initial commit

This commit is contained in:
Geoff Doty 2021-01-01 18:21:54 -05:00
commit 6e69d8370e
14 changed files with 4325 additions and 0 deletions

34
.eslintrc.js Normal file
View File

@ -0,0 +1,34 @@
module.exports = {
"env": {
"browser": true,
"es6": true,
"node": true
},
"extends": "eslint:recommended",
"globals": {
"Atomics": "readonly",
"SharedArrayBuffer": "readonly"
},
"parserOptions": {
"ecmaVersion": 2017,
"sourceType": "module"
},
"rules": {
"no-console": [
"warn"
],
"indent": [
"error",
4,
{"SwitchCase": 1}
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
node_modules/

72
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,72 @@
# Contributing
So you want to contribute, nice. **Thank you**.
Bug reports and code and documentation patches are all welcome. You can help this project also by using the development version and by reporting any bugs you might encounter.
You may contribute in several ways like:
* Creating new features
* Fixing bugs
* Improving documentation and examples
* Translating any document here to your language
## Table of contents
* [Contributing](#contributing)
* [Developing](#developing)
* [Running tests](#running-tests)
* [Reporting a bug](#reporting-a-bug)
* [Request a feature](#request-a-feature)
* [Commit message](#commit-message)
* [Code style](#code-style)
## Developing
There is only one main source file in the project. It is the [/src/index.js](/src/index.js).
The [test/index.spec.js](test/index.spec.js) is for now the only unit test file in the project.
The `dist` includes the minified version of the source code.
## Running tests
Run unit tests using this command:
```bash
npm run test
```
## Reporting a bug
Use the [GitHub issue tracker](https://github.com/n2geoff/js-lib/issues) to report any bug you find.
Bugs description should include:
* How to reproduce the bug;
* Easy to understand title;
Would be nice to have some code showing how to reproduce the code, you may use [gist](https://gist.github.com) or [Codepen](https://codepen.io) for uploading your example code.
## Request a feature
Use the [GitHub issue tracker](https://github.com/n2geoff/js-lib/issues) to request a new feature.
Keep in mind, this is a pure javascript library
Feel free to port it to your favorite framework, such as [RiotJS](http://riotjs.com), Angular or VueJs in a new repository.
## Commit message
Commit messages should includes GitHub number reference and a imperative easy to understand sentence.
## Coding style
If it is supported in all major browers without transpiling, then please use those JavaScript language features in your code, with one caveat -- readablity is king.
Currently all ES5 and ES6/ES2015 are available.
This project is linted agaist [ESLint](https://eslint.org/) and the [`.eslintrc.js`](.eslintrc.js) is dead-simple, and all you need to followed.
Thank you for reading this.
Hey, **star** this *repo* and/or share it with your friends.

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright (c) 2021 Geoff Doty
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

113
README.md Normal file
View File

@ -0,0 +1,113 @@
# Anchor
> fasten your apps!
Tiny (1kb) utility library that creates a unique global application registry.
Useful for composing single-page-apps or developing a Micro-Frontend architecture
## API
Anchor(register = {}, [mix = []])
- `register` {Object} - initial object registry (optional)
- `mixin` {Array} - extend anchor directly (optional)
## Quick Start
`Anchor` is the superfood for your application entry file
```js
// app.js
import anchor from 'anchor.js';
let app = new Anchor();
app.register('version', '1.0.0');
app.register('log', console);
export app;
```
Now `app` can do
```js
// another.js
import app from 'app.js';
app.log.info('using app version', app.version); // using app version 1.0.0
```
You can also initialize `Anchor` with an object to front-load the registry instead of using `app.register()`
```js
let app = new Anchor({
'version': '1.0.0',
'log': console,
...
});
```
> TIP: Connect multiple spas together, on each spa use `app.register` to extend that spas functionality on its bootstrap file
The `Anchor mixin` option acts more like a *merge*, rather than a `registry` and is useful to `mixin` objects directly, for example:
```js
// app.js
import anchor from 'anchor.js';
import mitt from 'mitt.js'; // event library
let app = new Anchor({}, [mitt()]); // adds on, off, emit, all to app
```
`app` now has `on`, `off`, `emit`, and `all` event functions bolted on (unsafe), so you can do
```js
app.on('my-event', dostuff);
```
Of course we are only talking about not using a namespace vs not using a namespace. You can achieve the same thing with `app.register('events', mitt())` and it is safer, but a *tiny* bit more typing :)
```js
app.events.emit('my-event', " I'm your huckel berry");
```
> WARNING: `mixin` has no safe guards and will overwrite existing duplicate functionality
## Tests
npm test
> NOTE: requires `deno` to execute module-based client-side test runner
and lint via
npm run lint
## Support
Please open [an issue](https://github.com/n2geoff/anchor/issues/new) for support.
## Contributing
Anyone is welcome to contribute, however, if you decide to get involved, please take a moment to review the [guidelines](CONTRIBUTING.md), they're minimalistic;)
## License
[MIT](LICENSE) 2021 Geoff Doty

38
dist/anchor.js vendored Normal file
View File

@ -0,0 +1,38 @@
class Anchor {
constructor(fasten = {}, mixins = [], debug = false) {
this.namespace = `_${Math.random().toString(36).slice(-6)}_`.toUpperCase();
this.global = window || global;
return this.build(fasten, mixins, debug);
}
register(key, value) {
if (this.global[this.namespace] && !this.global[this.namespace][key]) {
return this.global[this.namespace][key] = value;
}
return false;
}
build(fasten, merges, debug) {
if (this.global[this.namespace]) {
return false;
}
this.global[this.namespace] = fasten;
merges.forEach((merge) => Object.assign(this.global[this.namespace], merge));
this.register('register', this.register);
if (!!debug) {
console.log('ANCHOR:FASTEN', this.namespace, this.global[this.namespace]);
}
return this.global[this.namespace];
}
}
export default Anchor;

1
dist/anchor.min.js vendored Normal file
View File

@ -0,0 +1 @@
class Anchor{constructor(s={},e=[],t=!1){return this.namespace=`_${Math.random().toString(36).slice(-6)}_`.toUpperCase(),this.global=window||global,this.build(s,e,t)}register(s,e){return!(!this.global[this.namespace]||this.global[this.namespace][s])&&(this.global[this.namespace][s]=e)}build(s,e,t){return!this.global[this.namespace]&&(this.global[this.namespace]=s,e.forEach(s=>Object.assign(this.global[this.namespace],s)),this.register("register",this.register),t&&console.log("ANCHOR:FASTEN",this.namespace,this.global[this.namespace]),this.global[this.namespace])}}export default Anchor;

47
dist/anchor.umd.js vendored Normal file
View File

@ -0,0 +1,47 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define('umd', factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.umd = factory());
}(this, (function () { 'use strict';
class Anchor {
constructor(fasten = {}, mixins = [], debug = false) {
this.namespace = `_${Math.random().toString(36).slice(-6)}_`.toUpperCase();
this.global = window || global;
return this.build(fasten, mixins, debug);
}
register(key, value) {
if (this.global[this.namespace] && !this.global[this.namespace][key]) {
return this.global[this.namespace][key] = value;
}
return false;
}
build(fasten, merges, debug) {
if (this.global[this.namespace]) {
return false;
}
this.global[this.namespace] = fasten;
merges.forEach((merge) => Object.assign(this.global[this.namespace], merge));
this.register('register', this.register);
if (!!debug) {
console.log('ANCHOR:FASTEN', this.namespace, this.global[this.namespace]);
}
return this.global[this.namespace];
}
}
return Anchor;
})));

1
dist/anchor.umd.min.js vendored Normal file
View File

@ -0,0 +1 @@
!function(e,s){"object"==typeof exports&&"undefined"!=typeof module?module.exports=s():"function"==typeof define&&define.amd?define("umd",s):(e="undefined"!=typeof globalThis?globalThis:e||self).umd=s()}(this,function(){"use strict";return class{constructor(e={},s=[],t=!1){return this.namespace=`_${Math.random().toString(36).slice(-6)}_`.toUpperCase(),this.global=window||global,this.build(e,s,t)}register(e,s){return!(!this.global[this.namespace]||this.global[this.namespace][e])&&(this.global[this.namespace][e]=s)}build(e,s,t){return!this.global[this.namespace]&&(this.global[this.namespace]=e,s.forEach(e=>Object.assign(this.global[this.namespace],e)),this.register("register",this.register),t&&console.log("ANCHOR:FASTEN",this.namespace,this.global[this.namespace]),this.global[this.namespace])}}});

25
gulpfile.js Normal file
View File

@ -0,0 +1,25 @@
const gulp = require("gulp");
const minify = require("gulp-minify");
const strip = require("gulp-strip-comments");
const rollup = require("gulp-rollup-2").rollup;
gulp.task("default", function build() {
return gulp.src("./src/*.js")
.pipe(rollup({
output: [
{
file: "anchor.js",
name: "es",
format: "es"
},
{
file: "anchor.umd.js",
name: "umd",
format: "umd"
},
]
}))
.pipe(strip({safe: true}))
.pipe(minify({ext: {min: ".min.js"}}))
.pipe(gulp.dest("dist"))
});

3870
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

30
package.json Normal file
View File

@ -0,0 +1,30 @@
{
"name": "anchor",
"version": "1.0.0",
"description": "tiny global application registry",
"main": "src/index.js",
"directories": {
"test": "test"
},
"scripts": {
"build": "npx gulp default",
"test": "npm run build && npm run lint && deno run test/index.spec.js",
"lint": "npx eslint src/index.js"
},
"keywords": [
"utility",
"micro-frontend",
"spa"
],
"author": "Geoff Doty",
"license": "MIT",
"dependencies": {
},
"devDependencies": {
"eslint": "^7.16.0",
"gulp": "^4.0.2",
"gulp-minify": "^3.1.0",
"gulp-rollup-2": "^1.2.1",
"gulp-strip-comments": "^2.5.2"
}
}

65
src/index.js Normal file
View File

@ -0,0 +1,65 @@
/* {Module} v{version} | MIT | https:// */
/**
* Tiny global application registry
*/
class Anchor {
constructor(fasten = {}, mixins = [], debug = false) {
// create a unique namespace to avoid collisions
this.namespace = `_${Math.random().toString(36).slice(-6)}_`.toUpperCase();
// find environments global object
this.global = window || global;
// builds anchor instance
return this.build(fasten, mixins, debug);
}
/**
* Register
*
* Helper to extend functionality without overriding existing
*
* @param {String} key
* @param {Any} value
*/
register(key, value) {
if (this.global[this.namespace] && !this.global[this.namespace][key]) {
return this.global[this.namespace][key] = value;
}
return false;
}
/**
* Builds the Application Anchor
*
* @param {Object} fasten
* @param {Array} merges
* @param {Boolean} debug
*/
build(fasten, merges, debug) {
if (this.global[this.namespace]) {
// already initialized
return false;
}
// add to global instance
this.global[this.namespace] = fasten;
// merge with global instance
merges.forEach((merge) => Object.assign(this.global[this.namespace], merge));
// app global utils
this.register('register', this.register);
if (debug) {
// eslint-disable-next-line
console.log('ANCHOR:FASTEN', this.namespace, this.global[this.namespace]);
}
return this.global[this.namespace];
}
}
export default Anchor;

9
test/index.spec.js Normal file
View File

@ -0,0 +1,9 @@
import test from "../node_modules/testit/dist/testit.js";
import Anchor from "../src/index.js";
test.it({
"achor class exists": function () {
test.assert(Anchor);
}
}).run();