I've run across several use cases where I want to store a function in a Postman collection variable and reference it from an endpoint. Here's one example:
// at collection level
const parameterizedSchema = (codes) => ({
type: 'object',
properties: {
code: { enum: codes },
label: { type: 'string' }
}
});
pm.collectionVariables.set('parameterizedSchema', parameterizedSchema)
// in endpoint
const genericSchema = pm.collectionVariables.get('parameterizedSchema');
const thisEndpointSchema = genericSchema(['foo', 'bar']);
pm.test('response has correct schema', function () {
const {data} = pm.response.json();
if (!tv4.validate(data, thisEndpointSchema)) {
console.error(tv4.error);
pm.expect.fail()
}
});
But I don't seem to be able to store functions in variables -- I get an error TypeError: paramterizedSchema is not a function.
Is it possible to store functions in Postman variables somehow?
Related
I am trying to pass data from the server to the client to load my app faster and prevent multiple calls to the database.
Via Fetch
SvelteKit is made to do this via the fetch function. This is great if you have an endpoint that allows for custom fetch. But what if you don't?
Firebase is a perfect example of not having a custom fetch function.
Cookies
I would think I could use cookies, but when I set the cookie, it just prints 'undefined' and never gets set.
<script lang="ts" context="module">
import Cookies from 'js-cookie';
import { browser } from '$app/env';
import { getResources } from '../modules/resource';
export async function load() {
if (browser) {
// working code would use JSON.parse
const c = Cookies.get('r');
return {
props: {
resources: c
}
};
} else {
// server
const r = await getResources();
// working code would use JSON.stringify
Cookies.set('resources', r);
// no cookies were set?
console.log(Cookies.get());
return {
props: {
resources: r
}
};
}
}
</script>
So my code loads correctly, then dissapears when the browser load function is loaded...
Surely there is a functioning way to do this?
J
So it seems the official answer by Rich Harris is to use and a rest api endpoint AND fetch.
routes/something.ts
import { getFirebaseDoc } from "../modules/posts";
export async function get() {
return {
body: await getFirebaseDoc()
};
}
routes/content.svelte
export async function load({ fetch }) {
const res = await fetch('/resources');
if (res.ok) {
return {
props: { resources: await res.json() }
};
}
return {
status: res.status,
error: new Error()
};
}
This seems extraneous and problematic as I speak of here, but it also seems like the only way.
J
You need to use a handler that injects the cookie into the server response (because load functions do not expose the request or headers to the browser, they are just used for loading props I believe). Example here: https://github.com/sveltejs/kit/blob/59358960ff2c32d714c47957a2350f459b9ccba8/packages/kit/test/apps/basics/src/hooks.js#L42
https://kit.svelte.dev/docs/hooks#handle
export async function handle({ event, resolve }) {
event.locals.user = await getUserInformation(event.request.headers.get('cookie'));
const response = await resolve(event);
response.headers.set('x-custom-header', 'potato');
response.headers.append('set-cookie', 'name=SvelteKit; path=/; HttpOnly');
return response;
}
FYI: This functionality was only added 11 days ago in #sveltejs/kit#1.0.0-next.267: https://github.com/sveltejs/kit/pull/3631
No need to use fetch!
You can get the data however you like!
<script context="module">
import db from '$/firebaseConfig'
export async function load() {
const eventref = db.ref('cats/whiskers');
const snapshot = await eventref.once('value');
const res = snapshot.val();
return { props: { myData: res.data } } // return data under `props` key will be passed to component
}
</script>
<script>
export let myData //data gets injected into your component
</script>
<pre>{JSON.stringify(myData, null, 4)}</pre>
Here's a quick demo on how to fetch data using axios, same principle applies for firebase: https://stackblitz.com/edit/sveltejs-kit-template-default-bpr1uq?file=src/routes/index.svelte
If you want to only load data on the server you should use an "endpoint" (https://kit.svelte.dev/docs/routing#endpoints)
My solution might solve it especially for those who work with (e.g: laravel_session), actually in your case if you want to retain the cookie data when loading on each endpoint.
What you should gonna do is to create an interface to pass the event on every api() call
interface ApiParams {
method: string;
event: RequestEvent<Record<string, string>>;
resource?: string;
data?: Record<string, unknown>;
}
Now we need to modify the default sveltekit api(), provide the whole event.
// localhost:3000/users
export const get: RequestHandler = async (event) => {
const response = await api({method: 'get', resource: 'users', event});
// ...
});
Inside your api() function, set your event.locals but make sure to update your app.d.ts
// app.d.ts
declare namespace App {
interface Locals {
r: string;
}
//...
}
// api.ts
export async function api(params: ApiParams) {
// ...
params.event.locals.r = response.headers.get('r')
});
Lastly, update your hooks.ts
/** #type {import('#sveltejs/kit').Handle} */
export const handle: Handle = async ({ event, resolve }) => {
const cookies = cookie.parse(event.request.headers.get('cookie') || '');
const response = await resolve(event);
if (!cookies.whatevercookie && event.locals.r) {
response.headers.set(
'set-cookie',
cookie.serialize('whatevercookie', event.locals.r, {
path: '/',
httpOnly: true
})
);
}
return response;
});
Refer to my project:
hooks.ts
app.d.ts
_api.ts
index.ts
The Problem
Looking at this GraphQL query,
query {
asset {
name
interfaces {
created
ip_addresses {
value
network {
name
}
}
}
}
}
How do I define a resolver for just the network field on ip_addresses?
My First Thought
Reading docs the give examples of single nested queries, e.g
const resolverMap = {
Query: {
author(obj, args, context, info) {
return find(authors, { id: args.id });
},
},
Author: {
posts(author) {
return filter(posts, { authorId: author.id });
},
},
};
So I thought - why not just apply this pattern to nested properties?
const resolverMap = {
Query: {
asset,
},
Asset: {
interfaces: {
ip_addresses: {
network: () => console.log('network resolver called'),
},
},
},
};
But this does not work, when I run the query - I do not see the console log.
Further Testing
I wanted to make sure that a resolver will always be called if its on root level of the query return type.
My hypothesis:
Asset: {
properties: () => console.log('properties - will be called'), // This will get called
interfaces: {
created: () => console.log('created - wont be called'),
ip_addresses: {
network_id: () => console.log('network - wont be called'),
},
},
},
And sure enough my console showed
properties - will be called
The confusing part
But somehow apollo is still using default resolvers for created and ip_addresses, as I can see the returned data in playground.
Workaround
I can implement "monolith" resolvers as follows:
Asset: {
interfaces,
},
Where the interfaces resolver does something like this:
export const interfaces = ({ interfaces }) =>
interfaces.map(interfaceObj => ({ ...interfaceObj, ip_addresses: ip_addresses(interfaceObj) }));
export const ip_addresses = ({ ip_addresses }) =>
ip_addresses.map(ipAddressObj => ({
...ipAddressObj,
network: network(null, { id: ipAddressObj.network_id }),
}));
But I feel that this should be handled by default resolvers, as these custom resolvers aren't actually doing anything, but passing data down to another resolver.
The resolver map passed to the ApolloServer constructor is an object where each property is the name of a type in your schema. The value of this property is another object, wherein each property is a field for that type. Each of those properties then maps to a resolver function for that specified field.
You posted a query without posting your actual schema, so we don't know what any of your types are actually named, but assuming the network field is, for example, Network, your resolver map would need to look something like:
const resolver = {
// ... other types like Query, IPAddress, etc. as needed
Network: {
name: () => 'My network name'
}
}
You can, of course, introduce a resolver for any field in the schema. If the field returns an object type, you return a JavaScript Object and can let the default resolver logic handle resolving "deeper" fields:
const resolvers = {
IPAddress: {
network: () => {
return {
name: 'My network name',
}
}
}
}
Or...
const resolvers = {
Interface: {
ip_addresses: () => {
return [
{
value: 'Some value',
network: {
name: 'My network name',
},
},
]
}
}
}
Where you override the default resolver just depends at what point the data returned from your root-level field no longer matches your schema. For a more detailed explanation of the default resolver behavior, see this answer.
I have an arrow function in my React-Redux application that dispatches just an action without a payload, which will wipe (Reset) a part of my Redux store. There's no HTTP (or Promises) involved.
export const resetSearch = () => dispatch => {
dispatch({
type: RESET_SEARCH
});
};
I want to test that it returns the correct Action type:
import * as actions from '../actions/actionCreators';
import * as types from '../actions/actionTypes';
describe('actions', () => {
it('should create an action to reset part of the store', () => {
const expectedAction = {
type: types.RESET_SEARCH
};
expect(actions.resetSearch()).toEqual(expectedAction);
});
});
The test is not passing because I need to return an Object but, instead, I send this anonimous arrow function. Here is the Jest output
Expected value to equal: {"type": "RESET_SEARCH"}
Received: [Function anonymous]
How should the test be?
All help will be apreaciated!
Thanks
Can you plese try below code snippet, It should do:
const expectedAction = {
type: types.RESET_SEARCH
};
let retnFunc = actions.resetSearch();
retnFunc((receivedAction)=>{
expect(receivedAction).toEqual(expectedAction);
});
Here resetSearch returns a function which gets called with the action object so just imitated the same.
Let me know if you need any more help!
I want to know if it is possible to change the default input parameters of builtin methods like 'create', but only for input (not using the hidden property) and only for this method. In this case, I want to suppress the "balance" parameter. In other words, in the pointed location, my api explorer needs to show the following:
{
"userId": "string"
}
I have managed change custom remote methods, like so:
Using the following code:
module.exports = function(User) {
User.makeDeposit = function(data, callback){
//Method logic
};
User.remoteMethod(
'makeDeposit',
{
http: {path: '/makedeposit', verb: 'post'},
returns: {type: User, default:'User', root: true},
accepts: {arg: 'req', type: 'object', default: prettyJSON(depositSchema), http: {source: 'body'}}
}
);
};
// Returns a pretty printed json
function prettyJSON(str){
return JSON.stringify(str, null, ' ');
}
// Input Schemas - Only used for API Explorer
var depositSchema = {};
depositSchema.userId = "hash123";
depositSchema.amount = 11.37;
But I cannot replicate for built-in methods. Any help?
How would I 'get' the value of a property that is declared inside another property that is inside an array that is inside an object...
Here is an example:
module.exports = function(app) {
var express = require('express');
var thingsRouter = express.Router();
thingsRouter.get('/', function(req, res) {
res.send(
{
thing: [
{
id: 1,
year: 2008,
property: {
id:1,
location:"somewhere",
assessments: [
{
assessment:{
otherId: 1,
value: 10,
}
}
]
}
}]
});
});
app.use('/api/things', thingsRouter);
};
I want to get value. How would I get that value in the controller?
If you need more info, please let me know.
If you really have THING stored on the global App variable, then you could access value in your controller by:
var value = App.THING.property.assessments[0].assessment.value;
I am wondering why you are storing this object as a global. Also, the way you are setting a glocal variable isn't consistent with the way things should be set up in ember-cli - instead you should use imports, exports and `services, but you'll have to provide more detail about what you are generally trying to do in order to get suggestions for a better architecture.