Giter Club home page Giter Club logo

helix-shared's Introduction

Helix Shared

Shared libraries for Project Helix.

Status

NPM Version codecov GitHub Actions Workflow Status GitHub license GitHub issues Known Vulnerabilities

Helix Configuration Files

  • helix-fstab.yaml: maps paths to source URLs, use this to pull content from sources other than GitHub
  • helix-config.yaml: defines Strains (variants) of a Helix site, use this to create "environments", tests, or other variants
  • helix-query.yaml: define what can be indexed and queried in a Helix site
  • helix-markup.yaml: define what Markdown should generate which HTML, use this to tweak the HTML output

Usage

Using HelixConfig to read Helix configuration files

Helix is using YAML files for configuration management, but with the HelixConfig class, exported from @adobe/helix-shared, you can read, validate, and access configuration files with ease:

const { HelixConfig } = require('@adobe/helix-shared');

// in an async function
const configfromyaml = new HelixConfig()
  .withSource(yamlstring)
  .init();

const configfromjson = new HelixConfig()
  .withJSON(jsonobject)
  .init();

const configfromfile = new HelixConfig()
  .withDirectory('/path/to/dir') // the directory contains a `helix-config.yaml`
  .init();

Using sequence, functional, and op for functional programming

Development

Build

npm install

Test

npm test

Lint

npm run lint

helix-shared's People

Contributors

danrocha avatar dependabot[bot] avatar dlemstra avatar dominique-pfister avatar filmaj avatar greenkeeper[bot] avatar koraa avatar kptdobe avatar lgtm-com[bot] avatar marquiserosier avatar maxakuru avatar medusalix avatar ramboz avatar renovate-bot avatar renovate[bot] avatar rofe avatar semantic-release-bot avatar solaris007 avatar stefan-guggisberg avatar trieloff avatar tripodsan avatar

Stargazers

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

Watchers

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

helix-shared's Issues

GitUrl: Make `.git` suffix in urls optional but always use the API form for toString()

the .git suffix in the string URLs is a bit confusing. it stems from the fact, that git clone always uses a .git suffix:

https://www.git-scm.com/docs/git-clone#_git_urls_a_id_urls_a

and the url that github lets you copy-paste for the clone command, also has a .git suffix.
but the github API and UI never uses the .git suffix in the paths.

the helix-config.yaml requires .git suffix for string urls. in the object form, the repo property does not have a .git suffix. but toString() of the GitUrl always ensures the .git suffix.

potential changes:

  1. make .git suffix optional in strings, but always add it for toString().
  2. make .git suffix optional in strings, and always remove it for toString().
  3. make .git suffix optional in strings, and keep the same for toString() (roundtrip)

An in-range update of eslint-plugin-import is breaking the build 🚨

The devDependency eslint-plugin-import was updated from 2.16.0 to 2.17.0.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

eslint-plugin-import is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… codecov/project: No report found to compare against (Details).
  • βœ… codecov/patch: Coverage not affected. (Details).
  • ❌ smoke: * helix-smoke-tests/run - Failed
  • βœ… build: * build - Success

Commits

The new version differs by 61 commits.

  • 0499050 bump to v2.17.0
  • f479635 [webpack] v0.11.1
  • 8a4226d Merge pull request #1320 from bradzacher/export-ts-namespaces
  • 988e12b fix(export): Support typescript namespaces
  • 70c3679 [docs] make rule names consistent
  • 6ab25ea [Tests] skip a TS test in eslint < 4
  • 405900e [Tests] fix tests from #1319
  • 2098797 [fix] export: false positives for typescript type + value export
  • 70a59fe [fix] Fix overwriting of dynamic import() CallExpression
  • e4850df [ExportMap] fix condition for checking if block comment
  • 918567d [fix] namespace: add check for null ExportMap
  • 2d21c4c Merge pull request #1297 from echenley/ech/fix-isBuiltIn-local-aliases
  • 0ff1c83 [dev deps] lock typescript to ~, since it doesn’t follow semver
  • 40bf40a [*] [deps] update resolve
  • 28dd614 Merge pull request #1304 from bradennapier/feature/typescript-export-type

There are 61 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Conditions Language

Unify the expression of conditions so that:

  1. no VCL code has to be written
  2. we can reason to find out which condition is more specific (they should be evaluated first)
  3. we can aggregate and combine conditions.

Basic Boolean logic:

  • and
  • or
  • not

Property Matching:

  • url
    • hostname
    • path
  • referer
  • client_name
  • client_city
  • client_country_code
  • user_agent
  • accept_language
  • url_param.<name>

All property matching is using substring-starts, so only substring matches starting at index 0 are considered. More concise matching operations can be enabled through the suffixes: url= (strict match) and url~ (regex match)

Property Ranges:

  • client_lat>, client_lat<, client_lon>, client_lon<

Suggestion

  • Finalize the spec and write a grammar and JSON Schema
  • Implement a transformer that turns a condition config object into a Condition object with an AST
  • add methods1 to AST Nodes that evaluate a request object. (for helix-simluator)
  • add methods1 to AST Nodes that produce VCL code
  • expose condition via Strain.getCondition() and provide methods to evaluate objects and to produce VCL code.

1 Alternatively, use a visitor pattern.

Notes

We would have a new Condition class that adds following functions:

  • toFunction: creates a Javascript function that evaluates the condition against an express-style request object
  • toVCL: generates a VCL snippet

We can then further subdivide it into PropertyCondition and BooleanCondition. PropertyCondition simply has two properties: property and condition and two private mapping tables of property to JavaScript function and property to VCL string.

BooleanCondition has a list of children and an internal mapping table for the prefix, suffix, and infix (e.g. ! is a prefix, and && is an infix)


Appendix A

Support to calculate base-url

For conditions that select a strain based on URL, it is important to determine the common root path of the URL that matched the request. this base-url acts as chroot for resource processing.

Examples:

condition request (path) base-url (path)
url: https://www.adobe.com n/a ``
url: https://www.adobe.com/ n/a ``
url: https://www.adobe.com/api/docs n/a /api/docs
url~: https://www.adobe.com/[^/]+/docs /client/docs/index.html /client/docs

(the regexp support might be an advanced feature...)

So it might be better to return a ConditionResult from toFunction()(req) that contains some method to determine the base url. eg:

const res = strain.getCondition().match(req);
if (res) {
  const baseUrl = res.getBaseUrl();
  ...
}

for VCL, the condition should be able to produce a script that calculates the baseURL.

mandatory ref is not enforced in string git urls

Description
the schema mandates a ref in the code, content and static.url objects, but not in string alternatives. this should be consistently handled, and by adding a missing the ref to all strain giturls.

also see #82

An in-range update of eslint-plugin-import is breaking the build 🚨

The devDependency eslint-plugin-import was updated from 2.17.2 to 2.17.3.

🚨 View failing branch.

This version is covered by your current version range and after updating it in your project the build failed.

eslint-plugin-import is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • βœ… codecov/project: No report found to compare against (Details).
  • βœ… codecov/patch: Coverage not affected. (Details).
  • βœ… build: * build - Success
  • ❌ smoke: * helix-smoke-tests/run - Failed

Commits

The new version differs by 25 commits.

  • cf5573b Bump to v2.17.3
  • caae65c [Tests] eslint 2 does not have linter.version
  • 557a3e2 [Deps] update resolve
  • 17beb33 Merge pull request #1356 from christophercurrie/typescript-declare
  • c8ac7ff [Docs] Document env option for eslint-import-resolver-webpack
  • c09c0ce Issue #1258 (docs)
  • 753c9db [refactor] fix eslint 6 compat by fixing imports
  • b52bf3e PR feedback
  • 7aa13d1 PR feedback
  • f66e064 Remove log messages
  • d1e4455 Verbose variable names
  • 67b1e95 Support older typescript parsers
  • 288cedf Make groups non-capturing.
  • aa290bb Improve support for Typescript declare structures
  • 1edbbd0 [Fix] no-common-js: Also throw an error when assigning

There are 25 commits in total.

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

Add module usage introduction to README

Is your feature request related to a problem? Please describe.
I want to use this library to programmatically read the helix config, but I don't know where to start other than reading the source for the project.

Describe the solution you'd like
I would like a couple-liner node.js example in the README on how to use the library to read a helix config.

Strain.params does not exit

Strain.params is a whitelist of URL parameters. It works for Runtime and Proxy Strains. helix-shared does not have support for it right now.

Add ability to create a string transport logger for testing

Is your feature request related to a problem? Please describe.
for testing log output of the cli commands, it would we nice to have a string-only transport, so the test log files don't need to be read. this also would work around the flushing issue in winstonjs/winston#1504.

Describe the solution you'd like
when specifying /dev/text as logfile in Logger.getLogger(), a string based transport is created.
there should also be a way to retrieve the output, maybe by overriding the close() method so that:
const output = await log.close() returns the output.

Additional context

condition languages: rules treated as properties might lead to ugly trees

the current schema defines the condition values as properties:

"patternProperties": {

which would lead to ugly trees for alternatives:

conditions:
  or:
    url.hostname=: www.adobe.com
    or:
       url.hostname=: www.adobe.io
       or:
         url.hostname=: www.adobe.net

of course, it could be written in a regexp, so maybe this is not really a problem

conditions:
   url.hostname~: www.adobe.(com|io|net)

an alternative could be to define the or, and nodes as arrays:

conditions:
  - or:
     - url.hostname=: www.adobe.com
     - url.hostname=: www.adobe.io
     - url.hostname=: www.adobe.net

or maybe both should be possible?

Specify redirects for a strain

See adobe/helix-cli#587 (comment):

strains: 
  default: 
    redirects: 
      - 
        from: /old/
        to: /new/
      - 
        from: /old/(.*)
        to: /new/$1
  • add a new array property redirects
  • each array value has from and to properties
  • from is a path or regular expression
  • to is a regular expression replace pattern

Remove ref default "master" from GitURL schemas

The GitURL schemas defines a default value for the ref property. But the ref property is defined as required. This is somehow contradictory and misleading (if there is a default, this means you do not need to specify a value, the default will be used). The default value must be removed.

See:

deprecation warnings from yaml

[hlx] info: starting project
[hlx] info: Local Helix Dev server up and running: http://localhost:3000/
(node:99684) DeprecationWarning: The endpoint 'yaml/map' will be removed in a future release.
(node:99684) DeprecationWarning: The endpoint 'yaml/pair' will be removed in a future release.
(node:99684) DeprecationWarning: The endpoint 'yaml/seq' will be removed in a future release.

it would be good to get rid of those.

$ hlx --version
0.14.3

Add utilities for comparing dom trees

Unfortunately comparing dom trees while discarding insignificant whitespace changes is rather more complex than anticipated and there is no library that decently implements whitespace collapsing
for html trees.

Conditions Language: Specificity Rules

With #20 (conditions language) we might have a good shot at option 4 (which I think is preferred by @kptdobe): sort the strains from most specific condition to least specific condition.

CSS has some kind of specificity rules (https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity) and I think we could construct a partially ordered set on our conditions language, where we apply a set of rules to determine if two conditions are more or less specific, or not comparable or equal.

Rules:

Property Matches between different properties are never comparable

Example:

  • url_param.foo: bar is not comparable to url_param.bar: foo

For substring-starts matching, the longer substring is more specific than the shorter substring.

Examples:

  • url: https://www.project-helix.io/ is less specific than url: https://www.project-helix.io/docs/
  • url.path: /docs/README.md is more specific than url.path: /docs/
  • url.host: www.project-helix.io is not comparable to url.host: project-helix.io
  • user_agent: Lynx is equal to user_agent: Lynx

Two strict-match matches are always equal in specificity

Examples:

  • client_country_code=: DE is equal to client_country_code=: CH

Two regex-match matches are always equal in specificity

Note: We could (in theory) turn the Regular Expressions into two DFA graphs using https://github.com/hokein/automata.js/ and find out if one graph is a subgraph of the other, in which case it would be less specific.

Examples:

  • accept_language~: en is not comparable to accept_language~: en_US

A strict-match is more specific than a substring-starts match, if one contains the other

Examples:

  • url.path=: /docs/README.md is more specific than url.path: /docs/
  • url.path=: /docs/ is more specific than url.path: /docs/
  • url.path=: /docs/ is more specific than url.path: /docs/README.md

A strict-match is more specific than the regex-match it matches

Examples:

  • url.path=: /docs/ is more specific than url.path~: /docs/
  • url.path=: /docs/ is more specific than url.path~: ^/docs/$
  • url.path=: /docs/ is not comparable to url.path~: /frogs/

Property range matches are comparable

Examples:

  • client_lat>: 100 is more specific than client_lat>: 99

Two not expressions are comparable if their children are comparable

Examples:

not:
  url.path: /docs/

is comparable to

not:
  url:path: /docs/foo

but not to

not:
  url.path: /foo/docs

Two and or or expressions are comparable if children of one expression are a subset of children of the other expression

Note: this condition can potentially be loosened by taking into account the compatibility and specificity of pairs of children.

Example:

and:
  url.hostname: www.adobe.io
  url.path: /docs

and

and:
  url.hostname: www.adobe.io
  url.path: /docs
  client_country_code: DE

are comparable, but both aren't comparable to:

and:
  accept_language~: de
  client_country_code: DE

Of two comparable or expressions, the one with more children is less specific

or:
  url.hostname: www.adobe.io
  url.path: /docs

is more specific than

or:
  url.hostname: www.adobe.io
  url.path: /docs
  client_country_code: DE

Of two comparable and expressions, the one with more children is more specific

Example:

and:
  url.hostname: www.adobe.io
  url.path: /docs

is less specific than

and:
  url.hostname: www.adobe.io
  url.path: /docs
  client_country_code: DE

Of two comparable and and or expressions, the and expression is more specific

or:
  url.hostname: www.adobe.io
  url.path: /docs

is less specific than

and:
  url.hostname: www.adobe.io
  url.path: /docs

Originally posted by @trieloff in #71 (comment)

Implement new configuration design

see #12

  • create json schema for configuration (#25)
  • validate json during HelixConfig.parse()
  • remove old toplevel defaults
  • add tooling to create effective-helix-config.yaml (moved to #28)
  • add tooling to edit and write back the helix-config.yaml (moved to #30)
  • change helix-cli according to the changes (moved to adobe/helix-cli#449)
  • change helix-simulator according to the changes (moved to adobe/helix-simulator#121)

Configuration Format and Behavior

It looks like we need to have another discussion about our configuration format and how configuration behaves. What we have at the moment, looks like this:

  • users create a helix-config.yaml which will be loaded and denormalized into .hlx/strains.json
  • the helix-config.yaml contains a number of top-level (global) definitions and a map of strains
  • each defined strain takes default values from:
    • the global definitions
    • the command line options
    • the "default" strain
    • application defaults
    • (the exact precedence rules differ from property to property)

Our developer needs include:

  • the ability to start developing without any configuration file at all
  • the ability to quickly generate testable strains for code or content branches that are under development
  • the ability to quickly and conveniently switch between strains in simulator and production
  • the assurance that none of the above will break a published site
  • the ability to do all of the above in a fully automated fashion on a CI system (e.g. generate and deploy a new strain for a new branch)

Site administration needs also include:

  • the ability to define content mount points
  • the ability to pass through traffic to another CMS (proxy strains)

Furthermore, we should establish:

  • automated validation of configuration files that is independent from loading them
  • detailed and generated documentation for all configuration properties

Examples in CONFIGURATION.md are outdated

Is your feature request related to a problem? Please describe.
Examples in CONFIGURATION.md need to be reviewed and updated as necessary.

e.g.

definitions:
  strains:
    base: &basestrain
->      code: /acapt/default/https---github-com-adobe-project-helix-io-git--master--

Describe the solution you'd like
Examples in CONFIGURATION.md should be valid according to the current specification.

Static: emit events to notify Strain (and others) about changes

Is your feature request related to a problem? Please describe.
This is a follow up issue for adobe/helix-cli#496 (option 3)

Describe the solution you'd like
Strain has a member property of type Static and needs to be aware of deep changes therein so it can recalculate its YAML. Ideally, the Static instance would emit change events which the Strain then could react on.

Describe alternatives you've considered
Alternative solutions discussed in the issue above include calling "internal" methods (1) and deep setters (2), but none are as elegant as using events.

URLs and Sticky Strains not represented

In helix-cli a strain can have following properties:

  • url: a base URL for the strain, replaces condition
  • urls: a list of URLs (as strings) for hlx perf performance testing
  • sticky: a boolean indicating that a strain is sticky or non-sticky, i.e. should result in a cookie or not

None of this is represented in the Strain class.

Improve logging of errors

When an exception or error is passed to the log method, include the stack trace in the log format, if possible.

Remove strains "map" support

Code introduced by #71 does not fully support strains "map" (instead of strains "sequence") which was the previous way of defining the list of strains in the helix-config.yaml: if a ref of a GitURL is missing, the schema validation rejects the config, which was not the case before.
A migration (transform "map" to "sequence") is then required. Thus no need to keep the code that was supposed to still support the legacy version. It must be removed.

toJson() / fromJson() not symmetric in respect to strain order

Description
the order of properties is not guaranteed to be stable in objects, nor in the JSON serialization. this causes the order of strains to be undeterministic. Since the condition matching relies on the order, it is important to keep it stable.

To Reproduce
not so easy, since the object hash is mostly stable.

Version:

$ hlx --version
0.13.11-pre.9

use isomorphic-git to fetch origin, branch, etc instead of shell-js

Is your feature request related to a problem? Please describe.
GitUtils uses shell-js to execute git commands to retrieve basic information like remote origin and current branch. this has certain drawbacks:

  • only operates on cwd. i.e. the function would need to change the cwd and restore it after executing
  • it relies on the existence of a git command
  • potentially slower than a native implementation
  • potential problems, if the git output changes

advantage:

  • no package dependency
  • git is very stable and robust, potential implementations might fail

Describe the solution you'd like
Use isomorphic-git (or similar). Since we currently only need a read-only operations, this might be overkill, as it comes with many dependencies. however, we use isomorphic-git also in git-server, so it would already be present in the cli.

Alternative

  • find different library
  • only use in helix-cli, so that helix-shared stays small

git information that is read during up, deploy, etc:

  • isDirty (git status --porcelain)
  • getBranch (git rev-parse --abbrev-ref HEAD)
  • getRepository (git config --get remote.origin.url)
  • getCurrentRevision (git rev-parse HEAD)

Support to calculate base-url

@trieloff @dominique-pfister I added an Appendix A to the original description. we might tackle this in a separate issue.

Originally posted by @tripodsan in #20 (comment)

Support to calculate base-url

For conditions that select a strain based on URL, it is important to determine the common root path of the URL that matched the request. this base-url acts as chroot for resource processing.

Examples:

condition request (path) base-url (path)
url: https://www.adobe.com n/a ``
url: https://www.adobe.com/ n/a ``
url: https://www.adobe.com/api/docs n/a /api/docs
url~: https://www.adobe.com/[^/]+/docs /client/docs/index.html /client/docs

(the regexp support might be an advanced feature...)

So it might be better to return a ConditionResult from toFunction()(req) that contains some method to determine the base url. eg:

const res = strain.getCondition().match(req);
if (res) {
  const baseUrl = res.getBaseUrl();
  ...
}

for VCL, the condition should be able to produce a script that calculates the baseURL.

modifying extended strain removes merge

when adding a property to a strain with merged properties,

  clone:
    <<: *basestrain
    url: https://www.test.com/
    code: https://github.com/adobe/helix-test.git#master

...the merge key gets lost:

  clone:
    url: https://www.test.com/
    code: https://github.com/adobe/helix-test.git#master
    package: bfbde5fbfbde5fbfbde5f

wrong default port for http

    const src = 'http://localhost/owner/repo.git#local_path';
    const original = new GitUrl(src);
    const result = new GitUrl(original);
    assert.equal(result.toString(), src);

fails with wrong port 443

yaml parser problems with comments

Description
apparently, the position of comments can confuse the yaml parser.
see https://github.com/adobe/developer.adobe.com/commit/3624692853fa66cd907cbbdc3b7268adbc1ec02c

To Reproduce
see commit above.

Additional Context
according to https://yaml.org/spec/1.2/spec.html#id2780069,

Outside scalar content, comments may appear on a line of their own, independent of the indentation level. Note that outside scalar content, a line containing only white space characters is taken to be a comment line.

/cc @filmaj

add tooling to create effective-helix-config.yaml

For deploy and publish, one should be sure what the effective configuration values are and where they originate from. the ideas is to create an effective-helix-config.yaml (or print one to stdout) that contains annotations (comments) that describe the source of a configuration value.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.