I am having a CI service that validates YAML files using JSON schema. The solution works by firstly converting the YAML to JSON using js-yaml and then by checking the schema using ajv
sample code:
import { load } from 'js-yaml';
import { default as Ajv } from 'ajv';
import schema from '../../schema.json';
const ajv = new Ajv({
strict: false
});
export const validate = (file: { content: string }) => {
const parsed = load(file.content) as unknown;
const valid = ajv.validate(schema, parsed);
if (!valid) throw new Error(ajv.errorsText());
}
I would like to extend this solution to report back with the error Line and Column.
Do you know if there is a solution for this out there already? My GoogleFu let me down this time. The closest I got is vscode XML plugin vscode YAML plugin which seems to be tightly coupled with VS code :(
Related
I would like to translate this code into actual TypeScript. Could you help me there?
import mongoose, { Promise } from 'mongoose';
Promise = global.Promise;
const db = {};
db.mongoose = mongoose;
db.user = require("./user.model");
db.role = require("./role.model");
db.ROLES = ["user", "admin", "moderator"];
export default db;
It would be great if you'd provide us with what you have tried and achieved so that it is easier to modify your code.
A way to do this would be to type this in a TypeScript file in an editor that provides linting for TypeScript like Visual Studio Code. Then check all the errors and fix them.
I have the following yaml file:
trainingPhrases:
- help me
- what to do
- how to play
- help
I readi it from disk using readFile from node and parse it using load from js-yaml:
import { load } from "js-yaml";
import { readFile } from "fs/promises";
const phrases = load(await readFile(filepath, "utf8")).trainingPhrases as string[];
I get the following eslint warning:
ESLint: Unsafe member access .trainingPhrases on an any value.(#typescript-eslint/no-unsafe-member-access)
Instead of suppressing the warning, I would like to map it into a concrete type for the YAML file (as it happens in axios for example: axios.get<MyResponseInterface>(...) - performs a GET and MyResponseInterface defines the structure of the HTTP response).
Is there a dedicated library for that?
From what I can see when using #types/js-yaml is that load is not generic, meaning it does not accept a type parameter.
So the only way to get a type here is to use an assertion, for example:
const yaml = load(await readFile(filepath, "utf8")) as YourType;
const phrases = yaml.trainingPhrases;
Or in short:
const phrases = (load(await readFile(filepath, "utf8")) as YourType).trainingPhrases;
If you absolutely want a generic function, you can easily wrap the original, like:
import {load as original} from 'js-yaml';
export const load = <T = ReturnType<typeof original>>(...args: Parameters<typeof original>): T => load(...args);
And then you can use it as:
const phrases = load<YourType>('....').trainingPhrases;
I would like to include a couple of JSON files in my JavaScript code that are in the same directory as my JavaScript source file.
If I wanted to include another JavaScript file I could simply use require.
Now I'm using readFileSync and __dirname to get the JSON, which I think is an ugly way to do it.
Is there something similar for require that enables me to load a JSON file?
As of node v0.5.x yes you can require your JSON just as you would require a js file.
var someObject = require('./somefile.json')
In ES6:
import someObject from './somefile.json'
JSON files don’t require an explicit exports statement. You don't need to export to use it as Javascript files.
So, you can use just require for valid JSON document.
data.json
{
"name": "Freddie Mercury"
}
main.js
var obj = require('data.json');
console.log(obj.name);
//Freddie Mercury
Two of the most common
First way :
let jsonData = require('./JsonFile.json')
let jsonData = require('./JsonFile') // if we omitting .json also works
OR
import jsonData from ('./JsonFile.json')
Second way :
1) synchronously
const fs = require('fs')
let jsonData = JSON.parse(fs.readFileSync('JsonFile.json', 'utf-8'))
2) asynchronously
const fs = require('fs')
let jsonData = {}
fs.readFile('JsonFile.json', 'utf-8', (err, data) => {
if (err) throw err
jsonData = JSON.parse(data)
})
Note:
1) if we JsonFile.json is changed, we not get the new data, even if we re run require('./JsonFile.json')
2) The fs.readFile or fs.readFileSync will always re read the file, and get changes
No. Either use readFile or readFileSync (The latter only at startup time).
Or use an existing library like
cjson
Alternatively write your config in a js file rather then a json file like
module.exports = {
// json
}
A nifty non-caching async one liner for node 15 modules:
import { readFile } from 'fs/promises';
const data = await readFile('{{ path }}').then(json => JSON.parse(json)).catch(() => null);
You even can use require of your JSON without specifying the extension .json.
It will let you change the file extension to .js without any changes in your imports.
assuming we have ./myJsonFile.json in the same directory.
const data = require('./myJsonFile')
If in the future you'll change ./myJsonFile.json to ./myJsonFile.js nothing should be changed in the import.
You can import json files by using the node.js v14 experimental json modules flag. More details here
file.js
import data from './folder/file.json' assert { type: 'json' }
export default {
foo () {
console.log(data)
}
}
And you call it with node --experimental-json-modules file.js
You can use a module to create a require.
import { createRequire } from 'module'
const require = createRequire(import.meta.url)
const foo = require('./foo.json')
if you are using typescript, you can just add in your tsconfig.json a new field called resolveJsonModule: true, and then you can import all the informations of any .json file just like this:
import * as jsonfile from "./path/to/json"
I'm new to GraphQL. I'm trying to break apart a schema.sql file into multiple files.
First question, is this a standard way of doing things with GraphQL (for example, Query.graphql, Mutation.graphql, TypeA.graphql, etc.)
Second, I thought the parameter in typeDefs (for graphql-yoga) allows me to pass an array of locations for all the schema files, but it's not working for me (See below after the code for the error I'm geting.
Here is my code in my main index.js file:
import { graphQLServer, GraphQLServer } from 'graphql-yoga';
import db from '../database/db';
import Query from './resolvers/Query';
import Mutation from './resolvers/Mutation';
import Post from './resolvers/Post';
import User from './resolvers/User';
import Comment from './resolvers/Comment';
const typeDefs = [
'./schemas/query.graphql',
'./schemas/mutation.graphql',
'./schemas/user.graphql'
];
const server = new GraphQLServer({
typeDefs: typeDefs,
context: { db },
resolvers: { Query, Mutation, Post, User, Comment }
});
server.start(()=> {
console.log("Server started on localhost:4000!");
});
Here is the error I'm getting:
Error: Field createUser: Couldn't find type User in any of the schemas.
at collectNode (C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-import\src\definition.ts:154:15)
at C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-import\src\definition.ts:135:7
at Array.forEach (<anonymous>)
at collectNewTypeDefinitions (C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-import\src\definition.ts:134:26)
at Object.completeDefinitionPool (C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-import\src\definition.ts:49:39)
at Object.importSchema (C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-import\src\index.ts:127:18)
at mergeTypeDefs (C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-yoga\src\index.ts:456:14)
at C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-yoga\src\index.ts:472:32
at Array.reduce (<anonymous>)
at mergeTypeDefs (C:\Websites\Learning-GraphQL - Local Copy\graphql-bootcamp\graphql-basics\node_modules\graphql-yoga\src\index.ts:471:21)
As you can see, it says it can't find one of my types (User), but I do have it in the User.graphql schema file. When I have everything in just one file and pass that file only as the typeDefs, it works fine. Thanks in advance for your help!
const typeDefs = [
'./schemas/query.graphql',
'./schemas/mutation.graphql',
'./schemas/user.graphql'
];
this is only an array of strings
from docs:
typeDefs - String or Function or DocumentNode or array of previous
you can make something like:
import Query from './schemas/query.graphql'
import Mutation from './schemas/mutation.graphql'
import User from './schemas/user.graphql'
const typeDefs = [Query, Mutation, User];
config required: https://github.com/apollographql/graphql-tag#webpack-preprocessing-with-graphql-tagloader
Simple joi validation snippet in javascript.It will simply return an error object when validation fails.
validate.js
const Joi =require("joi");
function validateObject (input) {
const schema = {
key: Joi.string().required(),
};
return Joi.validate(input, schema);
};
let {error} = validateObject({key:5})
console.log(error)
Now I am learning typescript and like to do the exact functionality in TS.I am aware that Joi is a javascript library but can we make use of it in Typescript.When exploring I came across some alternatives like https://github.com/joiful-ts/joiful.
I am curious to know if there is any straightforward approach using Joi directly in typescript. Or little bit of changes to make the Joi work exactly like in Javascript.
WHAT I TRIED
validate.ts
import * as Joi from "joi";
export const validateObject = (input: object) => {
const schema = {
home: Joi.string().required(),
};
return Joi.validate(input, schema);
};
validateObject({key:5})
While compiling, I got the error
Cannot find name 'Iterable'.
703 map(iterable: Iterable<[string | number | boolean | symbol,
symbol]> | { [key: string]: symbol }): this;
UPDATE
I have installed #types/joi as suggested in the answer but still the same error
I am basically looking for validating string,boolean,number,array and object keys as it can be done easily with Joi in Javascript
Please change your import
-const Joi =require("joi");
+import Joi from "joi";
And make sure you've installed the types by using
npm install --save-dev #types/joi
Type definitions for Joi exists: #types/joi or #types/hapi__joi (for joi version 17).
Add those to your package.json, and you should be able to use Joi with Typescript. Generally speaking you should not be downloading seperate libraries to make a package work in Typescript, some definitions should do
Try to use this code instead.
import * as Joi from "joi";
export const validateObject = (input: object) => {
const schema = Joi.object().keys({
home: Joi.string().required(),
});
return schema.validate(input);
};
validateObject({key:5})
I hope you will manage to make it work.
I doubt that import * as Joi from "joi" is going to give you much joy. You are importing all exported members with that.
Is there an individual export you are wanting? Use import { IndividualExport } from "joi"
Is there a default export you are wanting? Use import Joi from "joi"
Also is there a reason you are calling Joi in the second example but not the first?
Zod seems to be a popular Joi alternative for TypeScrip:
https://www.npmjs.com/package/zod