Keys in One Object Must be the Same as Keys in Another Object - jsonschema

Initial Setting
You have a JavaScript object for keeping configs, it may be extended by plugins, each plugin has a version and one property on the configs object.
const CONFIGS = {
plugins: {
plugins: { version: '0.15' }, // Plugins is a plugin itself.
proxies: { version: '0.15' } // Used to configure proxies.
},
proxies: {
HTTPS: ['satan.hell:666']
}
}
Question
How to express in JSON schema, that each key of CONFIGS.plugins MUST have corresponding property on root of CONFIGS object and vice versa.
My Failed Attempt
ajv is 4.8.2, prints "Valid!" but must be "Invalid"
'use strict';
var Ajv = require('ajv');
var ajv = Ajv({allErrors: true, v5: true});
var schema = {
definitions: {
pluginDescription: {
type: "object",
properties: {
version: { type: "string" }
},
required: ["version"],
additionalProperties: false
}
},
type: "object",
properties: {
plugins: {
type: "object",
properties: {
plugins: {
$ref: "#/definitions/pluginDescription"
}
},
required: ["plugins"],
additionalProperties: {
$ref: "#/definitions/pluginDescription"
}
}
},
required: { $data: "0/plugins/#" }, // current obj > plugins > all props?
additionalProperties: false
};
var validate = ajv.compile(schema);
test({
plugins: {
plugins: { version: 'def' },
proxies: { version: 'abc' }
}
// Sic! No `proxies` prop, but must be.
});
function test(data) {
var valid = validate(data);
if (valid) console.log('Valid!');
else console.log('Invalid: ' + ajv.errorsText(validate.errors));
}

There are three solutions here:
create another property on the root level, e.g. requiredProperties. Its value should be an array with the list of properties you want to have both on the top level and inside plugins. Then you can use required with $data pointing to this array both on top level and inside plugins.
See example here: https://runkit.com/esp/581ce9faca86cc0013c4f43f
use custom keyword(s).
check this requirement in code - there is no way in JSON schema to say keys in one object should be the same as keys in another (apart from above options).

Related

"You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file". Electron+Vue

I am trying to use the npm package "Typeorm" in my Electron + Vue project, but when I run it I have this error:
Module parse failed: Unexpected character '​' (2:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import { EntitySchema } from "typeorm"
> ​
| export default new EntitySchema({
| name: "Post", // Will use table name `post` as default behaviour.
But I don't even have a webpack.config.js in my project. Not even inside files from frameworks that i'm using. So I can't follow the tips of this https://webpack.js.org/concepts#loaders.
The file that contains this import:
Category.js
import { EntitySchema } from "typeorm"
export default new EntitySchema({
name: "Category", // Will use table name `category` as default behaviour.
tableName: "categories", // Optional: Provide `tableName` property to override the default behaviour for table name.
columns: {
id: {
primary: true,
type: "int",
generated: true,
},
name: {
type: "varchar",
},
},
})
This is my Babel.config:
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset'
]
}
To try to make it work, in my vue.config.js I added this "transpileDependecies", as suggested in #vue/cli-plugin-babel/preset . But it stills the same error.
vue.config.js
const { defineConfig } = require('#vue/cli-service')
module.exports = defineConfig({
transpileDependencies: [
'typeorm'
],
configureWebpack: {
devtool: 'source-map',
},
pluginOptions: {
vuetify: {
// https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vuetify-loader
}
}
})
Other similar questions did not help..

How Do I Insert Data Into Shopware 6 Database Via The Administration

I have created a plugin, created an admin route but inserting the data into Shopware 6 database does not work. Below is my code. After the build process, it doesn't work, what am I doing wrong?
From the code below I am trying to insert the data 'Diekedie' into the 'name' column of the 'product_manufacturer_translation' table.
const { Component, Mixin } = Shopware;
import template from './custom-module-list.html.twig'
Component.register('custom-module-list', {
template,
inject: [
'repositoryFactory'
],
metaInfo() {
return {
title: this.$createTitle()
};
},
data: function () {
return {
entity: undefined
}
},
methods: {
manufacturerRepository() {
return this.repositoryFactory.create('product_manufacturer_translation');
}
},
computed: {
},
created() {
this.manufacturerRepository();
this.entity = this.manufacturerRepository.create(Shopware.Context.api);
this.entity.name = 'Diekedie';
this.manufacturerRepository.save(this.entity, Shopware.Context.api);
}
});
To set translations you use the repository of the related entity, not the repository of the translations themselves. Also if you have a method that returns the created repository, you must use that return value to create the entity:
methods: {
manufacturerRepository() {
return this.repositoryFactory.create('product_manufacturer');
},
},
created() {
const repository = this.manufacturerRepository();
this.entity = repository.create(Shopware.Context.api);
this.entity.name = 'Diekedie';
repository.save(this.entity, Shopware.Context.api);
}

KeystoneJs virtual field cannot use a custom field type

I need to display a json/object in a readonly form and I wrote a custom field type for it but then when I use a virtual to transform it to a string for passing it to the custom field type. I put the custom type into the args but it shows Error: Unknown type "JsonViewer".
Any idea of how to make it work?
const { Virtual } = require("#keystonejs/fields");
const JsonViewer = require("#/components/fields/jsonViewer");
module.exports = {
fields: {
requestData: {
type: Virtual,
args: [{ name: "requestData", type: "JsonViewer" }],
resolver: async (json) => {
return JSON.stringify(json);
},
},
}
}
You have to provide complex type details if they do not exist in the generated schema for graphql.
In your case as you are doing JSON.stringify you can use String return type like this. BTW String type is default return type and you should not need any type declaration there for string type.
Also there is no args option in keystone Virtual field.
const { Virtual } = require("#keystonejs/fields");
module.exports = {
fields: {
requestData: {
type: Virtual,
graphQLReturnType: `String`,
resolver: async (json) => {
return JSON.stringify(json);
},
},
}
}

How to document rest api using aws cdk

I'm creating a REST API using AWS CDK version 1.22 and I would like to document my API using CDK as well, but I do not see any documentation generated for my API after deployment.
I've dived into aws docs, cdk example, cdk reference but I could find concrete examples that help me understand how to do it.
Here is my code:
const app = new App();
const api = new APIStack(app, 'APIStack', { env }); // basic api gateway
// API Resources
const resourceProps: APIResourceProps = {
gateway: api.gateway,
}
// dummy endpoint with some HTTP methods
const siteResource = new APISiteStack(app, 'APISiteStack', {
env,
...resourceProps
});
const siteResourceDocs = new APISiteDocs(app, 'APISiteDocs', {
env,
...resourceProps,
});
// APISiteDocs is defined as follow:
class APISiteDocs extends Stack {
constructor(scope: Construct, id: string, props: APIResourceProps) {
super(scope, id, props);
new CfnDocumentationVersion(this, 'apiDocsVersion', {
restApiId: props.gateway.restApiId,
documentationVersion: config.app.name(`API-${config.gateway.api.version}`),
description: 'Spare-It API Documentation',
});
new CfnDocumentationPart(this, 'siteDocs', {
restApiId: props.gateway.restApiId,
location: {
type: 'RESOURCE',
method: '*',
path: APISiteStack.apiBasePath,
statusCode: '405',
},
properties: `
{
"status": "error",
"code": 405,
"message": "Method Not Allowed"
}
`,
});
}
}
Any help/hint is appreciated, Thanks.
I have tested with CDK 1.31 and it is possible to use the CDK's default deployment option and also add a document version to the stage. I have used the deployOptions.documentVersion in rest api definition to set the version identifier of the API documentation:
import * as cdk from '#aws-cdk/core';
import * as apigateway from "#aws-cdk/aws-apigateway";
import {CfnDocumentationPart, CfnDocumentationVersion} from "#aws-cdk/aws-apigateway";
export class CdkSftpStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const documentVersion = "v1";
// create the API
const api = new apigateway.RestApi(this, 'books-api', {
deploy: true,
deployOptions: {
documentationVersion: documentVersion
}
});
// create GET method on /books resource
const books = api.root.addResource('books');
books.addMethod('GET');
// // create documentation for GET method
new CfnDocumentationPart(this, 'doc-part1', {
location: {
type: 'METHOD',
method: 'GET',
path: books.path
},
properties: JSON.stringify({
"status": "successful",
"code": 200,
"message": "Get method was succcessful"
}),
restApiId: api.restApiId
});
new CfnDocumentationVersion(this, 'docVersion1', {
documentationVersion: documentVersion,
restApiId: api.restApiId,
description: 'this is a test of documentation'
});
}
}
From what I can gather, if you use the CDK's default deployment options which create stage and deployment on your behalf, it won't be possible to append the stage with a documentation version set.
Instead, the solution would be to set the RESTAPI's option object to deploy:false and define the stage and deployment manually.
stack.ts code
import * as cdk from '#aws-cdk/core';
import * as apigateway from '#aws-cdk/aws-apigateway';
import { Stage, Deployment, CfnDocumentationPart, CfnDocumentationVersion, CfnDeployment } from '#aws-cdk/aws-apigateway';
export class StackoverflowHowToDocumentRestApiUsingAwsCdkStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// create the API, need to not rely on CFN's automatic deployment because we need to
// make our own deployment to set the documentation we create
const api = new apigateway.RestApi(this, 'books-api',{
deploy: false
});
// create GET method on /books resource
const books = api.root.addResource('books');
books.addMethod('GET');
// // create documentation for GET method
const docpart = new CfnDocumentationPart(this, 'doc-part1', {
location: {
type: 'METHOD',
method: 'GET',
path: books.path
},
properties: JSON.stringify({
"status": "successful",
"code": 200,
"message": "Get method was succcessful"
}),
restApiId: api.restApiId
});
const doc = new CfnDocumentationVersion(this, 'docVersion1', {
documentationVersion: 'version1',
restApiId: api.restApiId,
description: 'this is a test of documentation'
});
// not sure if this is necessary but it made sense to me
doc.addDependsOn(docpart);
const deployment = api.latestDeployment ? api.latestDeployment: new Deployment(this,'newDeployment',{
api: api,
description: 'new deployment, API Gateway did not make one'
});
// create stage of api with documentation version
const stage = new Stage(this, 'books-api-stage1', {
deployment: deployment,
documentationVersion: doc.documentationVersion,
stageName: 'somethingOtherThanProd'
});
}
}
OUTPUT:
Created a feature request for this option here.
I had the same exact problem. The CfnDocumentationVersion call has to occur after you create all of your CfnDocumentationPart. Using your code as an example, it should look something like this:
class APISiteDocs extends Stack {
constructor(scope: Construct, id: string, props: APIResourceProps) {
super(scope, id, props);
new CfnDocumentationPart(this, 'siteDocs', {
restApiId: props.gateway.restApiId,
location: {
type: 'RESOURCE',
method: '*',
path: APISiteStack.apiBasePath,
statusCode: '405',
},
properties: JSON.stringify({
"status": "error",
"code": 405,
"message": "Method Not Allowed"
}),
});
new CfnDocumentationVersion(this, 'apiDocsVersion', {
restApiId: props.gateway.restApiId,
documentationVersion: config.app.name(`API-${config.gateway.api.version}`),
description: 'Spare-It API Documentation',
});
}
}

GraphQL buildSchema vs GraphQLObjectType

I went through GraphQL's Object Types tutorial and then read through the Constructing Types part of the docs. I did a similar style trial by creating a simplecase convention converter. Why? To learn :)
When converting to using GraphQLObjectType, I wanted the same results as buildSchema.
Why does buildSchema use type CaseConventions but when using GraphQLObjectType it is not set at a type? Am I doing something wrong here?
Did I implement this with any alarming problems?
Should I be using a rootValue object with the GraphQLObjectType version as I did with the buildQuery version?
Thank you for your patience and help.
Both versions use this Object:
class CaseConventions {
constructor(text) {
this.text = text;
this.lowerCase = String.prototype.toLowerCase;
this.upperCase = String.prototype.toUpperCase;
}
splitTargetInput(caseOption) {
if(caseOption)
return caseOption.call(this.text).split(' ');
return this.text.split(' ');
}
cssCase() {
const wordList = this.splitTargetInput(this.lowerCase);
return wordList.join('-');
}
constCase() {
const wordList = this.splitTargetInput(this.upperCase);
return wordList.join('_');
}
}
module.exports = CaseConventions;
buildSchema version:
const schema = new buildSchema(`
type CaseConventions {
cssCase: String
constCase: String
}
type Query {
convertCase(textToConvert: String!): CaseConventions
}
`);
const root = {
convertCase: ({ textToConvert }) => {
return new CaseConventions(textToConvert);
}
};
app.use('/graphql', GraphQLHTTP({
graphiql: true,
rootValue: root,
schema
}));
GraphQLObjectType version:
const QueryType = new GraphQLObjectType({
name: 'Query',
fields: {
cssCase: {
type: GraphQLString,
args: { textToConvert: { type: GraphQLString } },
resolve(parentValue) {
return parentValue.cssCase();
}
},
constCase: {
type: GraphQLString,
args: { textToConvert: { type: GraphQLString } },
resolve(parentValue) {
return parentValue.constCase()
}
}
}
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
convertCase: {
type: QueryType,
args: { textToConvert: { type: GraphQLString } },
resolve(p, { textToConvert }) {
return new CaseConventions(textToConvert);
}
}
}
});
const schema = new GraphQLSchema({
query: RootQuery
});
app.use('/graphql', GraphQLHTTP({
graphiql: true,
schema
}));
I will try to answer you question satisfactorily.
Why does buildSchema use type CaseConventions but when using GraphQLObjectType it is not set at a type? Am I doing something wrong here
They are two different ways of implementation. Using buildSchema uses the graphQL schema language while GraphQLSchema does not use the schema language, it creates the schema programmatically.
Did I implement this with any alarming problems?
Nope
Should I be using a rootValue object with the GraphQLObjectType version as I did with the buildQuery version?
No, In buildSchema, the root provides the resolvers while in using
GraphQLSchema, the root level resolvers are implemented on the Query and Mutation types rather than on a root object.