Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support injecting multiple files into the executable #68

Closed
mxschmitt opened this issue Apr 21, 2023 · 12 comments
Closed

Support injecting multiple files into the executable #68

mxschmitt opened this issue Apr 21, 2023 · 12 comments
Labels
enhancement New feature or request

Comments

@mxschmitt
Copy link

mxschmitt commented Apr 21, 2023

What is the problem this feature will solve?

Projects which include multiple files or non-javascript files would benefit from it and would not have to bundle everything.

What is the feature you are proposing to solve the problem?

Support injecting multiple files, since right now its limited to inject a single file as per here.

What alternatives have you considered?

Bundling


Please add the single-executables label to it or suggest a better place to file this feature request.

@RaisinTen RaisinTen transferred this issue from nodejs/node Apr 21, 2023
@tony-go tony-go added the enhancement New feature or request label May 3, 2023
@joyeecheung
Copy link
Member

I am working on something along the lines. My current draft:

In the config file, we support a dictionary of assets, with ids that are later used in the API as keys, and path to the actual files as values:

{
  "assets": {
    "a.dat": "/path/to/a.dat",
    "b.txt": "/path/to/a.txt"
  }
}

At build time, we read these assets and add them to the preparation blob.

At runtime, users can get the assets back like this:

const { getAsset } = require('node:sea');
const a = getAsset('a.dat', 'buffer');  // Creates a copy
const b = getAsset('b.txt', 'utf-8');   // decode as an utf8 string, no copy

The API I have in mind is like this because I think it's probably not a good idea to return mutable data to users.

This can be a somewhat low level API as a first step - we can build VFS on top of this later (e.g. put some kind of archive as one of the assets)

Any thoughts?

@nodejs/single-executable-admins

@mxschmitt
Copy link
Author

I think that would work for us, we would then create the VFS abstraction in the user land for now. Last-modified timestamp would be probably good to keep that stored inside as well. Not sure about rwx permissions / user permissions, makes probably not a lot of sense.

@tony-go
Copy link
Member

tony-go commented Nov 13, 2023

Really great @joyeecheung 👏🏼

Looking forward to see the PR 🤩

@RaisinTen
Copy link
Contributor

This sounds like a good first step for the VFS 👍

@joyeecheung
Copy link
Member

I have a branch at https://github.com/joyeecheung/node/tree/sea-assets that contains an implementation of the proposal which is probably good to go, but I think I need to look into some of the SEA flaky tests issues before adding another SEA feature/test.

@robertsLando
Copy link

robertsLando commented Nov 21, 2023

@joyeecheung thanks for all your efforts with nodejs SEA feature!

What about supporting also multiple js files? I mean for structured applications bundle them on a single file could be complex, is there any thougts about that?

@joyeecheung
Copy link
Member

joyeecheung commented Nov 21, 2023

That should probably be layered on top of VFS, which can be layered on top of this lower-level thing.

@lukaslihotzki
Copy link

Exposing a native, dedicated API to read assets is a great idea. VFS patching can be done on top of this, possibly by including archives as assets. For this use case, it would make sense to (also) expose assets as Blob (not just as Buffer and String). Blobs can be sliced (and then be read asynchronously), which would allow reading specific files inside an archive on-demand. Also Blobs (and their slices) can be streamed, which would be nice when the archive is compressed.

Until such a native API is available, you can include (binary) files into a SEA by reading them with fs.readFileSync during snapshot creation (https://gist.github.com/lukaslihotzki/c60fef03d5a14d1c8723bc1251ede0ee).

@joyeecheung
Copy link
Member

An interface that returns a Blob sounds like a good idea.

joyeecheung added a commit to nodejs/node that referenced this issue Feb 2, 2024
When it's a short string, print it inline, otherwise print it
from a separate line. Also add the missing line breaks finally.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
joyeecheung added a commit to nodejs/node that referenced this issue Feb 2, 2024
With this patch:

Users can now include assets by adding a key-path dictionary
to the configuration as the `assets` field. At build time, Node.js
would read the assets from the specified paths and bundle them into
the preparation blob. In the generated executable, users can retrieve
the assets using the `sea.getAsset()` and `sea.getAssetAsBlob()` API.

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "assets": {
    "a.jpg": "/path/to/a.jpg",
    "b.txt": "/path/to/b.txt"
  }
}
```

The single-executable application can access the assets as follows:

```cjs
const { getAsset } = require('node:sea');
// Returns a copy of the data in an ArrayBuffer
const image = getAsset('a.jpg');
// Returns a string decoded from the asset as UTF8.
const text = getAsset('b.txt', 'utf8');
// Returns a Blob containing the asset.
const blob = getAssetAsBlob('a.jpg');
```

Drive-by: update the  documentation to include a section dedicated
to the injected main script and refer to it as "injected main
script" instead of "injected module" because it's a script, not
a module.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
joyeecheung added a commit to nodejs/node that referenced this issue Feb 2, 2024
This patch adds support for `sea.getRawAsset()` which is
similar to `sea.getAsset()` but returns the raw asset
in an array buffer without copying. Users should avoid
writing to the returned array buffer. If the injected
section is not marked as writable or not aligned,
writing to the raw asset is likely to result in a crash.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
rdw-msft pushed a commit to rdw-msft/node that referenced this issue Feb 9, 2024
When it's a short string, print it inline, otherwise print it
from a separate line. Also add the missing line breaks finally.

PR-URL: nodejs#50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
rdw-msft pushed a commit to rdw-msft/node that referenced this issue Feb 9, 2024
With this patch:

Users can now include assets by adding a key-path dictionary
to the configuration as the `assets` field. At build time, Node.js
would read the assets from the specified paths and bundle them into
the preparation blob. In the generated executable, users can retrieve
the assets using the `sea.getAsset()` and `sea.getAssetAsBlob()` API.

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "assets": {
    "a.jpg": "/path/to/a.jpg",
    "b.txt": "/path/to/b.txt"
  }
}
```

The single-executable application can access the assets as follows:

```cjs
const { getAsset } = require('node:sea');
// Returns a copy of the data in an ArrayBuffer
const image = getAsset('a.jpg');
// Returns a string decoded from the asset as UTF8.
const text = getAsset('b.txt', 'utf8');
// Returns a Blob containing the asset.
const blob = getAssetAsBlob('a.jpg');
```

Drive-by: update the  documentation to include a section dedicated
to the injected main script and refer to it as "injected main
script" instead of "injected module" because it's a script, not
a module.

PR-URL: nodejs#50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
rdw-msft pushed a commit to rdw-msft/node that referenced this issue Feb 9, 2024
This patch adds support for `sea.getRawAsset()` which is
similar to `sea.getAsset()` but returns the raw asset
in an array buffer without copying. Users should avoid
writing to the returned array buffer. If the injected
section is not marked as writable or not aligned,
writing to the raw asset is likely to result in a crash.

PR-URL: nodejs#50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
targos pushed a commit to nodejs/node that referenced this issue Feb 15, 2024
When it's a short string, print it inline, otherwise print it
from a separate line. Also add the missing line breaks finally.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
targos pushed a commit to nodejs/node that referenced this issue Feb 15, 2024
With this patch:

Users can now include assets by adding a key-path dictionary
to the configuration as the `assets` field. At build time, Node.js
would read the assets from the specified paths and bundle them into
the preparation blob. In the generated executable, users can retrieve
the assets using the `sea.getAsset()` and `sea.getAssetAsBlob()` API.

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "assets": {
    "a.jpg": "/path/to/a.jpg",
    "b.txt": "/path/to/b.txt"
  }
}
```

The single-executable application can access the assets as follows:

```cjs
const { getAsset } = require('node:sea');
// Returns a copy of the data in an ArrayBuffer
const image = getAsset('a.jpg');
// Returns a string decoded from the asset as UTF8.
const text = getAsset('b.txt', 'utf8');
// Returns a Blob containing the asset.
const blob = getAssetAsBlob('a.jpg');
```

Drive-by: update the  documentation to include a section dedicated
to the injected main script and refer to it as "injected main
script" instead of "injected module" because it's a script, not
a module.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
targos pushed a commit to nodejs/node that referenced this issue Feb 15, 2024
This patch adds support for `sea.getRawAsset()` which is
similar to `sea.getAsset()` but returns the raw asset
in an array buffer without copying. Users should avoid
writing to the returned array buffer. If the injected
section is not marked as writable or not aligned,
writing to the raw asset is likely to result in a crash.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
@joyeecheung
Copy link
Member

Closed via nodejs/node#50960

@mxschmitt
Copy link
Author

Thats great, thank you, will try it out!

@mxschmitt
Copy link
Author

Tried it out and seems to work very well for us! 🚀

marco-ippolito pushed a commit to marco-ippolito/node that referenced this issue Feb 19, 2024
When it's a short string, print it inline, otherwise print it
from a separate line. Also add the missing line breaks finally.

PR-URL: nodejs#50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
marco-ippolito pushed a commit to marco-ippolito/node that referenced this issue Feb 19, 2024
With this patch:

Users can now include assets by adding a key-path dictionary
to the configuration as the `assets` field. At build time, Node.js
would read the assets from the specified paths and bundle them into
the preparation blob. In the generated executable, users can retrieve
the assets using the `sea.getAsset()` and `sea.getAssetAsBlob()` API.

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "assets": {
    "a.jpg": "/path/to/a.jpg",
    "b.txt": "/path/to/b.txt"
  }
}
```

The single-executable application can access the assets as follows:

```cjs
const { getAsset } = require('node:sea');
// Returns a copy of the data in an ArrayBuffer
const image = getAsset('a.jpg');
// Returns a string decoded from the asset as UTF8.
const text = getAsset('b.txt', 'utf8');
// Returns a Blob containing the asset.
const blob = getAssetAsBlob('a.jpg');
```

Drive-by: update the  documentation to include a section dedicated
to the injected main script and refer to it as "injected main
script" instead of "injected module" because it's a script, not
a module.

PR-URL: nodejs#50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
marco-ippolito pushed a commit to marco-ippolito/node that referenced this issue Feb 19, 2024
This patch adds support for `sea.getRawAsset()` which is
similar to `sea.getAsset()` but returns the raw asset
in an array buffer without copying. Users should avoid
writing to the returned array buffer. If the injected
section is not marked as writable or not aligned,
writing to the raw asset is likely to result in a crash.

PR-URL: nodejs#50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
richardlau pushed a commit to nodejs/node that referenced this issue Mar 25, 2024
When it's a short string, print it inline, otherwise print it
from a separate line. Also add the missing line breaks finally.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
richardlau pushed a commit to nodejs/node that referenced this issue Mar 25, 2024
With this patch:

Users can now include assets by adding a key-path dictionary
to the configuration as the `assets` field. At build time, Node.js
would read the assets from the specified paths and bundle them into
the preparation blob. In the generated executable, users can retrieve
the assets using the `sea.getAsset()` and `sea.getAssetAsBlob()` API.

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "assets": {
    "a.jpg": "/path/to/a.jpg",
    "b.txt": "/path/to/b.txt"
  }
}
```

The single-executable application can access the assets as follows:

```cjs
const { getAsset } = require('node:sea');
// Returns a copy of the data in an ArrayBuffer
const image = getAsset('a.jpg');
// Returns a string decoded from the asset as UTF8.
const text = getAsset('b.txt', 'utf8');
// Returns a Blob containing the asset.
const blob = getAssetAsBlob('a.jpg');
```

Drive-by: update the  documentation to include a section dedicated
to the injected main script and refer to it as "injected main
script" instead of "injected module" because it's a script, not
a module.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
richardlau pushed a commit to nodejs/node that referenced this issue Mar 25, 2024
This patch adds support for `sea.getRawAsset()` which is
similar to `sea.getAsset()` but returns the raw asset
in an array buffer without copying. Users should avoid
writing to the returned array buffer. If the injected
section is not marked as writable or not aligned,
writing to the raw asset is likely to result in a crash.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
richardlau pushed a commit to nodejs/node that referenced this issue Mar 25, 2024
When it's a short string, print it inline, otherwise print it
from a separate line. Also add the missing line breaks finally.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
richardlau pushed a commit to nodejs/node that referenced this issue Mar 25, 2024
With this patch:

Users can now include assets by adding a key-path dictionary
to the configuration as the `assets` field. At build time, Node.js
would read the assets from the specified paths and bundle them into
the preparation blob. In the generated executable, users can retrieve
the assets using the `sea.getAsset()` and `sea.getAssetAsBlob()` API.

```json
{
  "main": "/path/to/bundled/script.js",
  "output": "/path/to/write/the/generated/blob.blob",
  "assets": {
    "a.jpg": "/path/to/a.jpg",
    "b.txt": "/path/to/b.txt"
  }
}
```

The single-executable application can access the assets as follows:

```cjs
const { getAsset } = require('node:sea');
// Returns a copy of the data in an ArrayBuffer
const image = getAsset('a.jpg');
// Returns a string decoded from the asset as UTF8.
const text = getAsset('b.txt', 'utf8');
// Returns a Blob containing the asset.
const blob = getAssetAsBlob('a.jpg');
```

Drive-by: update the  documentation to include a section dedicated
to the injected main script and refer to it as "injected main
script" instead of "injected module" because it's a script, not
a module.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
richardlau pushed a commit to nodejs/node that referenced this issue Mar 25, 2024
This patch adds support for `sea.getRawAsset()` which is
similar to `sea.getAsset()` but returns the raw asset
in an array buffer without copying. Users should avoid
writing to the returned array buffer. If the injected
section is not marked as writable or not aligned,
writing to the raw asset is likely to result in a crash.

PR-URL: #50960
Refs: nodejs/single-executable#68
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Pending Triage
Development

No branches or pull requests

6 participants