UNPKG

react-ark-tools

Version:

Boilerplate and tooling for JavaScript application development with React

91 lines (76 loc) 2.73 kB
/** * React App SDK (https://github.com/kriasoft/react-app) * * Copyright © 2015-present Kriasoft, LLC. All rights reserved. * * This source code is licensed under the MIT license found in the * LICENSE.txt file in the root directory of this source tree. */ import React from 'react'; function decodeParam(val) { if (!(typeof val === 'string' || val.length === 0)) { return val; } try { return decodeURIComponent(val); } catch (err) { if (err instanceof URIError) { err.message = `Failed to decode param '${val}'`; err.status = 400; } throw err; } } // Match the provided URL path pattern to an actual URI string. For example: // matchURI({ path: '/posts/:id' }, '/dummy') => null // matchURI({ path: '/posts/:id' }, '/posts/123') => { id: 123 } function matchURI(route, path) { const match = route.pattern.exec(path); if (!match) { return null; } const params = Object.create(null); for (let i = 1; i < match.length; i++) { params[route.keys[i - 1].name] = match[i] !== undefined ? decodeParam(match[i]) : undefined; } return params; } // Find the route matching the specified location (context), fetch the required data, // instantiate and return a React component function resolve(routes, context) { for (const route of routes) { const params = matchURI(route, context.error ? '/error' : context.pathname); if (params) { // Check if the route has any data requirements, for example: // // { // path: '/tasks/:id', // data: { task: 'GET /api/tasks/$id' }, // component: './routes/TaskDetails' // } // if (route.data) { // Load route component and all required data in parallel const keys = Object.keys(route.data); return Promise.all([ route.load(), ...keys.map(key => { const query = route.data[key]; const method = query.substring(0, query.indexOf(' ')); // GET const url = query.substr(query.indexOf(' ') + 1); // /api/tasks/$id // TODO: Replace query parameters with actual values coming from `params` return fetch(url, { method }).then(resp => resp.json()); }), ]).then(([Component, ...data]) => { const props = keys.reduce((result, key, i) => ({ ...result, [key]: data[i] }), {}); return <Component route={route} error={context.error} {...props} />; }); } return route.load().then(Component => <Component route={route} error={context.error} />); } } const error = new Error('Page not found'); error.status = 404; return Promise.reject(error); } export default { resolve };