Serverless offline CUSTOM: using external file AND internally added variables? - serverless-framework

I am having a weird problem where I need to use Serverless "custom:" variables read both from an external file and internally from the serverless.yml file.
Something like this:
custom: ${file(../config.yml)}
dynamodb:
stages:
-local
..except this doesn't work. (getting bad indendation of a mapping entry error)
I'm not sure if that's possible and how do you do. Please help :)
The reason is dynamodb local serverless plugin won't work if it's config is set in the exteranl file. But we use the external file config in our project and we don't wanna change that.
So I need to have the dynamodb config separate in the serverless.yml file just not sure the proper way to do it.
Please someone help :) Thanks

You will either have to put all your vars in the external file or import each var from the custom file one at the time as {file(../config.yml):foo}
However... you can also use js instead of yml/json and create a serverless.js file instead allowing you to build your file programically if you need more power. I have fairly complex needs for my stuff and have about 10 yml files for all different services. For my offline sls I need to add extra stuff, modify some other so I just read the yaml files using node, parse them into json and build what I need then just export that.
Here's an example of loading multiple configs and exporting a merged one:
import { readFileSync } from 'fs'
import yaml from 'yaml-cfn'
import merge from 'deepmerge'
const { yamlParse } = yaml
const root = './' // wherever the config reside
// List of yml to read
const files = [
'lambdas',
'databases',
'whatever'
]
// A function to load them all
const getConfigs = () =>
files.map((file) =>
yamlParse(readFileSync(resolve(root, `${file}.yml`), 'utf8'))
)
// A function to merge together - you would want to adjust this - this uses deepmerge package which has options
const mergeConfigs = (configs) => merge.all(configs)
// No load and merge into one
const combined = mergeConfigs(getConfigs())
// Do stuff... maybe add some vars just for offline for ex
// Export - sls will pick that up
export default combined

Related

How to build individual component chunks with Vite to load with defineAsyncComponent

I'm not sure this is even possible, but it looks like some of the moving parts are there.
GOAL:
Create a library of single file Vue 3 components that will compile into separate chunks using Vite, and be dynamically/async loaded at runtime. The app itself will load, then load up a directory of individually chunk'd elements to put in a toolbox, so afterward each element could be updated, and new ones could be added by putting new chunks in the same path.
So far, I can create the separate chunks within the vite.config as follows:
...
build: {
rollupOptions: {
output: {
...buildChunks()
}
}
}
...
The buildChunks function iterates over SFC files in the ./src/toolbox path and returns an object like...
{
'toolbox/comp1':['./src/toolbox/comp1.vue'],
'toolbox/comp2':['./src/toolbox/comp2.vue'],
'toolbox/comp3':['./src/toolbox/comp3.vue'],
...
}
This all works, but I'm not sure how to make that next leap where the server code dynamically loads all of those generated chunk files without explicitly listing them in code. Also, since the Vite build adds an ID in the file name (e.g. comp.59677d29.js) on each build, referencing the actual file name in the import can't be done explicitly.
So far what I've considered is using defineAsyncComponent(()=>import(url)) to each of the files, but I'd need to generate a list of those files to import...which could be done by building a manifest file at build time, I guess.
Any suggestions? Is there a better approach?

Why FileExtensionContentTypeProvider no work with .min.js extension?

I have some css&js files in my project and I used the BuildBundlerMinifier NuGet package to minify and obfuscate them.
For example, the app.js will minify and obfuscate into app.min.js in the same directory.
Now I want the user can access the app.min.js but can't access the app.js.
I do this for I don't want anybody else to access the source code of my js.
Although someone still can get its source code from the app.min.js while I don't want them to get it easily.
I tried to use FileExtensionContentTypeProvider in Configure of startup.cs to achieve this:
var provider = new Microsoft.AspNetCore.StaticFiles.FileExtensionContentTypeProvider();
provider.Mappings.Remove(".js");
provider.Mappings.Add(new KeyValuePair<string, string>(".min.js", "application/javascript"));
app.UseStaticFiles(new StaticFileOptions()
{
ContentTypeProvider=provider
});
However, after it runs I can access neither app.js nor app.min.js.
What's wrong with my code?
Thank you.
The FileExtensionContentTypeProvider is only meant to provide a mapping from file extension to the correct MIME type. In order to retrieve the file extension from a file name, it will do the following:
private static string? GetExtension(string path)
{
int index = path.LastIndexOf('.');
if (index < 0)
return null;
return path.Substring(index);
}
It will take the very last part of the extension. So with app.min.js, the reported file extension will still be .js and not .min.js, and as such the mapping for .js will be required.
Modifying the MIME type mapping in order to disallow certain file extensions is probably not the best strategy. It would be better to modify the underlying file provider itself to handle that.
Alternatively, if you want to prevent access to non-minified JavaScript files, you could also split the middleware to conditionally prevent serving static files for any request to a path that ends with .js that is not a .min.js:
app.UseWhen(ctx => !ctx.Request.Path.HasValue
|| !ctx.Request.Path.Value.EndsWith(".js")
|| ctx.Request.Path.Value.EndsWith(".min.js"), app2 =>
{
app2.UseStaticFiles();
});

Ways to import a JSON file in public folder in Vue-CLI

I want to import a JSON file to use it, I need it to modify it in the future so I put it in public folder not assets, When I refer to it like this import JSON from ../../public/Data.json it works but I don't think so after building project can be resolved because after building there is no public folder. So I tried this :
let addr = process.env.BASE_URL;
import JSON from `${addr}Data.json`;
But It throws an error : SyntaxError
I'm confused now which way is the best and is there another way ?
The assets in the public folder are copied as is to the root of the dist folder. In your code, you can reference it just as /Data.json (if your app is deployed at the root of the domain).
E.g
async someMethod() {
const baseUrl = process.env.BASE_URL;
const data = await this.someHttpClient.get(`${ baseUrl }/Data.json`);
}
If you want to import the JSON as you have tried, I suggest to put it somewhere in the src folder and import from there
E.g.
import data from '#/data/someData.json'
console.log(data);
I came across this because I was doing a stand alone SPA that I wanted to run with no DB and keep the config in a JSON file. The import statement above works great for a static conf file, but anything imported like that gets compiled with the build, so even though your someData.json will exist in the public folder you won't see any changes in your dist because it's actually reading a JS compiled file.
To get around this I:
Convert the JSON file into a simple JS variable in a conf.js file:
e.g.
var srcConf={'bGreatJSON':true};
In index.html, did
<script src='./conf.js'>
Now that the JS variable has been declared in my Vue component I can just look for the window.srcConf and assign it if it exists in mounted or created:
if(typeof window.srcConf!='undefined')
this.sConf=window.srcConf;
This also avoids the GET CORS issue that others posts I've seen runs into, even in the same directory I kept getting CORS violations trying to do an axios call to read the file.

How do I create a list of data based on actual twig files within project

I am creating an app via NPM using https://www.npmjs.com/package/grunt-twig-render. It essentially is twig.js. I'm keeping it slim, so right now there isn't any other php or anything like that. Just npm / twig.js and other npm packages, including Grunt.
Here's what I'm trying to do. Right now, I have a bunch of twig files within subfolders of a directory.
What I'd like to do is generate a list of data of the .twig files in that subdirectory. Something like this may work well
files: [
{
"name": "file1.twig"
"path": "/folder1"
},
{
"name": "file2.twig"
"path": "/folder1"
},
{
"name": "file3.twig"
"path": "/folder1"
}
]
But I'm not super picky. Just seeing if anyone has found a way to create a list of files within a folder via npm, or twigjs, or something similar.
If it generates a .json file, that would be ideal. This would be part of a build process, so doing that via Grunt would work well too.
Thank you in advance
You can register a custom grunt task in your Gruntfile.js which utilizes the shelljs find method to retrieve the path of each .twig file.
shelljs is a package which provides portable Unix shell commands for Node.js. It's find method is analogous to the Bash find command.
The following steps describe how to achieve your requriement:
cd to your project directory and install shelljs by running:
npm i -D shelljs
Configure your Gruntfile.js as follows:
Gruntfile.js
module.exports = function(grunt) {
// requirements
var path = require('path'),
find = require('shelljs').find;
grunt.initConfig({
// other tasks ...
});
/**
* Custom grunt task generates a list of .twig files in a directory
* and saves the results as .json file.
*/
grunt.registerTask('twigList', 'Creates list of twig files', function() {
var obj = {};
obj.files = find('path/to/directory')
.filter(function(filePath) {
return filePath.match(/\.twig$/);
})
.map(function(filePath) {
return {
name: path.basename(filePath),
path: path.dirname(filePath)
}
});
grunt.file.write('twig-list.json', JSON.stringify(obj, null, 2));
});
grunt.registerTask('default', ['twigList']);
};
Explanation
Both shelljs and nodes built-in path module are required into Gruntfile.js.
Next a custom task named twigList is registered.
In the body of the function we initialize an empty object and assign it to a variable named obj.
Next, the shelljs find method is invoked passing in a path to the subdirectory containing the .twig files. Currently the path is set to path/to/directory so you'll need to redefine this path as necessary.
Note: The find method can also accept an array of multiple directory paths as an argument. For example:
find(['path/to/directory', 'path/to/another/directory'])
The find method returns an Array of all paths found inside the given directory, (many levels deep). We utilize the Array's filter() method to return only filepaths with a .twig file extension by providing a regex (\.twig$) to the Strings match method.
Each item of the resultant Array of .twig filepaths is passed to the Array's map() method. It returns an Object with two properties (name and path). The value for the name property is obtained from the full filepath using nodes path.basename() method. Similarly, the value for the path property is obtained from the full filepath using nodes path.dirname() method.
Finally the grunt file.write() method is utilized to write a .json file to disk. Currently the first argument is set to twig-list.json. This will result in a file named twig-list.json being saved to the top-level of your project directory where Gruntfile.js resides. You'll need to redefine this output path as necessary. The second argument is provided by utilizing JSON.stringify() to convert obj to JSON. The resultant JSON is indented by two spaces.
Additional info
As previously mentioned the shelljs find method lists all files (many levels deeep) in the given directory path. If the directory path provided includes a subfolder(s) containing .twig files that you want to exclude you can do something like the following in the filter() method:
.filter(function(file) {
return filePath.match(/\.twig$/) && !filePath.match(/^foo\/bar/);
})
This will match all .twig files, and ignore those in the sub directory foo/bar of the given directory, e.g. path/to/directory.

Coffeescript Common files module

I have a few common files like logger, stopwatch, metrics, etc. Now, I would like to add all of them in 1 common.coffee and place this files in a common folder under lib.
lib/common/logger.coffee
lib/common/metrics.coffee
lib/common/stopwatch.coffee
lib/common.coffee
Now, when I have to use these files. I just do a
require( 'lib/common' )
and should be able to call the logger class
like logger.info, etc in the lib files.
How to go about doing it ? Below is the common.coffee but it requires me to say "Common.logger" whenever I have to use it. I dont want the Common prefix
nconf = require('nconf')
environment = process.env.NODE_ENV || 'development'
nconf.file 'environment', "config/#{environment}.json"
nconf.file 'default', 'config/default.json'
module.exports = {
logger: require('lib/common/logger')
metrics: require('lib/common/metrics') nconf
stopwatch: require('lib/common/stop_watch')
}
Also, how can I make a module of the common folder so that I can just use npm to install it.
You could use destructuring assignments on your require call.
{logger, metrics, stopwatch} = require("lib/common")
another way would be to use a build tool like grunt.js and call a concatination task before building the final deployment articfact.