How to create a list of wix media folder images with url and name - velo

Is there a way in wix to get a list of all media files (images) urls and names?
I would need this to upload it in a field of the content manager to link data records and images.

You can use the new mediaManager API:
From Wix enable the developper mode
Go to the code files (icon {} to the left), and create a new backend JS file named 'http-functions.js'
Edit this file and add the following code:
import { ok, badRequest } from 'wix-http-functions';
import { mediaManager } from 'wix-media-backend';
export function get_filesList(request) {
const response = {
"headers": {
"Content-Type": "application/json"
}
};
var filters = {};
var paging = {};
if (request.query) {
if ('folder' in request.query ) { //
filters.parentFolderId = request.query["folder"];
}
if ('limit' in request.query) {
paging.limit = request.query['limit'];
}
if ('skip' in request.query) {
paging.skip = request.query['skip'];
}
}
return mediaManager.listFiles(filters, null, paging)
.then((myFiles) => {
response.body = {
"filesList": myFiles
};
return ok(response);
})
.catch((err) => {
response.body = {
"error": err
};
return badRequest(response);
});
}
export function get_listFolders(request) {
const response = {
"headers": {
"Content-Type": "application/json"
}
};
var filters = {};
var paging = {};
if (request.query) {
if ('folder' in request.query ) { //
filters.parentFolderId = request.query["folder"];
}
if ('limit' in request.query) {
paging.limit = request.query['limit'];
}
if ('skip' in request.query) {
paging.skip = request.query['skip'];
}
}
return mediaManager.listFolders(filters, null, paging)
.then((myFolders) => {
response.body = {
"foldersList": myFolders
};
return ok(response);
})
.catch((err) => {
response.body = {
"error": err
};
return badRequest(response);
});
}
Publish the files
You can query your custom API from: https://www.your_website.com/_functions/filesList and https://www.your_website.com/_functions/foldersList and query parameters folderId, skip and limit for pagination.
Wix documentation:
https://support.wix.com/en/article/velo-exposing-a-site-api-with-http-functions
https://www.wix.com/velo/reference/wix-media-backend/mediamanager-obj/listfiles

Related

How to update CSV in each it blocks in Cypress

I want to update CSV file data (Ex: columns data like orderId, date etc...) in each it blocks of spec file. I have written code to update CSV inside Cypress.config.js file and calling cy.task from spec file. But everytime first it block updated CSV is passed to all other it blocks. Please let me know how can I achieve this
Under uploadOrders.cy.js
/// <reference types='Cypress'/>
import { ORDERS } from '../../selector/orders';
import BU from '../../fixtures/BU.json';
import Helper from '../../e2e/utils/Helper';
const helper = new Helper();
let getTodaysDate = helper.getTodaysDate(); // get today's date and store in getTodaysDate variable
let getTomorrowssDate = helper.getTomorrowsDate(); // get tomorrows's date and store in getTomorrowssDate variable
let getYesterdaysDate = helper.getYesterdaysDate(); // get tomorrows's date and store in getTomorrowssDate variable
describe('Upload Orders', () => {
// Before start executing all it blocks
before(() => {
cy.login(); //login code written in cypress commands.js file
cy.get(ORDERS.ORDER_ICON).click();
});
// Before start executing each it block
beforeEach(() => {
cy.writeFile('cypress/fixtures/finalCsvToBeUploaded.csv', ''); // clears the file before each it block executes
});
// First it block
it('Upload orders and check its successful', () => {
let csvData = {
orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
orderDate: getTomorrowssDate,
homebaseExecutionDate: getTomorrowssDate,
customerExecutionDate: getTomorrowssDate,
}
cy.readFile('cypress/fixtures/referenceCsvFile.csv')
.then((data) => {
cy.task('csvToJson', data)
.then(finalJsonArray => {
cy.task('updateCsvData', { csvData, finalJsonArray })
.then(finalUpdatedJsonArray => {
cy.log("Update JSON array: " + finalUpdatedJsonArray[0]['Order ID']);
cy.task('finalCsv', finalUpdatedJsonArray);
});
})
})
cy.get(ORDERS.ORDER_UPLOAD).click();
cy.attachCsvFile('finalCsvToBeUploaded.csv');
cy.validateToastMsg('Orders uploaded successfully');
cy.log('Order is uploaded successfully via csv file and orderId is ');
});
// Second it block
it('Upload orders and check validation for past customer execution date', () => {
cy.wait(5000);
let csvData = {
orderId: 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds(),
orderDate: getTomorrowssDate,
homebaseExecutionDate: getYesterdaysDate,
customerExecutionDate: getYesterdaysDate,
}
cy.readFile('cypress/fixtures/finalCsvToBeUploaded.csv')
.then((data) => {
cy.task('csvToJson', data)
.then(finalJsonArray => {
cy.task('updateCsvData', { csvData, finalJsonArray })
.then(finalUpdatedJsonArray => {
cy.log("Update JSON array: " + finalUpdatedJsonArray);
cy.task('finalCsv', finalUpdatedJsonArray);
});
})
})
cy.get(ORDERS.ORDER_UPLOAD).click();
cy.attachCsvFile('finalCsvToBeUploaded.csv');
cy.validateToastMsg('Orders uploaded successfully');
cy.log('Order is uploaded successfully via csv file and orderId is');
});
// After exection of all it blocks
after(() => {
// clear cookies and localStorage
cy.clearCookies();
cy.clearLocalStorage();
});
});
Under cypress.config.js file
const { defineConfig } = require("cypress");
const converter = require('json-2-csv');
const csv = require('csv-parser');
const fs = require('fs');
const { default: Helper } = require("./cypress/e2e/utils/Helper");
const csvToJson1 = require('convert-csv-to-json');
const helper = require("csvtojson");
module.exports = defineConfig({
chromeWebSecurity: false,
watchFileForChanges: false,
defaultCommandTimeout: 10000,
pageLoadTimeout: 50000,
viewportWidth: 1280,
viewportHeight: 800,
video: false,
screenshotOnRunFailure: true,
"reporter": "mochawesome",
"reporterOptions": {
"charts": true,
"overwrite": false,
"html": false,
"json": true,
"timestamp": 'dd_mm_yy_HH_MM_ss',
"reportDir": "cypress/reports/mochawesome-report"
},
e2e: {
//To invoke test runner to pick files from the below path
specPattern: 'cypress/e2e/**/*.cy.js',
setupNodeEvents(on, config) {
// implement node event listeners here
// return require('./cypress/plugins/index.js')(on, config)
// `on` is used to hook into various events Cypress emits
// `config` is the resolved Cypress config
require('#cypress/code-coverage/task')(on, config)
//Start full screen
on('before:browser:launch', (browser = {}, launchOptions) => {
console.log(launchOptions.args);
if (browser.family === 'chromium' && browser.name !== 'electron') {
launchOptions.args.push('--start-fullscreen');
}
if (browser.name === 'electron') {
launchOptions.preferences.fullscreen = true;
}
return launchOptions;
});
//Convert CSV to JSON
on('task', {
csvToJson(data) {
var lines = data.split("\n");
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < (lines.length); i++) {
var obj = {};
var currentline = lines[i].split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j].replace(/["']/g, "");
}
result.push(obj);
}
console.log(result);
return result;
}
})
// Write updated csv data into file
on('task', {
finalCsv(updatedJSON) {
converter.json2csvAsync(updatedJSON).then(updatedCsv => {
fs.writeFileSync('cypress/fixtures/finalCsvToBeUploaded.csv', updatedCsv);
}).catch(err => console.log(err));
return null;
}
});
//For log purpose; prints message in the console
on('task', {
log(message) {
console.log(message);
return null;
},
});
on('task', {
updateCsvData({ csvData, finalJsonArray }) {
let updatedJSON,orderIds = [];
for (let i = 0; i < (finalJsonArray.length); i++) {
if ('orderId' in csvData) {
orderIds[i] = csvData.orderId;
finalJsonArray[i]['Order ID'] = csvData.orderId;
}
else {
// orderIds[i] = 'OrderId_' + helper.getCurrentDateAndTimeInMiliseconds();
orderIds[i] = 'OrderId_' + Date.now();
finalJsonArray[i]['Order ID'] = orderIds[i];
}
if ('orderDate' in csvData) {
finalJsonArray[i]['Order Date'] = csvData.orderDate;
}
if ('homebaseExecutionDate' in csvData) {
finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
}
if ('customerExecutionDate' in csvData) {
finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
}
}
updatedJSON = finalJsonArray;
return updatedJSON;
}
})
on('task', {
updateCsvFile(csvData) {
const finalJsonArray = [];
let updatedJSON, orderIds = [];
//readFile
fs.createReadStream('cypress/fixtures/referenceCsvFile.csv')
.pipe(csv())
.on('data', (data) => finalJsonArray.push(data))
.on('end', () => {
console.log(finalJsonArray); // CSV converted to json object
//Logic to update json objects; for loop to update csv columns in json array
for (let i = 0; i < (finalJsonArray.length); i++) {
if ('orderId' in csvData) {
orderIds[i] = csvData.orderId;
finalJsonArray[i]['Order ID'] = csvData.orderId;
}
else {
orderIds[i] = 'OrderId_' + this.getCurrentDateAndTimeInMiliseconds();
finalJsonArray[i]['Order ID'] = orderIds[i];
}
if ('orderDate' in csvData) {
finalJsonArray[i]['Order Date'] = csvData.orderDate;
}
if ('homebaseExecutionDate' in csvData) {
finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
}
if ('customerExecutionDate' in csvData) {
finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
}
}
updatedJSON = finalJsonArray;
converter.json2csvAsync(updatedJSON).then(csvFile => {
fs.writeFileSync('cypress/fixtures/' + fileName, csvFile)
}).catch(err => console.log(err));
})
return orderIds;
}
})
return config;
}
}
});
In first it block, CSV file is updating but when controller comes to second it block - considering the same csv file which is updated in first it block but I need to update the csv file separately in second it block
Finally got the answer to my question:
csvData is an object where column data are stored
let csvData = {
orderDate: getTodaysDate,
homebaseExecutionDate: getTomorrowsDate,
customerExecutionDate: getTomorrowsDate
};
Common method to upload the file under commands.js.
Cypress.Commands.add('updateCsvFileData', (csvData, referenceFileName, updatedCsvFileName) => {
cy.readFile('cypress/fixtures/' + referenceFileName)
.then((data) => {
cy.wait(100).then(() => {
cy.task('csvToJson', data)
.then((finalJsonArray) => {
cy.wait(100).then(() => {
cy.task('updateCsvData', { csvData, finalJsonArray })
.then((finalUpdatedJsonArray) => {
cy.wait(100).then(() => {
cy.task('finalCsv', { finalUpdatedJsonArray, updatedCsvFileName })
});
})
})
})
})
})
})
node.js methods:
Convert CSV to JSON object
on('task', {
csvToJson(data) {
var lines = data.split("\n");
var result = [];
var headers = lines[0].split(",");
for (var i = 1; i < (lines.length); i++) {
var obj = {};
var currentline = lines[i].split(/,(?=(?:(?:[^"]*"){2})*[^"]*$)/);
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j].replace(/["']/g, "");
}
result.push(obj);
}
return result;
}
})
Write updated csv data into CSV file
on('task', {
finalCsv({ finalUpdatedJsonArray, updatedCsvFileName }) {
converter.json2csvAsync(finalUpdatedJsonArray).then(updatedCsv => {
fs.writeFile('cypress/fixtures/' + updatedCsvFileName, updatedCsv);
}).catch(err => console.log(err));
return null;
}
});
Update required fields in CSV file
on('task', {
updateCsvData({ csvData, finalJsonArray }) {
let updatedJSON, orderIds = [];
for (let i = 0; i < (finalJsonArray.length); i++) {
if (csvData.hasOwnProperty('orderId')) {
orderIds[i] = csvData.orderId;
finalJsonArray[i]['Order ID'] = csvData.orderId;
}
else {
let orderIdRandomNum = Date.now() + "_" + Math.floor((Math.random() * 9999) + 1);
orderIds[i] = 'OrderId_' + orderIdRandomNum;
orders[i] = orderIds[i];
finalJsonArray[i]['Order ID'] = orderIds[i];
}
if ('orderDate' in csvData) {
finalJsonArray[i]['Order Date'] = csvData.orderDate;
}
if ('homebaseExecutionDate' in csvData) {
finalJsonArray[i]['Homebase Execution Date'] = csvData.homebaseExecutionDate;
}
if ('customerExecutionDate' in csvData) {
finalJsonArray[i]['Customer Execution Date'] = csvData.customerExecutionDate;
}
if ('teamId' in csvData) {
finalJsonArray[i]['Team ID'] = csvData.teamId;
}
}
updatedJSON = finalJsonArray;
return updatedJSON;
}
})

Shopify storefront API GraphQL: How to get specific product data?

Note: I'm new to GraphQL.
Challenge: I use the Shopify Storefront API to create a selectbox of all our products. When a user selects a product in this selectbox, its metafields should be displayed on the page.
I managed to create that selectbox. But how would i display the product-specific data when a choice was made in the selectbox? See current code:
function apiCall(productQuery) {
return fetch('https://store//api/2022-04/graphql.json',
{
method: 'POST',
headers: {
'Content-Type': 'application/graphql',
'X-Shopify-Storefront-Access-Token': "xxx"
},
"body": productQuery
}
)
.then(
response => response.json()
);
}
function getProducts() {
const productQuery = `{ products(first: 250) { edges { node { id handle title } } } }`;
return apiCall(productQuery);
}
$(document).ready(function() {
const product_selector_container = $('.product_selector_container');
getProducts().then(response => {
product_selector_container.prepend("<select name='product_compatibility_selector' id='product_compatibility_selector'></select>");
const productSelect = $('#product_compatibility_selector');
const productSelectResult = $("#product_compatibility_result");
response.data.products.edges.forEach(product => {
const optionValues = `<option value="${product.node.handle}">${product.node.title}<option>`;
productSelect.append(optionValues);
});
$("#product_compatibility_selector").on('change', function() {
var selected = $(this).find('option:selected').text();
var selectedVal = $(this).find('option').val();
$(".chosen_product_title").text(selected);
response.data.products.edges.forEach(product => {
// HOW DO I REFERENCE THE CURRENT CHOSEN PRODUCT TO OUTPUT VARIOUS NODES?
const compatibility_result = `${product.node.title}`;
productSelectResult.append(compatibility_result);
});
});
});
});
Now that you have the handle of the selected produt to retrieve all the metafields of that produt you need to run another query, using the "query" parameter, something like this
{
products(first: 1, query:"handle:your-handle"){
edges{
node{
metafields(first:10){
edges{
node{
value
key
}
}
}
}
}
}
}
or
{
product(handle:"your_handle"){
title
metafield(key:"your_key", namespace:"your_space"){
value
}
}
}
If you want to parametrize your handle you may want to introduce variables in your query, like this
query($handle:String){
product(handle:$handle){
title
metafield(key:"x",namespace:"y"){
id
value
}
}
}
and with the variable object being like
{"handle":"your-handle"}
In the request instead of just sending the query you send an object like
{"query" : your-query, "variables" : variable-object}

Strapi: GraphQL ctx.state is undefined

I have a custom controller to replace a default querie named "groupedOrders"
but when I try to test the query the response is
"message": "Cannot read property 'user' of undefined",
the code in api/grouped-order/controllers/grouped-order.js is:
module.exports = {
byUser: async ctx => {
const user = ctx.state.user
const resTypeUser = await strapi.query('tipo-usuario').find({ _id: user.tipo_usuario })
var resGroupedOrder = { error: true }
if (resTypeUser[0].super_admin) {
resGroupedOrder = await strapi.query('grouped-order').find()
} else if (resTypeUser[0].cliente) {
resGroupedOrder = await strapi.query('grouped-order').find({ users_permissions_user: user._id })
}
return resGroupedOrder
}
};
and the code in api/grouped-order/config/schema.graphql.js is:
module.exports = {
definition: ``,
query: ``,
type: {},
resolver: {
Query: {
groupedOrders: {
description: "Retornar todos los pedidos dependiendo el tipo de usuario",
resolverOf: "application::grouped-order.grouped-order.byUser",
policies: [
'plugins::users-permissions.permissions',
],
resolver: async (obj, options, ctx) => {
return await strapi.controllers["grouped-order"].byUser(ctx);
}
}
},
},
}
the test that I try to run in http://localhost:1337/graphql is:
query groupedOrders($where:JSON){
groupedOrders(where:$where){
createdAt
detail
status
}
}
and the HTTP HEADERS:
{
"Authorization": "Bearer TOKENJWT"
}
Solved, I just add this code on my controller:
if (!ctx.state && ctx.request && ctx.request.header && ctx.request.header.authorization) {
const { id } = await strapi.plugins["users-permissions"].services.jwt.getToken(ctx);
ctx.state.user = await strapi.plugins['users-permissions'].services.user.fetchAuthenticatedUser(id);
}
we can add the code globally, like this: https://github.com/strapi/strapi/issues/9159#issuecomment-789484109

Firebase Function Returns Before All Callback functions complete execution

I'm using the Google Storage NodeJS client library to list GCS Bucket paths.
Here's the code to the Firebase Function:
import * as functions from 'firebase-functions';
import { Storage } from '#google-cloud/storage';
import { globVars } from '../admin/admin';
const projectId = process.env.GCLOUD_PROJECT;
// shared global variables setup
const { keyFilename } = globVars;
// Storage set up
const storage = new Storage({
projectId,
keyFilename,
});
export const gcsListPath = functions
.region('europe-west2')
.runWith({ timeoutSeconds: 540, memory: '256MB' })
.https.onCall(async (data, context) => {
if (context.auth?.token.email_verified) {
const { bucketName, prefix, pathList = false, fileList = false } = data;
let list;
const options = {
autoPaginate: false,
delimiter: '',
prefix,
};
if (pathList) {
options.delimiter = '/';
let test: any[] = [];
const callback = (_err: any, _files: any, nextQuery: any, apiResponse: any) => {
test = test.concat(apiResponse.prefixes);
console.log('test : ', test);
console.log('nextQuery : ', nextQuery);
if (nextQuery) {
storage.bucket(bucketName).getFiles(nextQuery, callback);
} else {
// prefixes = The finished array of prefixes.
list = test;
}
}
storage.bucket(bucketName).getFiles(options, callback);
}
if (fileList) {
const [files] = await storage
.bucket(bucketName)
.getFiles(options);
list = files.map((file) => file.name);
}
return { list }; //returning null as it exec before callback fns finish
} else {
return {
error: { message: 'Bad Request', status: 'INVALID_ARGUMENT' },
};
}
});
My problem is that my Firebase function returns the list (null) before all the callback functions finish execution.
Could someone spot and point out what needs to be changed/added to make the function wait for all the callback functions to finish. I've tried adding async/await but can't seem to get it right.
The reason for your error is that you use a callback. It's not awaited in the code. I would recommend to turn the callback code to a promise. Something like this.
import * as functions from "firebase-functions";
import { Storage } from "#google-cloud/storage";
import { globVars } from "../admin/admin";
const projectId = process.env.GCLOUD_PROJECT;
// shared global variables setup
const { keyFilename } = globVars;
// Storage set up
const storage = new Storage({
projectId,
keyFilename,
});
const getList = (bucketName, options) => {
return new Promise((resolve, reject) => {
let list;
let test: any[] = [];
const callback = (
_err: any,
_files: any,
nextQuery: any,
apiResponse: any
) => {
test = test.concat(apiResponse.prefixes);
console.log("test : ", test);
console.log("nextQuery : ", nextQuery);
if (nextQuery) {
storage.bucket(bucketName).getFiles(nextQuery, callback);
} else {
// prefixes = The finished array of prefixes.
list = test;
}
resolve(list);
};
try {
storage.bucket(bucketName).getFiles(options, callback);
} catch (error) {
reject(eror);
}
});
};
export const gcsListPath = functions
.region("europe-west2")
.runWith({ timeoutSeconds: 540, memory: "256MB" })
.https.onCall(async (data, context) => {
if (context.auth?.token.email_verified) {
const { bucketName, prefix, pathList = false, fileList = false } = data;
let list;
const options = {
autoPaginate: false,
delimiter: "",
prefix,
};
if (pathList) {
options.delimiter = "/";
list = await getList(bucketName, options);
}
if (fileList) {
const [files] = await storage.bucket(bucketName).getFiles(options);
list = files.map((file) => file.name);
}
return { list }; //returning null as it exec before callback fns finish
} else {
return {
error: { message: "Bad Request", status: "INVALID_ARGUMENT" },
};
}
});
I'm not sure if the part with fileList will work as expectedt. It looks like the API doesn't support await but only callbacks.
import * as functions from "firebase-functions";
import { GetFilesOptions, Storage } from "#google-cloud/storage";
import { globVars } from "../admin/admin";
const projectId = process.env.GCLOUD_PROJECT;
// shared global variables setup
const { keyFilename } = globVars;
// Storage set up
const storage = new Storage({
projectId,
keyFilename,
});
const getList = (bucketName: string, options: GetFilesOptions) => {
return new Promise((resolve, reject) => {
// let test: any[] = [];
let list: any[] = [];
const callback = (
_err: any,
_files: any,
nextQuery: any,
apiResponse: any
) => {
list = list.concat(apiResponse.prefixes);
console.log("list : ", list);
console.log("nextQuery : ", nextQuery);
if (nextQuery) {
storage.bucket(bucketName).getFiles(nextQuery, callback);
} else {
// prefixes = The finished array of prefixes.
resolve(list);
}
};
try {
storage.bucket(bucketName).getFiles(options, callback);
} catch (error) {
reject(error);
}
});
};
export const gcsListPath = functions
.region("europe-west2")
.runWith({ timeoutSeconds: 540, memory: "256MB" })
.https.onCall(async (data, context) => {
if (context.auth?.token.email_verified) {
const { bucketName, prefix, pathList = false, fileList = false } = data;
let list;
const options = {
autoPaginate: false,
delimiter: "",
prefix,
};
if (pathList) {
options.delimiter = "/";
list = await getList(bucketName, options);
}
if (fileList) {
const [files] = await storage.bucket(bucketName).getFiles(options);
list = files.map((file) => file.name);
}
return { list }; //returning null as it exec before callback fns finish
} else {
return {
error: { message: "Bad Request", status: "INVALID_ARGUMENT" },
};
}
});

How do I add recursive logic in resolvers using GraphQL mutations?

Is it possible to add logic in resolvers using GraphQL mutations?
I am trying to create a four-digit string as an alias for a post if the user does not provide it. Then, I would like to check the database to see if the four-digit string exists. If the string exists, I would like to create another four-digit string recursively.
At the moment, I'm exploring adding logic to mutations within resolvers, but I'm not sure if this is doable. I'm using these documents for my foundation: graphql.org sequelize.org
This is my current code block:
Working as of 12/4/2020
const MakeSlug = require("./services/MakeSlug");
const resolvers = {
Query: {
async allLinks(root, args, { models }) {
return models.Link.findAll();
},
async link(root, { id }, { models }) {
return models.Link.findByPk(id);
}
},
Mutation: {
async createLink(root, { slug, description, link }, { models }) {
if (slug !== undefined) {
const foundSlug = await models.Link.findOne({
where: { slug: slug }
});
if (foundSlug === undefined) {
return await models.Link.create({
slug,
description,
link,
shortLink: `https://shink.com/${slug}`
});
} else {
throw new Error(slug + " exists. Try a new short description.");
}
}
if (slug === undefined) {
const MAX_ATTEMPTS = 10;
let attempts = 0;
while (attempts < MAX_ATTEMPTS) {
attempts++;
let madeSlug = MakeSlug(4);
const foundSlug = await models.Link.findOne({
where: { slug: madeSlug }
});
if (foundSlug !== undefined) {
return await models.Link.create({
slug: madeSlug,
description,
link,
shortLink: `https://shink.com/${madeSlug}`
});
}
}
throw new Error("Unable to generate unique alias.");
}
}
}
};
module.exports = resolvers;
This is my full codebase.
Thank you!
A while loop solved the challenge. Thanks xadm.
const MakeSlug = require("./services/MakeSlug");
const resolvers = {
Query: {
async allLinks(root, args, { models }) {
return models.Link.findAll();
},
async link(root, { id }, { models }) {
return models.Link.findByPk(id);
}
},
Mutation: {
async createLink(root, { slug, description, link }, { models }) {
if (slug !== undefined) {
const foundSlug = await models.Link.findOne({
where: { slug: slug }
});
if (foundSlug === undefined) {
return await models.Link.create({
slug,
description,
link,
shortLink: `https://shink.com/${slug}`
});
} else {
throw new Error(slug + " exists. Try a new short description.");
}
}
if (slug === undefined) {
const MAX_ATTEMPTS = 10;
let attempts = 0;
while (attempts < MAX_ATTEMPTS) {
attempts++;
let madeSlug = MakeSlug(4);
const foundSlug = await models.Link.findOne({
where: { slug: madeSlug }
});
if (foundSlug !== undefined) {
return await models.Link.create({
slug: madeSlug,
description,
link,
shortLink: `https://shink.com/${madeSlug}`
});
}
}
throw new Error("Unable to generate unique alias.");
}
}
}
};
module.exports = resolvers;

Resources