@ricsam/quickjs-fs 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,45 +1,72 @@
1
1
  # @ricsam/quickjs-fs
2
2
 
3
- ## ⚠️ IMPORTANT NOTICE ⚠️
4
-
5
- **This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
6
-
7
- This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
8
-
9
- ## Purpose
10
-
11
- This package exists to:
12
- 1. Configure OIDC trusted publishing for the package name `@ricsam/quickjs-fs`
13
- 2. Enable secure, token-less publishing from CI/CD workflows
14
- 3. Establish provenance for packages published under this name
15
-
16
- ## What is OIDC Trusted Publishing?
17
-
18
- OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
19
-
20
- ## Setup Instructions
21
-
22
- To properly configure OIDC trusted publishing for this package:
23
-
24
- 1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
25
- 2. Configure the trusted publisher (e.g., GitHub Actions)
26
- 3. Specify the repository and workflow that should be allowed to publish
27
- 4. Use the configured workflow to publish your actual package
28
-
29
- ## DO NOT USE THIS PACKAGE
30
-
31
- This package is a placeholder for OIDC configuration only. It:
32
- - Contains no executable code
33
- - Provides no functionality
34
- - Should not be installed as a dependency
35
- - Exists only for administrative purposes
36
-
37
- ## More Information
38
-
39
- For more details about npm's trusted publishing feature, see:
40
- - [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
41
- - [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
42
-
43
- ---
44
-
45
- **Maintained for OIDC setup purposes only**
3
+ File System Access API (OPFS-compatible).
4
+
5
+ ```typescript
6
+ import { setupFs, createNodeDirectoryHandle } from "@ricsam/quickjs-fs";
7
+
8
+ const handle = setupFs(context, {
9
+ getDirectory: async (path) => {
10
+ // Validate path access
11
+ if (!path.startsWith("/allowed")) {
12
+ throw new Error("Access denied");
13
+ }
14
+ return createNodeDirectoryHandle(`./sandbox${path}`);
15
+ },
16
+ });
17
+ ```
18
+
19
+ **Injected Globals:**
20
+ - `fs.getDirectory(path)` - Entry point for file system access
21
+ - `FileSystemDirectoryHandle`, `FileSystemFileHandle`
22
+ - `FileSystemWritableFileStream`
23
+
24
+ **Usage in QuickJS:**
25
+
26
+ ```javascript
27
+ // Get directory handle
28
+ const root = await fs.getDirectory("/data");
29
+
30
+ // Read a file
31
+ const fileHandle = await root.getFileHandle("config.json");
32
+ const file = await fileHandle.getFile();
33
+ const text = await file.text();
34
+ const config = JSON.parse(text);
35
+
36
+ // Write a file
37
+ const outputHandle = await root.getFileHandle("output.txt", { create: true });
38
+ const writable = await outputHandle.createWritable();
39
+ await writable.write("Hello, World!");
40
+ await writable.close();
41
+
42
+ // Directory operations
43
+ const subDir = await root.getDirectoryHandle("subdir", { create: true });
44
+ await root.removeEntry("old-file.txt");
45
+ await root.removeEntry("old-dir", { recursive: true });
46
+
47
+ // Iterate directory
48
+ for await (const [name, handle] of root.entries()) {
49
+ console.log(name, handle.kind); // "file" or "directory"
50
+ }
51
+ ```
52
+
53
+ #### Host Adapters
54
+
55
+ **Node.js/Bun adapter:**
56
+
57
+ ```typescript
58
+ import { createNodeDirectoryHandle } from "@ricsam/quickjs-fs";
59
+
60
+ const dirHandle = createNodeDirectoryHandle("/path/to/directory");
61
+ ```
62
+
63
+ **In-memory adapter (for testing):**
64
+
65
+ ```typescript
66
+ import { createMemoryDirectoryHandle } from "@ricsam/quickjs-fs";
67
+
68
+ const memFs = createMemoryDirectoryHandle({
69
+ "config.json": JSON.stringify({ debug: true }),
70
+ "data/users.json": JSON.stringify([]),
71
+ });
72
+ ```
@@ -0,0 +1,43 @@
1
+ // @bun @bun-cjs
2
+ (function(exports, require, module, __filename, __dirname) {var __defProp = Object.defineProperty;
3
+ var __getOwnPropNames = Object.getOwnPropertyNames;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __moduleCache = /* @__PURE__ */ new WeakMap;
7
+ var __toCommonJS = (from) => {
8
+ var entry = __moduleCache.get(from), desc;
9
+ if (entry)
10
+ return entry;
11
+ entry = __defProp({}, "__esModule", { value: true });
12
+ if (from && typeof from === "object" || typeof from === "function")
13
+ __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
14
+ get: () => from[key],
15
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
16
+ }));
17
+ __moduleCache.set(from, entry);
18
+ return entry;
19
+ };
20
+ var __export = (target, all) => {
21
+ for (var name in all)
22
+ __defProp(target, name, {
23
+ get: all[name],
24
+ enumerable: true,
25
+ configurable: true,
26
+ set: (newValue) => all[name] = () => newValue
27
+ });
28
+ };
29
+
30
+ // packages/fs/src/index.ts
31
+ var exports_src = {};
32
+ __export(exports_src, {
33
+ setupFs: () => import_setup.setupFs,
34
+ createNodeDirectoryHandle: () => import_node_adapter.createNodeDirectoryHandle,
35
+ createMemoryDirectoryHandle: () => import_memory_adapter.createMemoryDirectoryHandle
36
+ });
37
+ module.exports = __toCommonJS(exports_src);
38
+ var import_setup = require("./setup.ts");
39
+ var import_node_adapter = require("./node-adapter.ts");
40
+ var import_memory_adapter = require("./memory-adapter.ts");
41
+ })
42
+
43
+ //# debugId=A9E29D78C7B0FEDC64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "export { setupFs } from \"./setup.ts\";\nexport { createNodeDirectoryHandle } from \"./node-adapter.ts\";\nexport { createMemoryDirectoryHandle } from \"./memory-adapter.ts\";\n\nexport type {\n SetupFsOptions,\n FsHandle,\n HostDirectoryHandle,\n HostFileHandle,\n HostWritableFileStream,\n WriteParams,\n} from \"./types.ts\";\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAwB,IAAxB;AAC0C,IAA1C;AAC4C,IAA5C;",
8
+ "debugId": "A9E29D78C7B0FEDC64756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@ricsam/quickjs-fs",
3
+ "version": "0.2.0",
4
+ "type": "commonjs"
5
+ }
@@ -0,0 +1,12 @@
1
+ // @bun
2
+ // packages/fs/src/index.ts
3
+ import { setupFs } from "./setup.ts";
4
+ import { createNodeDirectoryHandle } from "./node-adapter.ts";
5
+ import { createMemoryDirectoryHandle } from "./memory-adapter.ts";
6
+ export {
7
+ setupFs,
8
+ createNodeDirectoryHandle,
9
+ createMemoryDirectoryHandle
10
+ };
11
+
12
+ //# debugId=DF39C017335E76D064756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/index.ts"],
4
+ "sourcesContent": [
5
+ "export { setupFs } from \"./setup.ts\";\nexport { createNodeDirectoryHandle } from \"./node-adapter.ts\";\nexport { createMemoryDirectoryHandle } from \"./memory-adapter.ts\";\n\nexport type {\n SetupFsOptions,\n FsHandle,\n HostDirectoryHandle,\n HostFileHandle,\n HostWritableFileStream,\n WriteParams,\n} from \"./types.ts\";\n"
6
+ ],
7
+ "mappings": ";;AAAA;AACA;AACA;",
8
+ "debugId": "DF39C017335E76D064756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "name": "@ricsam/quickjs-fs",
3
+ "version": "0.2.0",
4
+ "type": "module"
5
+ }
@@ -0,0 +1,12 @@
1
+ import type { StateMap } from "@ricsam/quickjs-core";
2
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
3
+ import type { HostDirectoryHandle } from "../types.ts";
4
+ export declare const pendingHostHandles: Map<number, {
5
+ handle: HostDirectoryHandle;
6
+ name: string;
7
+ }>;
8
+ export declare function registerHostDirectoryHandle(handle: HostDirectoryHandle): number;
9
+ /**
10
+ * Create the FileSystemDirectoryHandle class for QuickJS
11
+ */
12
+ export declare function createFileSystemDirectoryHandleClass(context: QuickJSContext, stateMap: StateMap): QuickJSHandle;
@@ -0,0 +1,14 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ import type { HostFileHandle, HostWritableFileStream } from "../types.ts";
4
+ export declare const pendingFileHandles: Map<number, {
5
+ handle: HostFileHandle;
6
+ name: string;
7
+ }>;
8
+ export declare const pendingWritableStreams: Map<number, HostWritableFileStream>;
9
+ export declare function registerHostFileHandle(handle: HostFileHandle): number;
10
+ export declare function registerHostWritableStream(stream: HostWritableFileStream): number;
11
+ /**
12
+ * Create the FileSystemFileHandle class for QuickJS
13
+ */
14
+ export declare function createFileSystemFileHandleClass(context: QuickJSContext, stateMap: StateMap): QuickJSHandle;
@@ -0,0 +1,6 @@
1
+ import type { QuickJSContext, QuickJSHandle } from "quickjs-emscripten";
2
+ import type { StateMap } from "@ricsam/quickjs-core";
3
+ /**
4
+ * Create the FileSystemWritableFileStream class for QuickJS
5
+ */
6
+ export declare function createFileSystemWritableFileStreamClass(context: QuickJSContext, stateMap: StateMap): QuickJSHandle;
@@ -0,0 +1,4 @@
1
+ export { setupFs } from "./setup.ts";
2
+ export { createNodeDirectoryHandle } from "./node-adapter.ts";
3
+ export { createMemoryDirectoryHandle } from "./memory-adapter.ts";
4
+ export type { SetupFsOptions, FsHandle, HostDirectoryHandle, HostFileHandle, HostWritableFileStream, WriteParams, } from "./types.ts";
@@ -0,0 +1,18 @@
1
+ import type { HostDirectoryHandle } from "./types.ts";
2
+ /**
3
+ * Create an in-memory directory handle
4
+ * Useful for testing or fully sandboxed environments
5
+ *
6
+ * @example
7
+ * import { createMemoryDirectoryHandle } from "@ricsam/quickjs-fs";
8
+ *
9
+ * const memFs = createMemoryDirectoryHandle({
10
+ * "config.json": JSON.stringify({ debug: true }),
11
+ * "data/users.json": JSON.stringify([]),
12
+ * });
13
+ *
14
+ * const handle = setupFs(context, {
15
+ * getDirectory: async (path) => memFs
16
+ * });
17
+ */
18
+ export declare function createMemoryDirectoryHandle(initialFiles?: Record<string, string | Uint8Array>): HostDirectoryHandle;
@@ -0,0 +1,23 @@
1
+ import type { HostDirectoryHandle } from "./types.ts";
2
+ /**
3
+ * Create a directory handle backed by Node.js/Bun fs
4
+ * Useful for server-side implementations
5
+ *
6
+ * @param rootPath - Absolute path to the directory on disk
7
+ * @returns A HostDirectoryHandle implementation
8
+ *
9
+ * @example
10
+ * import { createNodeDirectoryHandle } from "@ricsam/quickjs-fs";
11
+ *
12
+ * const handle = setupFs(context, {
13
+ * getDirectory: async (path) => {
14
+ * // Only allow access to /sandbox
15
+ * if (!path.startsWith("/sandbox")) {
16
+ * throw new Error("Access denied");
17
+ * }
18
+ * const realPath = path.replace("/sandbox", "/var/app/sandbox");
19
+ * return createNodeDirectoryHandle(realPath);
20
+ * }
21
+ * });
22
+ */
23
+ export declare function createNodeDirectoryHandle(rootPath: string): HostDirectoryHandle;
@@ -0,0 +1,56 @@
1
+ import type { QuickJSContext } from "quickjs-emscripten";
2
+ import type { SetupFsOptions, FsHandle } from "./types.ts";
3
+ /**
4
+ * Setup File System API in a QuickJS context
5
+ *
6
+ * Injects the following globals:
7
+ * - fs.getDirectory(path) - Server-compatible entry point
8
+ * - FileSystemFileHandle
9
+ * - FileSystemDirectoryHandle
10
+ * - FileSystemWritableFileStream
11
+ *
12
+ * **Private globals (internal use):**
13
+ * - `__FileSystemFileHandle__` - For creating file handle instances from wrapper code
14
+ * - `__FileSystemDirectoryHandle__` - For creating directory handle instances
15
+ * - `__FileSystemWritableFileStream__` - For creating writable stream instances
16
+ *
17
+ * These private globals follow the `__Name__` convention and are required for the
18
+ * wrapper pattern: public methods call internal methods that return IDs, then use
19
+ * evalCode with private constructors to create properly-typed class instances.
20
+ * See PATTERNS.md sections 2 and 5 for details.
21
+ *
22
+ * **Wrapper pattern example:**
23
+ * ```typescript
24
+ * // Public method (added via evalCode)
25
+ * FileSystemFileHandle.prototype.createWritable = async function(options) {
26
+ * const result = await this._createWritableInternal(options);
27
+ * return new __FileSystemWritableFileStream__(result.__writableStreamId);
28
+ * };
29
+ * ```
30
+ *
31
+ * @example
32
+ * import { setupFs, createNodeDirectoryHandle } from "@ricsam/quickjs-fs";
33
+ *
34
+ * const handle = setupFs(context, {
35
+ * getDirectory: async (path) => {
36
+ * // Validate and resolve path
37
+ * const resolvedPath = resolveSandboxPath(path);
38
+ * return createNodeDirectoryHandle(resolvedPath);
39
+ * }
40
+ * });
41
+ *
42
+ * context.evalCode(`
43
+ * const root = await fs.getDirectory("/data");
44
+ * const configHandle = await root.getFileHandle("config.json");
45
+ * const file = await configHandle.getFile();
46
+ * const text = await file.text();
47
+ * console.log(JSON.parse(text));
48
+ *
49
+ * // Write a new file
50
+ * const outputHandle = await root.getFileHandle("output.txt", { create: true });
51
+ * const writable = await outputHandle.createWritable();
52
+ * await writable.write("Hello, World!");
53
+ * await writable.close();
54
+ * `);
55
+ */
56
+ export declare function setupFs(context: QuickJSContext, options: SetupFsOptions): FsHandle;
@@ -0,0 +1,85 @@
1
+ import type { StateMap, CoreHandle } from "@ricsam/quickjs-core";
2
+ export type { StateMap, CoreHandle };
3
+ /**
4
+ * Host-side directory handle interface
5
+ * Implement this to provide file system access to QuickJS
6
+ */
7
+ export interface HostDirectoryHandle {
8
+ readonly kind: "directory";
9
+ readonly name: string;
10
+ getFileHandle(name: string, options?: {
11
+ create?: boolean;
12
+ }): Promise<HostFileHandle>;
13
+ getDirectoryHandle(name: string, options?: {
14
+ create?: boolean;
15
+ }): Promise<HostDirectoryHandle>;
16
+ removeEntry(name: string, options?: {
17
+ recursive?: boolean;
18
+ }): Promise<void>;
19
+ resolve(possibleDescendant: HostFileHandle | HostDirectoryHandle): Promise<string[] | null>;
20
+ entries(): AsyncIterable<[string, HostFileHandle | HostDirectoryHandle]>;
21
+ keys(): AsyncIterable<string>;
22
+ values(): AsyncIterable<HostFileHandle | HostDirectoryHandle>;
23
+ }
24
+ /**
25
+ * Host-side file handle interface
26
+ */
27
+ export interface HostFileHandle {
28
+ readonly kind: "file";
29
+ readonly name: string;
30
+ getFile(): Promise<File>;
31
+ createWritable(options?: {
32
+ keepExistingData?: boolean;
33
+ }): Promise<HostWritableFileStream>;
34
+ }
35
+ /**
36
+ * Host-side writable file stream interface
37
+ */
38
+ export interface HostWritableFileStream {
39
+ write(data: string | ArrayBuffer | Uint8Array | Blob | WriteParams): Promise<void>;
40
+ seek(position: number): Promise<void>;
41
+ truncate(size: number): Promise<void>;
42
+ close(): Promise<void>;
43
+ abort(reason?: unknown): Promise<void>;
44
+ }
45
+ export interface WriteParams {
46
+ type: "write" | "seek" | "truncate";
47
+ data?: string | ArrayBuffer | Uint8Array | Blob;
48
+ position?: number;
49
+ size?: number;
50
+ }
51
+ export interface SetupFsOptions {
52
+ /**
53
+ * Handler to resolve paths to directory handles
54
+ * This is the server-side entry point for file system access
55
+ *
56
+ * @param path - The path requested by QuickJS code
57
+ * @returns A directory handle rooted at this path
58
+ * @throws If the path is not allowed or doesn't exist
59
+ */
60
+ getDirectory: (path: string) => Promise<HostDirectoryHandle>;
61
+ /** Existing state map */
62
+ stateMap?: StateMap;
63
+ /** Existing core handle */
64
+ coreHandle?: CoreHandle;
65
+ }
66
+ export interface FsHandle {
67
+ /** State map containing internal states */
68
+ readonly stateMap: StateMap;
69
+ /** Dispose all handles */
70
+ dispose(): void;
71
+ }
72
+ export interface FileSystemFileHandleState {
73
+ kind: "file";
74
+ name: string;
75
+ hostHandle: HostFileHandle;
76
+ }
77
+ export interface FileSystemDirectoryHandleState {
78
+ kind: "directory";
79
+ name: string;
80
+ hostHandle: HostDirectoryHandle;
81
+ }
82
+ export interface FileSystemWritableFileStreamState {
83
+ hostStream: HostWritableFileStream;
84
+ closed: boolean;
85
+ }
package/package.json CHANGED
@@ -1,10 +1,55 @@
1
1
  {
2
2
  "name": "@ricsam/quickjs-fs",
3
- "version": "0.0.1",
4
- "description": "OIDC trusted publishing setup package for @ricsam/quickjs-fs",
3
+ "version": "0.2.0",
4
+ "main": "./dist/cjs/index.cjs",
5
+ "types": "./dist/types/index.d.ts",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/types/index.d.ts",
9
+ "require": "./dist/cjs/index.cjs",
10
+ "import": "./dist/mjs/index.mjs"
11
+ }
12
+ },
13
+ "scripts": {
14
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun",
15
+ "test": "bun test",
16
+ "typecheck": "tsc --noEmit"
17
+ },
18
+ "dependencies": {
19
+ "@ricsam/quickjs-core": "^0.2.0",
20
+ "quickjs-emscripten": "^0.31.0"
21
+ },
22
+ "peerDependencies": {
23
+ "quickjs-emscripten": "^0.31.0"
24
+ },
25
+ "author": "Richard Samuelsson",
26
+ "license": "MIT",
27
+ "repository": {
28
+ "type": "git",
29
+ "url": "git+https://github.com/ricsam/richie-qjs.git"
30
+ },
31
+ "bugs": {
32
+ "url": "https://github.com/ricsam/richie-qjs/issues"
33
+ },
34
+ "homepage": "https://github.com/ricsam/richie-qjs#readme",
5
35
  "keywords": [
6
- "oidc",
7
- "trusted-publishing",
8
- "setup"
36
+ "quickjs",
37
+ "sandbox",
38
+ "javascript",
39
+ "runtime",
40
+ "fetch",
41
+ "filesystem",
42
+ "streams",
43
+ "wasm",
44
+ "emscripten"
45
+ ],
46
+ "description": "File system API implementation for QuickJS runtime",
47
+ "module": "./dist/mjs/index.mjs",
48
+ "publishConfig": {
49
+ "access": "public"
50
+ },
51
+ "files": [
52
+ "dist",
53
+ "README.md"
9
54
  ]
10
- }
55
+ }