enabling classProperties for #babel/plugin-proposal-class-properties in symfony - reactjs

I keep getting this Support for the experimental syntax 'classProperties' isn't currently enabled when I apply a write a function for my react app. For context, I am playing around with Symfony as a backend while using React as a frontend.
From this, it says I need to enable 'loose':true for #babel/plugin-proposal-class-properties in symfony in plugins. However, I can't find the .babelrc file in my root folder.
My webpack.config.js file:
var Encore = require('#symfony/webpack-encore');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
// enables #babel/preset-env polyfills
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment to get integrity="..." attributes on your script & link tags
// requires WebpackEncoreBundle 1.4 or higher
//.enableIntegrityHashes(Encore.isProduction())
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
// uncomment if you use API Platform Admin (composer req api-admin)
.enableReactPreset()
//.addEntry('admin', './assets/js/admin.js')
;
module.exports = Encore.getWebpackConfig();
After some reading, I found that I can edit it using config using configureBabel but I'm unsure how to do so.
Given that I don't have an .babelrc file, how do I enable the class properties using the method?
Any insight would be much appreciated. Thanks for reading.

I'm dumb and should've played more with it.
It is just as the article mentions, use .configureBabel to enable the plugin.
So now my webpack is the same but with this addition after configureBabelPresetEnv() add:
.configureBabel((config)=>{
config.plugins.push('#babel/plugin-proposal-class-properties');
})
So the new webpack.config.js file now looks like:
var Encore = require('#symfony/webpack-encore');
// Manually configure the runtime environment if not already configured yet by the "encore" command.
// It's useful when you use tools that rely on webpack.config.js file.
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev');
}
Encore
// directory where compiled assets will be stored
.setOutputPath('public/build/')
// public path used by the web server to access the output path
.setPublicPath('/build')
// only needed for CDN's or sub-directory deploy
//.setManifestKeyPrefix('build/')
/*
* ENTRY CONFIG
*
* Add 1 entry for each "page" of your app
* (including one that's included on every page - e.g. "app")
*
* Each entry will result in one JavaScript file (e.g. app.js)
* and one CSS file (e.g. app.css) if your JavaScript imports CSS.
*/
.addEntry('app', './assets/js/app.js')
//.addEntry('page1', './assets/js/page1.js')
//.addEntry('page2', './assets/js/page2.js')
// When enabled, Webpack "splits" your files into smaller pieces for greater optimization.
.splitEntryChunks()
// will require an extra script tag for runtime.js
// but, you probably want this, unless you're building a single-page app
.enableSingleRuntimeChunk()
/*
* FEATURE CONFIG
*
* Enable & configure other features below. For a full
* list of features, see:
* https://symfony.com/doc/current/frontend.html#adding-more-features
*/
.cleanupOutputBeforeBuild()
.enableBuildNotifications()
.enableSourceMaps(!Encore.isProduction())
// enables hashed filenames (e.g. app.abc123.css)
.enableVersioning(Encore.isProduction())
// enables #babel/preset-env polyfills
.configureBabelPresetEnv((config) => {
config.useBuiltIns = 'usage';
config.corejs = 3;
})
.configureBabel((config)=>{
config.plugins.push('#babel/plugin-proposal-class-properties');
})
// enables Sass/SCSS support
//.enableSassLoader()
// uncomment if you use TypeScript
//.enableTypeScriptLoader()
// uncomment to get integrity="..." attributes on your script & link tags
// requires WebpackEncoreBundle 1.4 or higher
//.enableIntegrityHashes(Encore.isProduction())
// uncomment if you're having problems with a jQuery plugin
//.autoProvidejQuery()
// uncomment if you use API Platform Admin (composer req api-admin)
.enableReactPreset()
//.addEntry('admin', './assets/js/admin.js')
;
module.exports = Encore.getWebpackConfig();

Related

React component inside Angular app: import scss files

I'm trying to understand how to customize the Angular CLI build process to be able to have React components properly built when they import scss files.
I'm currently able to build an Angular project where some React components are used. There's a lot of material out there that explains how to achieve it (it's pretty simple actually).
I still haven't found an article that points out how to have scss file imports properly resolved in .tsx files though.
For example, if I have this simple React component:
import * as styles from "./styles.scss";
const ReactComponentWithBrokenStyles = () => (
<div className={styles.root}>This div won't have a class</div>
);
export default ReactComponentWithBrokenStyles;
how can I edit the Angular CLI build process to properly add the loaders that would transform the .scss file?
I've found some resources pointing me to using a custom builder instead of the standard builder, which would allow me to provide an extra webpack config file. What I don't understand is how to write the loaders in that file to solve my problem.
The default Angular CLI webpack config already has a loader for .scss files, which need to be transformed and referenced by Angular components, and I don't want to override that... so how can I add a loader just for .scss files that are imported in .tsx files? Is there a way to tell webpack to match files based on siblings in addition to the usual regex?
I guess this is exquisitely a webpack question after all.
Note: using Angular CLI v7 and webpack 4.
The real problem was: I need to distinguish Angular .scss files from React .scss files.
The solution I came up with is centered around using oneOf in Webpack's rule configuration for .scss files, which allows discriminating between files that pass the same test (/\.scss|\.sass$/) in a more fine grained way.
So I've used #angular-builders/custom-webpack as suggested by the link I posted in the question, and I've created this customizer for the standard Angular CLI Webpack configuration:
const reactScssFilesLoaders = [
"style-loader",
{
loader: "css-loader",
options: {
discardDuplicates: true,
importLoaders: 1,
modules: true,
localIdentName: "[name]__[local]___[hash:base64:5]",
},
},
"postcss-loader",
"sass-loader"
];
/**
* Modifies the default Webpack config so that our React components are able to
* import styles from scss files as JS objects
* #param {*} defaultAngularConfig The default Webpack config that comes with the NG Cli
* #param {*} buildOptions The build options (not needed here)
* #returns The adjusted Webpack config
*/
function customizeWebpackConfig(defaultAngularConfig, buildOptions) {
const builtInNgScssFilesRule = defaultAngularConfig.module.rules.find(r => r.test.source.includes("scss"));
if (!builtInNgScssFilesRule) {
throw new Error("WTF?");
}
const angularScssFilesLoaders = builtInNgScssFilesRule.use;
// We only want one top level rule for .scss files, so we need to further test
// We want to leave normal Angular style files to the default loaders, and
// we just want to turn styles into JS code when imported by tsx components
builtInNgScssFilesRule.oneOf = [{
issuer: /\.(tsx)$/,
use: reactScssFilesLoaders
}, {
test: /\.(component)\.(scss)$/,
use: angularScssFilesLoaders
}]
delete builtInNgScssFilesRule.exclude;
delete builtInNgScssFilesRule.use;
return defaultAngularConfig;
}
module.exports = customizeWebpackConfig;
Works like a charm.

How do I exclude files from svelte-kit build?

If I run npm run build with SvelteKit it seems to include all files from the src folder. Is it possible to exclude a certain file type (eg. *test.js)?
Example
Select demo app with npm init svelte#next my-app
Add the following code to src/routes/todos/foo.test.js
describe('foo', () => {
it('temp', () => {
expect(true).toBe(false)
})
})
npm run build
npm run preview
Result: describe is not defined
Workaround
Move tests outside of src
UPDATE: SvelteKit 1.0.0-beta now requires pages/endpoints to follow a specific naming pattern, so explicit file exclusion should no longer be needed.
SvelteKit specially handles files in the routes/ directory with the following filenames (note the leading + in each filename):
+page.svelte
+page.js
+page.server.js
+error.js
+layout.svelte
+layout.js
+layout.server.js
+server.js
All other files are ignored and can be colocated in the routes/ directory.
If, for some reason, you need to have a file that has a special name shown above, it's currently not possible to exclude that file from special processing.
Original outdated answer:
SvelteKit 1.0.0-beta supports a routes configuration that enables file exclusion from the src/routes directory. The config value is a function that receives a file path as an argument, and returns true to use the file as a route.
For example, the following routes config excludes *.test.js files from routes:
// sveltekit.config.js
⋮
const config = {
kit: {
⋮
routes: filepath => {
return ![
// exclude *test.js files
/\.test\.js$/,
// original default config
/(?:(?:^_|\/_)|(?:^\.|\/\.)(?!well-known))/,
].some(regex => regex.test(filepath))
},
},
}
demo

Stop watching folder changes in reactjs

i'm working on a react project where user can uploads files,and the problem that i'am facing is when i upload a file to the server and save that file into folder called uploads which lives in the public folder,then when this process finished the page refreshed that's because the app watching for any changes and refresh the page
and i know that i can stop this by edit the webpackdevserver.config File but i don't know how to do that.
webpackdevserver.config:
// #remove-on-eject-begin
/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
// #remove-on-eject-end
'use strict';
const fs = require('fs');
const errorOverlayMiddleware = require('react-dev-utils/errorOverlayMiddleware');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
const paths = require('./paths');
const getHttpsConfig = require('./getHttpsConfig');
const host = process.env.HOST || '0.0.0.0';
const sockHost = process.env.WDS_SOCKET_HOST;
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/sockjs-node'
const sockPort = process.env.WDS_SOCKET_PORT;
module.exports = function(proxy, allowedHost) {
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
// https://github.com/webpack/webpack-dev-server/issues/887
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
// However, it made several existing use cases such as development in cloud
// environment or subdomains in development significantly more complicated:
// https://github.com/facebook/create-react-app/issues/2271
// https://github.com/facebook/create-react-app/issues/2233
// While we're investigating better solutions, for now we will take a
// compromise. Since our WDS configuration only serves files in the `public`
// folder we won't consider accessing them a vulnerability. However, if you
// use the `proxy` feature, it gets more dangerous because it can expose
// remote code execution vulnerabilities in backends like Django and Rails.
// So we will disable the host check normally, but enable it if you have
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
disableHostCheck:
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true',
// Enable gzip compression of generated files.
compress: true,
// Silence WebpackDevServer's own logs since they're generally not useful.
// It will still show compile warnings and errors with this setting.
clientLogLevel: 'none',
// By default WebpackDevServer serves physical files from current directory
// in addition to all the virtual build products that it serves from memory.
// This is confusing because those files won’t automatically be available in
// production build folder unless we copy them. However, copying the whole
// project directory is dangerous because we may expose sensitive files.
// Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder.
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
// Note that we only recommend to use `public` folder as an escape hatch
// for files like `favicon.ico`, `manifest.json`, and libraries that are
// for some reason broken when imported through webpack. If you just want to
// use an image, put it in `src` and `import` it from JavaScript instead.
contentBase: paths.appPublic,
contentBasePublicPath: paths.publicUrlOrPath,
// By default files from `contentBase` will not trigger a page reload.
watchContentBase: true,
// Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint
// for the WebpackDevServer client so it can learn when the files were
// updated. The WebpackDevServer client is included as an entry point
// in the webpack development configuration. Note that only changes
// to CSS are currently hot reloaded. JS changes will refresh the browser.
hot: true,
// Use 'ws' instead of 'sockjs-node' on server since we're using native
// websockets in `webpackHotDevClient`.
transportMode: 'ws',
// Prevent a WS client from getting injected as we're already including
// `webpackHotDevClient`.
injectClient: false,
// Enable custom sockjs pathname for websocket connection to hot reloading server.
// Enable custom sockjs hostname, pathname and port for websocket connection
// to hot reloading server.
sockHost,
sockPath,
sockPort,
// It is important to tell WebpackDevServer to use the same "publicPath" path as
// we specified in the webpack config. When homepage is '.', default to serving
// from the root.
// remove last slash so user can land on `/test` instead of `/test/`
publicPath: paths.publicUrlOrPath.slice(0, -1),
// WebpackDevServer is noisy by default so we emit custom message instead
// by listening to the compiler events with `compiler.hooks[...].tap` calls above.
quiet: true,
// Reportedly, this avoids CPU overload on some systems.
// https://github.com/facebook/create-react-app/issues/293
// src/node_modules is not ignored to support absolute imports
// https://github.com/facebook/create-react-app/issues/1065
watchOptions: {
ignored: ignoredFiles(paths.appSrc),
},
https: getHttpsConfig(),
host,
overlay: false,
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebook/create-react-app/issues/387.
disableDotRule: true,
index: paths.publicUrlOrPath,
},
public: allowedHost,
// `proxy` is run between `before` and `after` `webpack-dev-server` hooks
proxy,
before(app, server) {
// Keep `evalSourceMapMiddleware` and `errorOverlayMiddleware`
// middlewares before `redirectServedPath` otherwise will not have any effect
// This lets us fetch source contents from webpack for the error overlay
app.use(evalSourceMapMiddleware(server));
// This lets us open files from the runtime error overlay.
app.use(errorOverlayMiddleware());
if (fs.existsSync(paths.proxySetup)) {
// This registers user provided middleware for proxy reasons
require(paths.proxySetup)(app);
}
},
after(app) {
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
app.use(redirectServedPath(paths.publicUrlOrPath));
// This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if
// it used the same host and port.
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
},
};
};
and here where is store the files uploaded:
structureAPP
So my question is Like so:
How do i can edit webpackdevserver.config File to stop watching uploads File ?
i have been searching for this problem for two days and didn't fix it.
thanks in advance.
watchOptions: {
ignored: ignoredFiles(paths.appSrc),
},
This is indeed where ignored path are listed but ignoredFiles(paths.appSrc) is not the src folder. If you look higher you see ignoredFiles.js comes from the react-dev-utils module.
const ignoredFiles = require('react-dev-utils/ignoredFiles');
With react create app, the default ignoredFiles.js returns the node_modules folder which speeds up things by avoiding the watcher to go through all modules. Now it is possible to add more folders as watchOptions.ignored accepts an array So you can add your uploads path directly in the watchOptions.
watchOptions: {
ignored: [ignoredFiles(paths.appSrc), yourUploadPath],
},

Codemirror - Module parse failed: Unexpected token

I am using react-codemirror2. I used npx create-react-app appname to create my app.
But when I try to run the development server it gives me the following error -
./node_modules/codemirror/mode/rpm/changes/index.html 1:0
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
> <!doctype html>
|
| <title>CodeMirror: RPM changes mode</title>
One solution suggested to change the modulesDirectories. I tried doing so using npm run eject. But wasn't successful at doing it.
Please help me with the same
Go to solutions section if you are in a hurry.
The why
The reason for this error is the way bundling dynamic imports works in webpack. Imports go by providing a starting part of a path and you may refine that through an end part that holds a path that precise an extension.
Ex:
import(`codemirror/mode/${snippetMode}/${snippetMode}`)
ref: https://webpack.js.org/api/module-methods/#dynamic-expressions-in-import
Such an import is processed by webpack through the following regex ^\.\/.*$. That we can see in the error message:
| <title>CodeMirror: RPM changes mode</title>
# ./node_modules/codemirror/mode/ sync ^\.\/.*$ ./rpm/changes/index.html
And that's basically to determine the possible modules. And bundle them as chunks for code splitting.
Because of that open matching regex. So all files of all types (extensions) are matched. Then depending on the extension. The correct loader would be used. If we had the html-loader setup and configured through a rule. That wouldn't fail. As the loader will handle that module (webpack module [html]). Even though that can be an option to handle the problem. It wouldn't be the right thing to do. As it would create an extra bundle for the module. And also some entries for it. In the main bundle.
Dynamic Imports types and there resolution
All types get code splitted (chunks created for them for code splitting). Except for the last one.
Absolute full path. (static) ==> Imported dynamically and code splitted.Ex:
import('codemirror/mode/xml/xml')
The exact path and module will be resolved and a chunk for it will be created.
Dynamic path with a starting path.
Ex:
import(`codemirror/mode/${snippetMode}/${snippetMode}`)
All paths with this regex codemirror\/mode\/.*$ are matched.
Dynamic path with a starting path and an ending path with extension as well.ex:
import(`./locale/${language}.json`)
All paths with the following regex would be matched ./locale/.*\.json which limit it to .json extension module only.
Full variable import.Ex:
import(someVar)
Doesn't create code splitting at all. Neither tries to match. Because it can match just quite anything in the project. Even if the variable is set to a path someVar = 'some/static/path'. It wouldn't check and resolve the variable association.
The solutions
No electron or electron.
module.noParse
module: {
noParse: /codemirror\/.*\.html$/,
rules: [
// ...
noParse tell webpack to not parse the matched files. So it both allows us to exclude files and boost the performance. It works all great. And can be one of the best solutions as well. You can use a regex. Or a function.
ref: https://webpack.js.org/configuration/module/#module-noparse
Don't use the import('some/path' + dynamicEl) format and use instead
const dynamicPath = 'some/path' + dynamicEl
import(dynamicPath) // That would work just ok
Use magic comments [wepackExclude or wepackInclude] with import (if electron and using require => convert require to import + magic comment). Magic comments don't work with require but only import.
ex:
import(
/* webpackExclude: /\.html$/ */
`codemirror/mode/${snippetMode}/${snippetMode}`
)
or even better
import(
/* webpackInclude: /(\.js|\.jsx)$/ */
`codemirror/mode/${snippetMode}/${snippetMode}`
)
Include allows us to make sure we are targeting exactly what we want to target. Excluding HTML. May still create chunks for some other files that are not .js. It's all relative to what we want. If you want to include only a specific extension. An include is better. Otherwise, if we don't know. And some other extension would be required. Then an exclude is better.
ref: https://webpack.js.org/api/module-methods/#magic-comments
Magic comments examples and usage:
// Single target
import(
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackExports: ["default", "named"] */
'module'
);
// Multiple possible targets
import(
/* webpackInclude: /\.json$/ */
/* webpackExclude: /\.noimport\.json$/ */
/* webpackChunkName: "my-chunk-name" */
/* webpackMode: "lazy" */
/* webpackPrefetch: true */
/* webpackPreload: true */
`./locale/${language}`
);
And to fully ignore code splitting
import(/* webpackIgnore: true */ 'ignored-module.js');
If nodejs or electron and the import should be processed as commonjs require. Use the externals config property like in the example bellow:
externals: {
'codemirror': 'commonjs codemirror'
}
which works like this. Webpack for any import with codemirror (left part). convert it to the commonjs import without bundling it (right part).
import(`codemirror/mode/${snippetMode}/${snippetMode}`)
will be converted to:
require(`codemirror/mode/${snippetMode}/${snippetMode}`)
instead of bundled.
extenals doc ref: https://webpack.js.org/configuration/externals/#externals
If electron. And the feature should not be bundled. use window.require for all nodejs electron API calls (Otherwise set it on entry file window.require = require). And use it instead.
Its electron, nodejs ==> Webpack stay the hell out of this
The doctype declaration is incorrect, it should have been:
<!DOCTYPE html>
Notice DOCTYPE should be in caps.

Dynamically Loading Plugin Configuration Files in CakePHP 3

Question: How do I load a configuration file from a Plugin/config Directory?
Demo Project: https://github.com/CakePHPKitchen/CakeDC-Users-Permissions-Example
I am using CakeDC/users plugin and it has a permissions.php file that it loads the RBAC permissions from. From what I can tell, it either loads the default permissions file that is in the user plugin's config folder OR it loads the permissions.php file from the app/config folder.
Now for my app skeleton I have a bunch of permissions in the app/config/permissions.php, however, I do not want to modify that file as I will be doing git pulls from the upstream repo and I would like to avoid conflicts.
So what I would like to do is, in the app skeleton bootstrap
I would like to
foreach(Plugin::loaded() as $plugin) {
$path = Plugin::path($plugin) . 'config/permissions.php';
if(file_exists($path)) {
Configure::load($path, 'default', true);
}
}
But I am getting the following error....
Error: The application is trying to load a file from the /Users/jlroberts/Projects/JeffreyLRobertsCom/CakePHPKitchen/PluginDemos/plugins/SharpAgent/config/permissions plugin.
Make sure your plugin /Users/jlroberts/Projects/JeffreyLRobertsCom/CakePHPKitchen/PluginDemos/plugins/SharpAgent/config/permissions is in the /Users/jlroberts/Projects/JeffreyLRobertsCom/CakePHPKitchen/PluginDemos/plugins/ directory and was loaded.
Any ideas on how I can load the permissions.php file from the Plugin/config directory?
EDITED: You can load permissions.php file from the Plugin as it is doing now, but change the contents of permissions.php to preserve existing permissions defined in configuration, for example:
config/permissions.php
$permissions = [
// add your app permissions here
[
// ...
],
];
// there are more permissions in this config key, defined across your plugins
$morePermissions = \Cake\Core\Configure::read('MyPermissions');
$allPerms = array_merge($permissions, $morePermissions);
return ['CakeDC/Auth.permissions' => $allPerms];
Then inside each plugin you could have:
YOUR_PLUGIN/config/bootstrap.php
$permissions = \Cake\Core\Configure::read('MyPermissions');
$someMorePermissions = [
[
// permissions injected into the app from this plugin
]
];
$permissions = array_merge((array)$permissions, $someMorePermissions);
\Cake\Core\Configure::write('MyPermissions', $permissions);
Allowing each plugin to dynamically inject/manage permissions into the app.
I've created a c9.io environment with this code here https://ide.c9.io/steinkel/users-35-custom-permissions

Resources