VeeValidate/i18n using different languages in v4 - json

I've been using VeeValidate v2 and had something like this:
VeeValidate.Validator.localize('en', customErrors);
const customErrors = {
custom: {
someField: {
required: 'error.required',
},
...
}}
I have JSON files for example en.json, de.json, fr.json, etc. which look like this:
// en.json
{
"something": {
"something1": "phrase1",
"something2": "phrase2",
}
"error": {
"required": "Field is required"
}
}
In v2 this worked and errors were translated.
I updated vee-validate to v4 because of the Vue update to v3 and I don't know how to achieve the same effect.
Now I got
import { configure } from 'vee-validate';
// VeeValidate.Validator.localize('en', customErrors);
configure({
generateMessage: localize('en', customErrors)
});
I also changed customErrors
const customErrors = {
fields: {
someField: {
required: 'error.required',
},
...
}}
With this config my error is just error.required instead of the value from this field from the JSON file.
Can somebody help?

Related

BadRequest by InvalidTemplate when deploying a bicep file containing an eventgridSubscription with a servicebus destination endpoint

What I would like to achieve is to be able to generate eventgridsubscriptions very easy using bicep. Because manually it costs a lot of time. I have to create like a over a dozen each day.
I have the following bicep file called main.bicep
param eventSubscriptionName string = 'eventSubName'
param storageAccountName string ='storeAccountName'
param deadLetterAccountName string = 'deadlttrstore'
param serviceBusQueueName string = 'queue.name.enter'
param onrampName string = 'storagecontainername'
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-09-01' existing = {
name: storageAccountName
}
resource deadLetterAccount 'Microsoft.Storage/storageAccounts#2021-09-01' existing = {
name: deadLetterAccountName
}
resource serviceBusQueue 'Microsoft.ServiceBus/namespaces/queues#2021-11-01' existing = {
name: serviceBusQueueName
}
resource eventgridsubscription 'Microsoft.EventGrid/eventSubscriptions#2021-12-01' = {
name: eventSubscriptionName
scope: storageAccount
properties: {
deadLetterDestination: {
endpointType: 'StorageBlob'
properties: {
blobContainerName: 'storage-deadletters'
resourceId: deadLetterAccount.id
}
}
destination: {
endpointType: 'ServiceBusQueue'
properties: {
deliveryAttributeMappings: [
{
name: serviceBusQueueName
type: 'Static'
properties: {
isSecret: false
value: ''
}
}
]
resourceId: serviceBusQueue.id
}
}
eventDeliverySchema: 'EventGridSchema'
filter: {
enableAdvancedFilteringOnArrays: false
includedEventTypes: [
'Microsoft.Storage.BlobCreated'
]
isSubjectCaseSensitive: false
subjectBeginsWith: '/blobServices/default/containers/${onrampName}'
subjectEndsWith: '.json'
}
retryPolicy: {
eventTimeToLiveInMinutes: 1440
maxDeliveryAttempts: 5
}
}
}
When I want create the event subscription using az cli with:
az deployment group create -f main.bicep -g <resource-group>
I get the following error:
{
"status": "Failed",
"error":
{
"code": "DeploymentFailed",
"message": "At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.",
"details":
[
{
"code": "BadRequest",
"message": "{\r\n \"error\":
{\r\n \"code\": \"InvalidTemplate\",\r\n \"message\": \"Unable to process template language expressions for resource '/subscriptions/x1234456-f9cc-44e5-bc40-5f02d962f2d7/resourceGroups/<resource-group>/providers/Microsoft.Storage/storageAccounts/<storage-account>/providers/Microsoft.EventGrid/eventSubscriptions/eventSubName' at line '34' and column '5'. 'The language expression property array index '1' is out of bounds.'\",\r\n \"additionalInfo\":
[\r\n {\r\n \"type\": \"TemplateViolation\",\r\n \"info\": {\r\n \"lineNumber\": 34,\r\n \"linePosition\": 5,\r\n \"path\": \"\"\r\n }\r\n }\r\n ]\r\n }\r\n}"
}
]
}
}
I am working according to the template documented at MS here:
https://learn.microsoft.com/en-us/azure/templates/microsoft.eventgrid/eventsubscriptions?tabs=bicep
Eventually the solution was quite simple the servicebus resource was missing its parent resource namely the servicebus namespace. Once that was added it worked.
resource serviceBus 'Microsoft.ServiceBus/namespaces#2021-11-01' existing = {
name: serviceBusName
}
and
resource serviceBusQueue 'Microsoft.ServiceBus/namespaces/queues#2021-11-01' existing = {
parent: serviceBus
name: serviceBusQueueName
}
to
param eventSubscriptionName string = 'eventSubName'
param storageAccountName string ='storeAccountName'
param deadLetterAccountName string = 'deadlttrstore'
param serviceBusQueueName string = 'queue.name.enter'
param onrampName string = 'storagecontainername'
resource storageAccount 'Microsoft.Storage/storageAccounts#2021-09-01' existing = {
name: storageAccountName
}
resource deadLetterAccount 'Microsoft.Storage/storageAccounts#2021-09-01' existing = {
name: deadLetterAccountName
}
resource serviceBus 'Microsoft.ServiceBus/namespaces#2021-11-01' existing = {
name: serviceBusName
}
resource serviceBusQueue 'Microsoft.ServiceBus/namespaces/queues#2021-11-01' existing = {
parent: serviceBus
name: serviceBusQueueName
}
resource eventgridsubscription 'Microsoft.EventGrid/eventSubscriptions#2021-12-01' = {
name: eventSubscriptionName
scope: storageAccount
properties: {
deadLetterDestination: {
endpointType: 'StorageBlob'
properties: {
blobContainerName: 'storage-deadletters'
resourceId: deadLetterAccount.id
}
}
destination: {
endpointType: 'ServiceBusQueue'
properties: {
deliveryAttributeMappings: [
{
name: serviceBusQueueName
type: 'Static'
properties: {
isSecret: false
value: 'some-value'
}
}
]
resourceId: serviceBusQueue.id
}
}
eventDeliverySchema: 'EventGridSchema'
filter: {
enableAdvancedFilteringOnArrays: false
includedEventTypes: [
'Microsoft.Storage.BlobCreated'
]
isSubjectCaseSensitive: false
subjectBeginsWith: '/blobServices/default/containers/${onrampName}'
subjectEndsWith: '.json'
}
retryPolicy: {
eventTimeToLiveInMinutes: 1440
maxDeliveryAttempts: 5
}
}
}
I tried to reproduce the error message you posted but could get the same result. I did get an error message because value: '':
{
name: serviceBusQueueName
type: 'Static'
properties: {
isSecret: false
value: ''
}
}
When I updated to the following, it worked:
{
name: serviceBusQueueName
type: 'Static'
properties: {
isSecret: false
value: 'some-value'
}
}
The error message I saw with the empty string was:
Null or empty value for static delivery attribute queue-name-enter. Static delivery attribute value must be a non-empty string.
After adding some random text, the deployment completed successfully.

How to convert a json to a typescript interface?

Given a JSON output of an api:
{
"id": 13,
"name": "horst",
"cars": [{
"brand": "VW",
"maxSpeed": 120,
"isWastingGazoline": true
}]
}
I would like to define interfaces for typescript:
export interface Car {
brand: string;
maxSpeed: number;
isWastingGazoline: boolean;
}
export interface RaceCarDriver {
id: number;
name: string;
cars: Car[];
}
Yet I don't want them to type them manually, I rather have a script generate them for me.
How can I convert json into typescript interfaces? I also don't want to use webservices like MakeTypes or json2ts.
You can write the script using typescript compiler API and its ability to infer types. I was really surprised how easy it was.
You have to wrap your sample data to make it compile-able as typescript code. The script will pick all variable declarations and try to print inferred types for them. It uses variable names and property names for assigning names to types, and if two objects have a property with the same name, it will pick the type from the first one. So it will not work in case these types are actually different (the fix is left as an exercise). For your JSON output, the data sample will look like
file sample.ts
let raceCarDriver = {
"id": 13,
"name": "horst",
"cars": [{
"brand": "VW",
"maxSpeed": 120,
"isWastingGazoline": true,
}]
};
The script was tested with Typescript 2.1 (just released):
npm i typescript
npm i #types/node
./node_modules/.bin/tsc --lib es6 print-inferred-types.ts
node print-inferred-types.js sample.ts
output:
export interface RaceCarDriver {
id: number;
name: string;
cars: Car[];
}
export interface Car {
brand: string;
maxSpeed: number;
isWastingGazoline: boolean;
}
Here is the script: print-inferred-types.ts:
import * as ts from "typescript";
let fileName = process.argv[2];
function printInferredTypes(fileNames: string[], options: ts.CompilerOptions): void {
let program = ts.createProgram(fileNames, options);
let checker = program.getTypeChecker();
let knownTypes: {[name: string]: boolean} = {};
let pendingTypes: {name: string, symbol: ts.Symbol}[] = [];
for (const sourceFile of program.getSourceFiles()) {
if (sourceFile.fileName == fileName) {
ts.forEachChild(sourceFile, visit);
}
}
while (pendingTypes.length > 0) {
let pendingType = pendingTypes.shift();
printJsonType(pendingType.name, pendingType.symbol);
}
function visit(node: ts.Node) {
if (node.kind == ts.SyntaxKind.VariableStatement) {
(<ts.VariableStatement>node).declarationList.declarations.forEach(declaration => {
if (declaration.name.kind == ts.SyntaxKind.Identifier) {
let identifier = <ts.Identifier>declaration.name;
let symbol = checker.getSymbolAtLocation(identifier);
if (symbol) {
let t = checker.getTypeOfSymbolAtLocation(symbol, identifier);
if (t && t.symbol) {
pendingTypes.push({name: identifier.text, symbol: t.symbol});
}
}
}
});
}
}
function printJsonType(name: string, symbol: ts.Symbol) {
if (symbol.members) {
console.log(`export interface ${capitalize(name)} {`);
Object.keys(symbol.members).forEach(k => {
let member = symbol.members[k];
let typeName = null;
if (member.declarations[0]) {
let memberType = checker.getTypeOfSymbolAtLocation(member, member.declarations[0]);
if (memberType) {
typeName = getMemberTypeName(k, memberType);
}
}
if (!typeName) {
console.log(`// Sorry, could not get type name for ${k}!`);
} else {
console.log(` ${k}: ${typeName};`);
}
});
console.log(`}`);
}
}
function getMemberTypeName(memberName: string, memberType: ts.Type): string | null {
if (memberType.flags == ts.TypeFlags.String) {
return 'string';
} else if (memberType.flags == ts.TypeFlags.Number) {
return 'number';
} else if (0 !== (memberType.flags & ts.TypeFlags.Boolean)) {
return 'boolean';
} else if (memberType.symbol) {
if (memberType.symbol.name == 'Array' && (<ts.TypeReference>memberType).typeArguments) {
let elementType = (<ts.TypeReference>memberType).typeArguments[0];
if (elementType && elementType.symbol) {
let elementTypeName = capitalize(stripS(memberName));
if (!knownTypes[elementTypeName]) {
knownTypes[elementTypeName] = true;
pendingTypes.push({name: elementTypeName, symbol: elementType.symbol});
}
return `${elementTypeName}[]`;
}
} else if (memberType.symbol.name == '__object') {
let typeName = capitalize(memberName);
if (!knownTypes[typeName]) {
knownTypes[typeName] = true;
pendingTypes.push({name: typeName, symbol: memberType.symbol});
}
return typeName;
} else {
return null;
}
} else {
return null;
}
}
function capitalize(n: string) {
return n.charAt(0).toUpperCase() + n.slice(1);
}
function stripS(n: string) {
return n.endsWith('s') ? n.substring(0, n.length - 1) : n;
}
}
printInferredTypes([fileName], {
noEmitOnError: true, noImplicitAny: true,
target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
});
Found a npm package that converts a arbitrary JSON file without a schema into a TS interface:
https://www.npmjs.com/package/json-to-ts
The author also provided a VSCode plugin.
You can use an npm module instead of the web hosted solution:
https://www.npmjs.com/package/json-schema-to-typescript
If your JSON comes from an HTTP API and the API has an swagger code definition, you can generate a TypeScript client:
https://github.com/swagger-api/swagger-codegen#api-clients
If you json comes from a Java ot .Net backened, you can generate TypeScript from Java or C# classes:
http://type.litesolutions.net
https://github.com/raphaeljolivet/java2typescript
Using only sed and tsc
sed '1s#^#const foo = #' sample.json > sample.$$.ts
tsc sample.$$.ts --emitDeclarationOnly --declaration
Append const foo = to beginning of file
Using sed to replace (s) nothing (#^#) at the beginning of the first line (1) with const foo =
output to sample.$$.ts
the extension is the required to be .ts
$$ expands to the shells process id, handy for a temp file that is unlikely to overwrite stuff you care about
ask tsc to only emit a .d.ts typings file
this file has pretty much everything you want for the interface. You might need to replace a few strings and customize it in a way you want but most of the leg work is done

How to extract json Response?

Someone told me.
obj is a JSON response.
obj = { title: 'ABCD', _key: '-KX9Cwwuc2FjxcG-SNY0' }
I can get ABCD using console.log(obj["title”]).
How about complex case?
obj = { '-KXu3irrOjUtcejm4VF3':
{ gold: 0,
title: ‘xxxx09x#gmail.com',
uketuke: 0,
user: ‘xxxx09x#gmail.com' },
'-KXu3vLo7--JeVYC9fJa': { title: ‘JUMP' },
'-KXu3yRZgFlDcS8BZ7e1': { title: 'JUMP1' } }
In this case, how can I get the user entity?
By the way like this obj["title”] presentation, I think this should be ECMA standard,
please let me know where reference is?
If you knew the key then it's quite easy. For example:
obj = {
'-KXu3irrOjUtcejm4VF3': {
gold: 0,
title: 'xxxx09x#gmail.com',
uketuke: 0,
user: 'xxxx09x#gmail.com'
},
'-KXu3vLo7--JeVYC9fJa': { title: 'JUMP' },
'-KXu3yRZgFlDcS8BZ7e1': { title: 'JUMP1' }
}
var user_key = '-KXu3irrOjUtcejm4VF3'
user = obj[user_key].user
"xxxx09x#gmail.com"
However if you did not know the key of object in which the user exists then the following function can help with asymptotic complexity O(n):
function getUser(obj) {
for (var key in obj) {
// skip loop if the property is from prototype
if (!obj.hasOwnProperty(key)) continue;
if (typeof obj[key].user !== undefined) {
return obj[key].user;
}
}
}
getUser(obj)
"xxxx09x#gmail.com"
And finally there is something I used in one of projects: jsonpath
$..user
would return all user from your obj. This way you can go quite far with a complicated json IMHO.
Need to do some corrections :
To access the property value from this JSON response var obj = { title: 'ABCD', _key: '-KX9Cwwuc2FjxcG-SNY0' } you have to use dot(.) operator instead of [].
If you will use obj[title] it will give you an error :
Uncaught ReferenceError: title is not defined(…)
If you will use obj.title it will give you an output :
ABCD
So, as per the complex case :
First thing : Strings should be wrapped in double quotes.
Invalid JSON :
var obj = {
'-KXu3irrOjUtcejm4VF3': {
gold: 0,
title: 'xxxx09x#gmail.com',
uketuke: 0,
user: 'xxxx09x#gmail.com'
},
'-KXu3vLo7--JeVYC9fJa': { title: ‘JUMP' },
'-KXu3yRZgFlDcS8BZ7e1': { title: 'JUMP1' }
};
Valid JSON :
var obj = {
"-KXu3irrOjUtcejm4VF3": {
"gold": 0,
"title": "abc#gmail.com",
"uketuke": 0,
"user": "def#gmail.com"
},
"-KXu3vLo7--JeVYC9fJa": {
"title": "JUMP"
},
"-KXu3yRZgFlDcS8BZ7e1": {
"title": "JUMP1"
}
}

extract-document-data comes as xml string element in json output

I am trying to enrich my search results with some elements taken from the "matching" documents, using the query option "extract-document-data" like
<options xmlns="http://marklogic.com/appservices/search">
<extract-document-data selected="include">
<extract-path>/language-version/language-version-canonical-model/title</extract-path>
<extract-path>/language-version/language-version-canonical-model/language</extract-path>
</extract-document-data>
(...)
</options>
When I run the search and I ask for Json output (using the header Accept: application/json) I get as mix of json and "strinxml" as a result:
{
"snippet-format": "snippet",
"total": 564,
"start": 1,
"page-length": 10,
"selected": "include",
"results": [
{
"index": 1,
"uri": "ENV/CHEM/NANO(2015)22/ANN5/2",
"path": "fn:doc(\"ENV/CHEM/NANO(2015)22/ANN5/2\")",
(...)
"matches": [
{
"path": "fn:doc(\"ENV/CHEM/NANO(2015)22/ANN5/2\")/ns2:language-version/ns2:language-version-raw-data/*:document/*:page[22]",
(...)
}
],
"extracted": {
"kind": "element",
"content": [
"<language>En</language>",
"<title>ZINC OXIDE DOSSIERANNEX 5</title>",
"<reference>ENV/CHEM/NANO(2015)22/ANN5</reference>",
"<classification>2</classification>",
"<modificationDate>2015-04-16T00:00:00.000+02:00</modificationDate>",
"<subject label_en=\"media\" >media</subject>",
"<subject label_en=\"fish\" ">fish</subject>",
]
}
},
The problem here is with the "extracted" part, as you can see, it looks like the xml elements have been simply copied as string, when I would really expect them to be converted to json.
Does anybody have an idea about this problem?
MarkLogic won’t convert content. So, XML will remain XML when asking for JSON formatted search response. And since you can't really embed XML inside JSON, it gets serialized as a string.
You could try applying a REST transform on your search results, and use something like json:transform-to-json (probably with the custom config) to convert those on the fly. For instance something like this Server-side JavaScript transform:
/* jshint node:true,esnext:true */
/* global xdmp */
var json = require('/MarkLogic/json/json.xqy');
var config = json.config('custom');
function toJson(context, params, content) {
'use strict';
var response = content.toObject();
if (response.results) {
response.results.map(function(result) {
if (result.extracted && result.extracted.content) {
result.extracted.content.map(function(content, index) {
if (content.match(/^</) && !content.match(/^<!/)) {
result.extracted.content[index] = json.transformToJson(xdmp.unquote(content), config);
}
});
}
});
}
return response;
}
exports.transform = toJson;
You could also convert client-side of course.
HTH!
If you're using the Java Client API you can use the correct handle for each result to read the extracted items (see ExtractedResult and ExtractedItem):
SearchHandle results = queryManager.search(query, new SearchHandle());
for (MatchDocumentSummary summary : results.getMatchResults()) {
ExtractedResult extracted = summary.getExtracted();
// here we check to see if this result is XML format, and if so
// we use org.w3c.dom.Document
if ( Format.XML == summary.getFormat() ) {
for (ExtractedItem item : extracted) {
Document extractItem = item.getAs(new DOMHandle()).get();
...
}
// or if the result is JSON we could choose a different handle
} else if ( Format.JSON == summary.getFormat() ) {
for (ExtractedItem item : extracted) {
JsonNode extractItem = item.getAs(JsonNode.class);
...
}
}
}

Ember Data: Saving relationships

I need to save a deep object to the server all at once and haven't been able to find any examples online that use the latest ember data (1.0.0-beta.4).
For example, with these models:
(jsfiddle)
App.Child = DS.Model.extend({
name: DS.attr('string'),
age: DS.attr('number'),
toys: DS.hasMany('toy', {async:true, embedded:'always'}),
});
App.Toy = DS.Model.extend({
name: DS.attr('string'),
child: DS.belongsTo('child')
});
And this code:
actions: {
save: function(){
var store = this.get('store'),
child, toy;
child = store.createRecord('child', {
name: 'Herbert'
});
toy = store.createRecord('toy', {
name: 'Kazoo'
});
child.set('toys', [toy]);
child.save();
}
}
It only saves the JSON for the child object but not any of the toys -- not even side loaded:
{
child: {
age: null
name: "Herbert"
}
}
Do I have to manually save the toys too? Is there anyway that I can have it send the following JSON to the server:
{
child: {
age: null
name: "Herbert",
toys: [{
name: "Kazoo"
}]
}
}
Or
{
child: {
age: null
name: "Herbert",
toys: [1]
}
}
See JSFiddle: http://jsfiddle.net/jgillick/LNXyp/2/
The answers here are out of date. Ember Data now supports embedded records, which allows you to do exactly what you're looking to do, which is to get and send the full object graph in one big payload. For example, if your models are set up like this:
App.Child = DS.Model.extend({
name: DS.attr('string'),
age: DS.attr('number'),
toys: DS.hasMany('toy')
});
App.Toy = DS.Model.extend({
name: DS.attr('string'),
child: DS.belongsTo('child')
});
You can define a custom serializer for your Child model:
App.ChildSerializer = DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
attrs: {
toys: {embedded: 'always'}
}
});
This tells Ember Data that you'd like 'toys' to be included as part of the 'child' payload. Your HTTP GET response from your API should look like this:
{
"child": {
"id": 1,
"name": "Todd Smith",
"age": 5,
"toys": [
{"id": 1, "name": "boat"},
{"id": 2, "name": "truck"}
]
}
}
And when you save your model, Ember Data will send this to the server:
{
"child":{
"name":"Todd Smith",
"age":5,
"toys":[
{
"id":"1",
"name":"boat",
"child":"1"
},
{
"id":"2",
"name":"truck",
"child":"1"
}
]
}
}
Here is a JSBin that demonstrates this.
http://emberjs.jsbin.com/cufaxe/3/edit?html,js,output
In the JSbin, when you click the 'Save' button, you'll need to use the Dev Inspector to view the request that's sent to the server.
toys can't be both async and embedded always, those are contradicting options. Embedded only exists on the active model serializer currently.
toys: DS.hasMany('toy', {embedded:'always'})
the toys are a ManyToOne relationship, and since the relationship exists on the belongsTo side it is more efficient to save the relationship during the toy's save. That being said, if you are creating it all at once, then want to save it in one big chunk that's where overriding comes into play.
serializeHasMany: function(record, json, relationship) {
var key = relationship.key;
var relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);
if (relationshipType === 'manyToNone' || relationshipType === 'manyToMany' ||
relationshipType === 'manyToOne') {
json[key] = get(record, key).mapBy('id');
// TODO support for polymorphic manyToNone and manyToMany relationships
}
},
And your save should be like this
var store = this.get('store'),
child, toy;
child = store.createRecord('child', {
name: 'Herbert'
});
toy = store.createRecord('toy', {
name: 'Kazoo'
});
child.get('toys').pushObject(toy);
child.save().then(function(){
toy.save();
},
function(err){
alert('error', err);
});
I needed a deep object, instead of a side-loaded one, so based on kingpin2k's answer, I came up with this:
DS.JSONSerializer.reopen({
serializeHasMany: function(record, json, relationship) {
var key = relationship.key,
property = Ember.get(record, key),
relationshipType = DS.RelationshipChange.determineRelationshipType(record.constructor, relationship);
if (property && relationshipType === 'manyToNone' || relationshipType === 'manyToMany' ||
relationshipType === 'manyToOne') {
// Add each serialized nested object
json[key] = [];
property.forEach(function(item, index){
json[key].push(item.serialize());
});
}
}
});
Now when you call child.serialize(), it will return this object:
{
child: {
name: "Herbert",
toys: [
{
name: 'Kazoo'
}
]
}
}
Which is what I need. Here's the jsfiddle with it in action: http://jsfiddle.net/jgillick/LNXyp/8/