How can I post a container in Storage api from loopback? - javascript

I already have declared my datasource ,my model and the connector between these.
My model
{
"name": "container",
"base": "Model",
"idInjection": true,
"options": {
"validateUpsert": true
},
"properties": {},
"validations": [],
"relations": {},
"acls": [],
"methods": {}
}
Datasource
"storage": {
"name": "storage",
"connector": "loopback-component-storage",
"provider": "filesystem",
"root": "./server/storage"
}
My provider
{
"filesystem": {
"root": "./server/storage"
}
}
And the Connector
"container": {
"dataSource": "storage",
"public": true
}
I try posting a object like {"Object":"container1"} into path "./server/storage" but I get the following error from callback.
{
"error": {
"statusCode": 500,
"name": "TypeError",
"message": "Path must be a string. Received undefined",
"stack": "TypeError: Path must be a string. Received undefined.."
}
}
Please who can help me to find my issue? Thanks!

You can also use "name" instead of "Object" as key in your JSON object to create a new container/directory using the API.
POST /api/containers {"name":"container1"}

The way to post a container is, without using the loopback api. Create a folder that is gonna be the container into your provider path (being filesystem).
As simple as that!

If you need a programmatic way to add new containers, let's say for example you want to create a filesystem of sorts for new users. You can use the route below. "Container" is the name I called my Model, you can call yours whatever you'd like.
POST localhost:3000/api/container
Inside the body of the post request you have to have an attribute name and the value of the name can be the new container you're creating. The Strongloop/Loopback documentation, which can be found here, is not accurate and neither is the error you get back when you try to post it with their directions.
"error": {
"statusCode": 500,
"name": "TypeError",
"message": "Path must be a string. Received undefined"
}
An excerpt of the code to send a post request to create a new container is also below.
var request = require("request");
var options = {
method: 'POST',
url: 'http://localhost:3000/api/containers',
body: { name: 'someNewContainer' },
json: true
};
request(options, function (error, response, body) {
if (error) throw new Error(error);
console.log(body);
});

Related

Use variables in Azure Functions out binding

I'm using Azure functions with javascript, and i would like to modify the out binding of path in my functions. For example this is my function.json:
{
"bindings": [
{
"authLevel": "function",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"name": "outputBlob",
"path": "container/{variableCreatedInFunction}-{rand-guid}",
"connection": "storagename_STORAGE",
"direction": "out",
"type": "blob"
}
]
I Would like to set {variableCreatedInFunction} in index.js, for example:
module.exports = async function (context, req) {
const data = req.body
const date = new Date().toISOString().slice(0, 10)
const variableCreatedInFunction = `dir/path/${date}`
if (data) {
var responseMessage = `Good`
var statusCode = 200
context.bindings.outputBlob = data
} else {
var responseMessage = `Bad`
var statusCode = 500
}
context.res = {
status: statusCode,
body: responseMessage
};
}
Couldn't find any way to this, is it possible?
Bindings are resolved before the function executes. You can use {DateTime} as a binding expression. It will by default be yyyy-MM-ddTHH-mm-ssZ. You can use {DateTime:yyyy} as well (and other formatting patterns, as needed).
Imperative bindings (which is what you want to achieve) is only available in C# and other .NET languages, the docs says:
Binding at runtime In C# and other .NET languages, you can use an
imperative binding pattern, as opposed to the declarative bindings in
function.json and attributes. Imperative binding is useful when
binding parameters need to be computed at runtime rather than design
time. To learn more, see the C# developer reference or the C# script developer reference.
MS might've added it to JS as well by now, since I'm pretty sure I read that exact section more than a year ago, but I can't find anything related to it. Maybe you can do some digging yourself.
If your request content is JSON, the alternative is to include the path in the request, e.g.:
{
"mypath":"a-path",
"data":"yourdata"
}
You'd then be able to do declarative binding like this:
{
"name": "outputBlob",
"path": "container/{mypath}-{rand-guid}",
"connection": "storagename_STORAGE",
"direction": "out",
"type": "blob"
}
In case you need the name/path to your Blob, you'd probably have to chain two functions together, where one acts as the entry point and path generator, while the other is handling the Blob (and of course the binding).
It would go something like this:
Declare 1st function with HttpTrigger and Queue (output).
Have the 1st function create your "random" path containing {date}-{guid}.
Insert a message into the Queue output with the content {"mypath":"2020-10-15-3f3ecf20-1177-4da9-8802-c7ad9ada9a33", "data":"some-data"} (replacing the date and guid with your own generated values, of course...)
Declare 2nd function with QueueTrigger and your Blob-needs, still binding the Blob path as before, but without {rand-guid}, just {mypath}.
The mypath is now used both for the blob output (declarative) and you have the information available from the queue message.
It is not possiable to set dynamic variable in .js and let the binding know.
The value need to be given in advance, but this way may achieve your requirement:
index.js
module.exports = async function (context, req) {
context.bindings.outputBlob = "This is a test.";
context.done();
context.res = {
body: 'Success.'
};
}
function.json
{
"bindings": [
{
"authLevel": "anonymous",
"type": "httpTrigger",
"direction": "in",
"name": "req",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
},
{
"name": "outputBlob",
"path": "test/{test}",
"connection": "str",
"direction": "out",
"type": "blob"
}
]
}
local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"str":"DefaultEndpointsProtocol=https;AccountName=0730bowmanwindow;AccountKey=xxxxxx;EndpointSuffix=core.windows.net"
}
}
Or you can just put the output logic in the body of function. Just use the javascript sdk.

Graphql - creating a schema from a generated JSON file

I'm trying to create a custom graphql schema to use on my graphql yoga server. The graphql yoga server is just a proxy to another graphql API from which I have managed to retrieve a schema from in JSON format. Here is a preview of what that schema looks like:
{
"data": {
"__schema": {
"queryType": {
"name": "Query"
},
"mutationType": null,
"subscriptionType": null,
"types": [
{
"kind": "OBJECT",
"name": "Core",
"description": null,
"fields": [
{
"name": "_meta",
"description": null,
"args": [],
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "OBJECT",
"name": "Meta",
"ofType": null
}
},
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "_linkType",
"description": null,
"args": [],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": false,
"deprecationReason": null
}
],
"inputFields": null,
"interfaces": [
{
I now want to take this generated JSON schema and use it to create a graphql schema to use in my graphql yoga server. I believe the correct way to do this is by using the new GraphQLSchema method from graphql along with a root query. Here is my code attempting this:
schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: schema.data.__schema
})
});
The above code gives me the following error:
Error: Query.mutationType field config must be an object
Not entirely sure where it's going wrong or if this is the proper approach to creating a graphql schema from generated JSON?
The JSON you have is the results of an introspection query. Unfortunately, introspection will not allow you to copy a remote schema. That's because while it does identify what fields exist in a schema, it does not tell you anything about how they should be executed. For example, based on the snippet you posted, we know the remote server exposes a _meta query that returns a Meta type -- but we don't know what code to run to resolve the value returned by the query.
Technically, it's possible to pass the results of an introspection query to buildClientSchema from the graphql/utilities module. However, the schema will not be executable, as the docs point out:
Given the result of a client running the introspection query, creates and returns a GraphQLSchema instance which can be then used with all GraphQL.js tools, but cannot be used to execute a query, as introspection does not represent the "resolver", "parse" or "serialize" functions or any other server-internal mechanisms.
If you want to create a proxy to another GraphQL endpoint, the easiest way is to use makeRemoteExecutableSchema from graphql-tools.
Here's the example based on the docs:
import { HttpLink } from 'apollo-link-http';
import fetch from 'node-fetch';
const link = new HttpLink({ uri: 'http://your-endpoint-url/graphql', fetch });
async function getRemoteSchema () {
const schema = await introspectSchema(link);
return makeRemoteExecutableSchema({
schema,
link,
});
}
The resulting schema is a GraphQLSchema object that can be used like normal:
import { GraphQLServer } from 'graphql-yoga'
async function startServer () {
const schema = await introspectSchema(link);
const executableSchema = makeRemoteExecutableSchema({
schema,
link,
});
const server = new GraphQLServer({ schema: executableSchema })
server.start()
}
startServer()
graphql-tools also allows you to stitch schemas together if you not only wanted to proxy the existing endpoint, but wanted to add on to it as well.

How to store Exception/Error from Azure function js?

I have created an Azure function to save data in SQL database from Iot Hub that is working fine, Now I want to save Exception and Error to Azure storage Table so for that I have added try{ } catch(err){} but that is not working. please correct me. Thanks!
my function is here
module.exports = function (context, iotHubMessage) {
try {
var strMsg = JSON.stringify(iotHubMessage);
context.log('Message received: ' + strMsg);
var ob1 = { "employee_idw": 444, "last_name": "Teller", "first_name": "Saara", "age": 34, "salary": 87000 };
//I misspelled 'employee_idw' to generate error
var ob2 = { "employee_id": 555, "last_name": "Teller", "first_name": "Saara", "age": 31, "salary": 87000 };
ob1.EventProcessedUtcTime = new Date;
ob2.EventProcessedUtcTime = new Date;
var arr = [];
arr.push(ob1);
arr.push(ob2);
context.bindings.outputTable = arr;
context.done();
} catch (err) {
context.log('CCC Error' + err); // even can not see this message in log
context.bindings.error= { "partitionKey": partitionKey, "rowKey": rowKey, "data": err };
}
};
see this is JSON file
{
"bindings": [
{
"type": "eventHubTrigger",
"name": "myEventHubMessage",
"path": "myeventhub",
"consumerGroup": "$Default",
"connection": "PBCorIOTHub_events_IOTHUB",
"cardinality": "many",
"direction": "in"
},
{
"type": "apiHubTable",
"name": "outputTable",
"dataSetName": "default",
"tableName": "employees",
"connection": "sql_SQL",
"direction": "out"
},
{
"type": "table",
"name": "error",
"tableName": "dddtTest",
"connection": "cccteststr_STORAGE",
"direction": "out"
}
],
"disabled": false
}
Are you using Azure SQL or Azure table storage to store the data? From your code it looks like you are using Azure table storage. The reason i ask is because a changed property name would not cause an error in function. Instead the table storage would create a new property with misspelled name.
Like Mikhail suggested the to store an error caused inside of a function all you have to do is create another output binding and assign the exception to it.
However not all exceptions occur inside of a function context. For example an error in function.json configuration could cause a error connecting to storage. This would cause function execution to fail outside of function code context. Azure functions has direct integration with Application Insights and can help monitor what you are looking for. Here is a blog post that can shows how to configure Application Insights.
https://blogs.msdn.microsoft.com/appserviceteam/2017/04/06/azure-functions-application-insights/

How to set recipients with Gmail's Node.js API

As simple as it may seem, I cannot seem to figure out how to set recipients of a draft with Google's Gmail API. The documentation says that a users.messages Resource object contains a payload object that contains a headers object, and that headers object contains name-value pairs.
// example from google's gmail API documentation
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": string,
"value": string
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
It is within these headers I presume you set the "To" part of a draft, since the documentation says
List of headers on this message part. For the top-level message part, representing the entire message payload, it will contain the standard RFC 2822 email headers such as To, From, and Subject.
however, when I make a request that looks something like this
"payload" : {
"headers" : [
{
"name" : "To",
"value" : "me"
// "me" should direct the draft to myself
}
]
}
the To part of the draft is still left empty. Any solution or advice?
In your request you have this:
"headers" : [ "name" : "To", "value" : "me" ]
"headers" is supposed to be an array of objects but your array contains none.
Instead, it should look like this:
"headers": [ { "name": "To", "value": "me" } ]
Just like their example:
"payload": {
"partId": string,
"mimeType": string,
"filename": string,
"headers": [
{
"name": "To",
"value": "me"
}
],
"body": users.messages.attachments Resource,
"parts": [
(MessagePart)
]
},
So, it appears that I was misinterpreting documentation on the Gmail API. When you send a request to drafts.create, you do need to supply is a users.messages Resource, however, not all of it is writable. Only threadId, labelIds, and raw are writable objects. As it turns out, you aren't supposed to use the payload at all to set the To, From, etc. You are supposed to include them in your raw.
My new code looks something like this
let create = (toAddress, subject, content, callback) => {
gmail.users.drafts.create(
{
'userId' : 'me',
'resource' : {
'message' : {
'raw' : base64.encodeURI(
`To:${toAddress}\r\n` + // Who were are sending to
`Subject:${subject}\r\n` + // Subject
`Date:\r\n` + // Removing timestamp
`Message-Id:\r\n` + // Removing message id
`From:\r\n` + // Removing from
`${content}` // Adding our actual message
)
}
}
},
(err, response) => {
// Do stuff with response
callback(err, response);
}
)
}

can't POST to github v3 API

I'm trying to create a public gist via javascript. I'm not using any authentication - this is all client-side.
var gist = {
"description": "test",
"public": true,
"files": {
"test.txt": {
"content": "contents"
}
}
};
$.post('https://api.github.com/gists', gist, function(data) {
});
The above code throws a 400: Bad Request - Problems parsing JSON. However, my JSON is valid. Any ideas?
Aha - I can't pass an object to $.post. It needs to be stringified first:
var gist = {
"description": "test",
"public": true,
"files": {
"test.txt": {
"content": "contents"
}
}
};
$.post('https://api.github.com/gists', JSON.stringify(gist), function(data) {});

Categories