Location of Mirage files in ember addon - node.js

I have an Ember addon which is supposed to handle a request to return some data. The main app needs to use this addon, so that requests to retrieve this data are retrieved from mirage. At some point in the future this needs to be disabled in live environments (but not for the time being)
My question is where the mirage directory (and its subdirectories such as factories, fixtures, models, routes etc) should be located in an addon. Should it be in the project root or elsewhere, such as in the app or addon subdirectory?
I have run:
ember install ember-cli-mirage
which creates some files in \tests\dummy\mirage
Creating the files in this directory doesn't seem to work:
/tests/dummy/fixtures/mydata.js
export default [{
"title": "Some data here"
}]
/tests/dummy/routes/mydata.js
class MyDataRoutes {
constructor(routerFnc, route, db) {
routerFnc(route + '/', ({db}) => {
return db.mydata;
});
}
}
export default MyDataRoutes;
/tests/mirage/config.js:
export default function() {
// this.urlPrefix = ''; // make this `http://localhost:8080`, for example, if your API is on a different server
this.namespace = 'api'; // make this `api`, for example, if your API is namespaced
this.timing = 100; // delay for each request, automatically set to 0 during testing
new MyDataRoutes(this.get, '/content/mydata', this.db);
}

This is the right place.
You will then be able to use your mirage endpoints either in your tests or in the dummy app directly.
If you want an example of how that would all work together, you can have a look at the repo for ember-power-select https://github.com/cibernox/ember-power-select. They have mirage as well as nice tests in place.

Related

How to use node:fs inside of a vue app to save images into source directory

I'm building a personal portfolio website using Vue.js, and I'm attempting to build a form to allow me to add to my portfolio later. I'm storing the text data in firebase, but I also want to be able to upload and access pictures. I'm attempting to upload through a form and save with node:fs with the following
import { writeFile } from 'node:fs'
export function saveImages (data:FileList, toDoc: string) {
const reader = new FileReader()
const imageNames = []
console.log(toDoc)
for (let i = 0; i < data.length; i++) {
imageNames.push(toDoc + '/' + data[i].name)
reader.readAsBinaryString(data[i])
reader.onloadend = function (e) {
if (e.target?.readyState === FileReader.DONE) {
const imageFile = e.target.result as string
if (imageFile) {
writeFile('./assets/' + data[i].name, imageFile, 'binary', (err) =>
console.log('was unable to save file ' + data[i].name + ' => ' + err)
)
}
}
}
}
return imageNames
}
When I attempt to call saveImages, I get the error
ERROR in node:fs
Module build failed: UnhandledSchemeError: Reading from "node:fs" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "node:" URIs.
As pointed out by the comments on your answer, the Node.js-fs-module is cannot be used in the frontend. Here is why:
While developing your vue.js-app, you should remember that you always have to run a development server in order for the app to compile to a browser-readable format. The resulting page will not be delivered as some .vue-files and .js-files but everything will be bundled into an html-file and some additional .js-files.
While running the development server, the source directory of your app is 'lying' on a server, but this is not even the directory that is delivered to the browser.
In a production server, there will be static assets built out for your vue.js-app, which does also only contain .html- and .js-files.
When a client (browser) accesses a route, some static files will be delivered to the browser, and all the code you are writing in your .vue-files will be run on the client's machine, not on a server. So you cannot interact with server-side directories.
Therefore, you should look into a backend server framework, which you can connect to your frontend to allow users to upload files to a server, and those files would be saved on the server. You will then set up your vue app to communicate with the backend. Here are some additional resources:
Node modules with vue: StackOverflow
Express.js: popular backend framework for Node.js
Express.js: Deliver files
Blog article on Express.js file upload (Attacomsian)
You might also want to take a look on how to send static files with express, because once the files are uploaded and the server receives them, it could store them into a static-directory, where you could access them without having to use separate API-routes.

How to integrate swagger with restify framwork in node

I implemented a project for test purpose with restify framework in node and implemented a GET API.
But I don't know how to integrate a swagger with restify framework.
There are many blogs for integration swagger with express..
I followed a link like
https://www.npmjs.com/package/restify-swagger-jsdoc
https://github.com/bvanderlaan/swagger-ui-restify
Please help me how to integrate.
For everyone who's come this far, as well as me, I assume you're using restify instead of express and haven't found an easy answer yet. I have an API server using restify, use typescript to program and convert the files to javascript before running my server, all in a Docker container. After a lot of searching I managed to solve my problem as follows:
Install the "swagger-autogen" package.
Create a file called "swagger.ts" with the following commands:
const swaggerAutogen = require('swagger-autogen')()
const outputFile = '../swagger_output.json'
const endpointsFiles = ['../routes/users.router.ts'] // root file where the route starts.
swaggerAutogen(outputFile, endpointsFiles)
.then(() => {
require('./dist/src/app.js') // Your project's root file
})
Go to the files reserved for your API routes (where they have the GET, POST, PATCH, ... functions) -- in my case '../routes/users.router.ts', and put comments, like :
// #swagger.path = "/users"
// #swagger.tags = ['User']
// #swagger.description = 'Endpoint to create a user.'
/*
#swagger.responses[201] = {
schema: { "$ref": "#/definitions/User" },
description: "User was successfully created." }
*/
NOTE: To learn more about these swagger-autogen comment tags see:
https://github.com/davibaltar/swagger-autogen#swagger-20
Run the following command: (In my case, this command is in a script in package.json that is called inside the Dockerfile):
NOTE: Remember that if you don't automatically generate the javascript files from the script in typescript you need to create your structure entirely in javascript and not in typescript. Pay attention to file names and extensions.
node ./dist/src/server/swagger.js // change to your path
When you do this a swagger_output.json file will be created containing your application details.
After the file has been generated, you need to install the "swagger-ui-restify" package.
Put these commands where the middlewares are (usually at application startup):
const swaggerUi = require("swagger-ui-restify")
const swaggerDocument = require("../swagger_output.json")
const swaggerOptions = {
explorer: true,
baseURL: 'api-docs',
}
app.get("/api-docs"+'/*', ...swaggerUi.serve)
app.get("/api-docs", swaggerUi.setup(swaggerDocument, swaggerOptions))
Now your application has a middleware to consult the automatically generated documentation.

Set Base URL for Preact CLI

Using Preact CLI is it possible to set the path where the app will be hosted outside of the root directory?
For instance hosting the app at http://mywebsite.com/relativepath/index.html
You have several problems to solve:
1. Get Webpack to output the correct paths in your html
This is done via creating a preact.config.js in your root folder, and put the following in there
export default (config) => {
config.output.publicPath = '/relativepath/';
};
2. Set your navigation and assets links in your app
The best way to solve it in my opinion is to use a global variable which you can be used in your app. So again, edit the preact.config.js to the following:
export default (config, env, helpers) => {
config.output.publicPath = '/relativepath/';
// use the public path in your app as 'process.env.PUBLIC_PATH'
config.plugins.push(
new helpers.webpack.DefinePlugin({
'process.env.PUBLIC_PATH': JSON.stringify(config.output.publicPath || '/')
})
);
};
3. Routing
When using your preact app, it should be no problem to navigate. However, if you try to load a fresh URL e.g. www.myserver.com/relativepath/mything/9, the server doesn't know that it should load your single page app living at www.myserver.com/relativepath/index.html
You have two options:
a) Server-side routing
Make sure your all the requests to relativepath (including e.g. relativepath/mything/9) will be rewritten to your app's relativepath/index.html (in case of using Apache).
Then your Javascript can process the routes, e.g. preact-router
b) Client-side routing (recommended)
The easier option for enabling reloading of URLs is to use hash urls, thereby avoid going through the server when loading a URL.
Your URLs will look something like www.myserver.com/relativepath/#/mything/9
The server ignores the part after # and only loads (hopefully) /relativepath/index.html
You can use e.g. the preact-router with Hash History to avoid server-side routing, read about it here https://github.com/developit/preact-router#custom-history
I'm proxying from http-proxy-middleware to the preact-cli dev server and these settings worked for me in preact.config.js
export default (config, env, helpers) => {
config.output.publicPath = '/relativepath';
config.devServer.devMiddleware.publicPath = "/relativepath";
};

ArangoDB with custom JS

Hello is there any way to use JS environment built in ArangoDB to execute custom JS? I'd like to set up path to my JS files which would be executed instead of foxx application files.
Via GitHub: https://github.com/arangodb/arangodb/issues/1723#issuecomment-183289699
You are correct that modules are cached independently of the routing
cache. Clearing the module cache (or preventing a module from being
cached) is currently not supported.
The actions mechanism is really only intended as an internal API and
only supported for backwards compatibility with early ArangoDB
versions and some edge cases.
As you may have noticed while digging through the ArangoDB source
code, Foxx provides a per-service module cache which is cleared
whenever a Foxx service is reloaded. I would strongly encourage you to
see whether Foxx fits your use case before continuing to dig into the
actions mechanism.
It's actually possible to create a Foxx service with just two files (a
manifest and a controller file) and without using repositories or
models (you can just use the same APIs available in actions).
You just need a controller file like this (e.g. ctrl.js):
'use strict';
const Foxx = require('org/arangodb/foxx');
const ctrl = new Foxx.Controller(applicationContext);
ctrl.get('/', function (req, res) {
res.send('Hello World');
});
with a manifest.json like this:
{
"name": "my-foxx",
"version": "0.0.0",
"controllers": "ctrl.js",
"defaultDocument": "",
"engines": {"arangodb": "^2.8.0"}
}
You can then mount the service (upload a zip bundle) at a path like
/db and access it:
curl http://localhost:8529/_db/_system/db
The upcoming 3.0 release will remove a lot of the existing conceptual
overhead of Foxx which will hopefully make it even easier to get
started with it.
Yes, this can be done with User Actions. Foxx was created as a more comfortable alternative and is likely a better choice for non-trivial applications. The documentation can be intimidating but Foxx services can actually be very lightweight and simple (see my other answer). If you really don't want to use Foxx for this, here's how to do it manually:
First create a virtual module in the _modules system collection:
var db = require('org/arangodb').db;
db._modules.save({
path: '/db:/ownTest',
content: `
exports.do = function (req, res, options, next) {
res.body = 'test';
res.responseCode = 200;
res.contentType = 'text/plain';
};
`
});
Then create a route that uses it:
db._routing.save({
url: '/ourtest',
action: {
controller: 'db://ownTest'
}
});
Finally, tell ArangoDB to update its routing cache so it notices the new route:
require('internal').reloadRouting();
If you install your JavaScript module to the js/common/ or the js/server/ directory you can use the module name (e.g. myOnDiskModule) instead of the virtual module name "db://owntest" in the controller.
For smaller modules you can just define the function inline using callback instead of controller:
db._routing.save({
url: '/hello/echo',
action: {
callback: `
function (req, res) {
res.statusCode = 200;
res.body = require('js-yaml').safeDump({
Hello: 'World',
are: 'you here?'
});
}
`
}
});
Remember to always update the routing cache after changes to the routing collection:
require('internal').reloadRouting();
Note: the callback implementation in 2.8 has a bug that will be fixed in 2.8.3. If you want to apply the fix manually, it's in commit b714dc5.

Add express middleware for param validations

In a sails.js application is there a simple way of including express-middleware?
For instance extending the request object with express-validator.
Adding express-middleware in a sails application is simple.
create a new policy.
policies
|_
middleware.js / .coffee
Add Express MiddlewareYOUR_MIDDLE_WARE_FILE_NAME.js
Inside your middleware file we create the standard export for node.js
module.exports = require('middle-ware')(OPTIONS_GO_HERE) // See middleware docs for configuration settings.
Then once you have created the middleware you can apply it to all requests or a single controller by following the Sails.js convension.
Entire Applicationpolicies.js
module.exports.policies = {
'*':['middleware'] // node same name as file without extention
}
Single Controller Action policies.js
module.exports.policies = {
RabbitController:{
feed:['middleware']
}
}
First of all, #SkyTecLabs' answer is the proper way to do this. But I wanted to add that, in some cases, you may need to control your static files (images, client-side javascript, css, etc) as well (I just had to deal with this recently). In this case, you can apply middleware generically to every route.
As of Sails.js v0.9.3, you can do:
// Put this in `config/express.js`
module.exports.express = {
customMiddleware: function (app) {
app.use(require('../node_modules/sails/node_modules/express').basicAuth('balderdash', 'wickywocky'));
}
};
More here: https://gist.github.com/mikermcneil/6255295
In the case where you want middleware to run before one or more of your controllers or actions, you're definitely better served using the policy approach though!

Resources