NextJs Server API File Access - reactjs

I am struggling with reading files on the NextJS API.
My folder structure is as follows:
- data
- file.txt
- pages
- api
- generateFile.ts
I want to be able to read file.txt inside the generateFile.ts but I am getting:
Error: ENOENT: no such file or directory
I read the files with the use of fs.readFile wrapped in promisify.
I cannot import that single file as the data folder contains multiple files and its not necessary to import them all every time the function gets called.
How can I make sure the data folder is included in the server build and can be read from?
I have been exploring and found that:
. directory contains
[
'.env.example',
'.next',
'___next_launcher.cjs',
'___vc',
'node_modules',
'package.json'
]
and "/" contains:
[
'THIRD-PARTY-LICENSES.txt',
'bin',
'boot',
'dev',
'etc',
'home',
'lambda-entrypoint.sh',
'lib',
'lib64',
'media',
'mnt',
'opt',
'proc',
'root',
'run',
'sbin',
'srv',
'sys',
'tmp',
'usr',
'var'
]
EDIT
Well I have tried reading the contracts just by getting a path to that dir, added one line of code path.join(process.cwd(), data); and somehow data folder now got included in the build. Why?

Related

Flatten build directory structure in React Build Folder

Im wondering if there is a way to completely flatten the folder structure within the build directory of a create-react-app. Im attempting to do a quick port over of my app onto a sharepoint site but the sharepoint site does not play well with the static/ folder and its children folders such as css/, js/, and media/ is there a way to do a npm run build such that the paths created are all within the same folder?
for example the asset-manifest.json currently shows files like this
{
"files": {
"main.css": "./static/css/main.ad49c970.chunk.css",
"main.js": "./static/js/main.bfd3a96b.chunk.js",
"main.js.map": "./static/js/main.bfd3a96b.chunk.js.map",
"runtime-main.js": "./static/js/runtime-main.c0915b68.js",
"runtime-main.js.map": "./static/js/runtime-main.c0915b68.js.map",
"static/css/2.d9ad5f5c.chunk.css": "./static/css/2.d9ad5f5c.chunk.css",
"static/js/2.3c65d00b.chunk.js": "./static/js/2.3c65d00b.chunk.js",
"static/js/2.3c65d00b.chunk.js.map": "./static/js/2.3c65d00b.chunk.js.map",
"index.html": "./index.html",
"precache-manifest.8fc2b5edb6f6029051530a49398ae5c2.js": "./precache-manifest.8fc2b5edb6f6029051530a49398ae5c2.js",
"service-worker.js": "./service-worker.js",
"static/css/2.d9ad5f5c.chunk.css.map": "./static/css/2.d9ad5f5c.chunk.css.map",
"static/css/main.ad49c970.chunk.css.map": "./static/css/main.ad49c970.chunk.css.map",
"static/js/2.3c65d00b.chunk.js.LICENSE.txt": "./static/js/2.3c65d00b.chunk.js.LICENSE.txt",
"static/media/logo.svg": "./static/media/logo.5d5d9eef.svg"
},
"entrypoints": [
"static/js/runtime-main.c0915b68.js",
"static/css/2.d9ad5f5c.chunk.css",
"static/js/2.3c65d00b.chunk.js",
"static/css/main.ad49c970.chunk.css",
"static/js/main.bfd3a96b.chunk.js"
]
}
Ideally I just want everything under the root/ folder without static/js/ etc.

Using file-loader to load binary file in react

I am trying to load a file from a folder using a name from react props.
when I write this:
import FileImage from '!!file-loader!../public/uploads/file-1589134024728.file';
<img src={FileImage}/>
everything works (but is static). In elements I see:
<img src="368d70b7855164f45e8b1c68db4d549c.file">
[![working][1]][1]
But using this:
src={`!!file-loader!../public/uploads/${file}`}
will show as
<img src="!!file-loader!../public/uploads/file-1589134024728.file">
[![not working][2]][2]
GET http://localhost:8080/public/uploads/file-1589134024728.file 404 (Not Found)
I also tried
src={`../public/uploads/${file}`}
while webpack.config.js looks like that:
{
test: /\.(woff(2)?|ttf|eot|svg|file)(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'fonts/'
}
}
]
}```
I believe I somehow need to return [contenthash].[ext] but how?
[1]: https://i.stack.imgur.com/ZDx6l.png
[2]: https://i.stack.imgur.com/lCnMd.png
These files look like they are uploaded, which means you don't have access to their names at build time. This is ok, you have the file name.
You need to make sure that the /uploads/ directory is available through your HTTP server, and then you can use src={'/uploads/' + file} to load the resource from that location.
Even if these are not user uploads, but static files that you provide, then you can put them in your public/uploads directory and still just link them using their location on the webserver. It's hard to be sure without knowing where file comes from.

TypeScript with Relay: Can't resolve generated module

In my MessageItem.tsx component I have the following code:
const data = useFragment(
graphql`
fragment MessageItem_message on Message {
date
body
}
`,
message as any
);
After running relay-compiler --src ./src --schema ../../schema.graphql --language typescript --artifactDirectory ./src/__generated__, a module named MessageItem_message.graphql.ts gets generated.
But when I run the app it gives me an error:
Failed to compile.
./src/components/MessageItem.tsx
Module not found: Can't resolve
'./__generated__/MessageItem_message.graphql'
The reason is only components at the src root can refer to the right path (./__generated__), whereas components in a folder actually need to refer to the path (../__generated__) but it's not doing so.
How can I configure the path?
Edit .babelrc to point to the artifactDirectory
// .babelrc
{
"plugins": [
[
"relay",
{
"artifactDirectory": "./src/ui/graphql/types"
}
]
]
}
Remove "--artifactDirectory ./src/__generated__" from the relay-compiler options.
By default it seems the Relay compiler puts a "__generated__" directory in the directory with any source code containing GraphQL.
As a result any "./__generated__" references anywhere and at any level in the source code hierarchy now work as they should.
Thanks to #ThibaultBoursier for the pointer.
PS I wonder if the --artifcactDirectory option is just meant to be used to change the name of the artifact directory, rather than its location?
Just moments ago I ran into the same issue. The reason is that the relay-compiler is using the artifactDirectory setting to decide where to put the generated files, but the babel-plugin-relay exposing the graphql tag needs to get the very same argument otherwise it just attempts to include a colocated relative file.
I fixed it in my case by configuring the plugin with a babel-plugin-macros.config.js file as follows (where the artifactDirectory is the same as the one supplied to the relay-compiler):
module.exports = {
relay: {
artifactDirectory: "./src/ui/graphql/types",
},
};
This solution assumes you are using the macro via babel-plugin-macros, otherwise you might need to supply that argument via the .babelrc file but I have no experience with that unfortunately.

React - synchronous txt file to string?

I'm absolutely baffled by this one...
In my React project with create-react-app, I have a standalone js file in which I'd like to read a string from a txt file. The txt file is part of a project and not on a server.
I can't seem to find any answers of how to complete this seemingly trivial task in a synchronous manner. These would seem like obvious options:
import text from './data/text.txt';
const text = require('./data/text.txt');
Both lines above return a new path that includes /static/media/, which I can access through localhost in the browser, but that doesn't help me.
I can use JSON but it's almost a matter of principle at this point. It just seems ridiculous that I can't read a simple txt file.
You can use webpack raw-loader to directly import raw files into your project.
Install:
$ npm install raw-loader --save-dev
Config:
// webpack.config.js
module.exports = {
module: {
rules: [
{
test: /\.txt$/i,
use: 'raw-loader',
},
],
},
};
Usage:
import text from './data/text.txt';
console.log(text); // This line will print out the content of the text file in the console

Dynamically Loading Plugin Configuration Files in CakePHP 3

Question: How do I load a configuration file from a Plugin/config Directory?
Demo Project: https://github.com/CakePHPKitchen/CakeDC-Users-Permissions-Example
I am using CakeDC/users plugin and it has a permissions.php file that it loads the RBAC permissions from. From what I can tell, it either loads the default permissions file that is in the user plugin's config folder OR it loads the permissions.php file from the app/config folder.
Now for my app skeleton I have a bunch of permissions in the app/config/permissions.php, however, I do not want to modify that file as I will be doing git pulls from the upstream repo and I would like to avoid conflicts.
So what I would like to do is, in the app skeleton bootstrap
I would like to
foreach(Plugin::loaded() as $plugin) {
$path = Plugin::path($plugin) . 'config/permissions.php';
if(file_exists($path)) {
Configure::load($path, 'default', true);
}
}
But I am getting the following error....
Error: The application is trying to load a file from the /Users/jlroberts/Projects/JeffreyLRobertsCom/CakePHPKitchen/PluginDemos/plugins/SharpAgent/config/permissions plugin.
Make sure your plugin /Users/jlroberts/Projects/JeffreyLRobertsCom/CakePHPKitchen/PluginDemos/plugins/SharpAgent/config/permissions is in the /Users/jlroberts/Projects/JeffreyLRobertsCom/CakePHPKitchen/PluginDemos/plugins/ directory and was loaded.
Any ideas on how I can load the permissions.php file from the Plugin/config directory?
EDITED: You can load permissions.php file from the Plugin as it is doing now, but change the contents of permissions.php to preserve existing permissions defined in configuration, for example:
config/permissions.php
$permissions = [
// add your app permissions here
[
// ...
],
];
// there are more permissions in this config key, defined across your plugins
$morePermissions = \Cake\Core\Configure::read('MyPermissions');
$allPerms = array_merge($permissions, $morePermissions);
return ['CakeDC/Auth.permissions' => $allPerms];
Then inside each plugin you could have:
YOUR_PLUGIN/config/bootstrap.php
$permissions = \Cake\Core\Configure::read('MyPermissions');
$someMorePermissions = [
[
// permissions injected into the app from this plugin
]
];
$permissions = array_merge((array)$permissions, $someMorePermissions);
\Cake\Core\Configure::write('MyPermissions', $permissions);
Allowing each plugin to dynamically inject/manage permissions into the app.
I've created a c9.io environment with this code here https://ide.c9.io/steinkel/users-35-custom-permissions

Resources