This is an automated email from the ASF dual-hosted git repository.
colegreer pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git
The following commit(s) were added to refs/heads/master by this push:
new c1f943e513 CTR Modernize JS README and examples for TP4, and update JS
Upgrade Docs
c1f943e513 is described below
commit c1f943e513912f1c19dcc745849a3f049d565df1
Author: Cole Greer <[email protected]>
AuthorDate: Tue Mar 31 14:27:15 2026 -0700
CTR Modernize JS README and examples for TP4, and update JS Upgrade Docs
---
docs/src/upgrade/release-4.x.x.asciidoc | 113 +++++++++++++++++++++
gremlin-js/gremlin-javascript/README.md | 18 +++-
.../examples/node/basic-gremlin.js | 2 +-
.../examples/node/connections.js | 6 +-
.../examples/node/modern-traversals.js | 6 +-
gremlin-js/gremlin-javascript/lib/index.ts | 2 +
6 files changed, 138 insertions(+), 9 deletions(-)
diff --git a/docs/src/upgrade/release-4.x.x.asciidoc
b/docs/src/upgrade/release-4.x.x.asciidoc
index 43bd657f8c..a0dc259ebe 100644
--- a/docs/src/upgrade/release-4.x.x.asciidoc
+++ b/docs/src/upgrade/release-4.x.x.asciidoc
@@ -123,6 +123,13 @@ might apply.
* JavaScript GLV
** `mimeType` setting has been removed. Use `reader` and `writer` options
directly to control serialization format.
+** `authenticator` option has been removed. Use `interceptors` with
`auth.basic()` or `auth.sigv4()` instead.
+** `session` option has been removed.
+** `interceptors` option has been added to `Client` and
`DriverRemoteConnection` for HTTP request modification.
+** `writer` can be set to `null` to skip request serialization, allowing
interceptors to handle it directly.
+** `bulkResults` has been added as a request option. `DriverRemoteConnection`
defaults it to `true`.
+** `Bytecode` has been replaced with `GremlinLang`.
+** Serialization updated to GraphBinary 4.
* .NET GLV
** `ConnectionPoolSettings` has been replaced with `ConnectionSettings` for
HTTP connection configuration.
** `webSocketConfiguration` parameter has been removed.
@@ -223,6 +230,112 @@ The WebSocket-specific settings (`TransporterType`,
`ReadBufferSize`, `WriteBuff
`NewConnectionThreshold`, `Session`) have been removed. New HTTP connection
pool settings have been added:
`MaximumConcurrentConnections`, `MaxIdleConnections`, `IdleConnectionTimeout`,
and `KeepAliveInterval`.
+[[javascript-typescript-esm]]
+==== Gremlin-JavaScript TypeScript and ESM Migration
+
+The `gremlin-javascript` driver has been rewritten in TypeScript and now ships
with built-in type declarations. The
+package publishes dual ESM and CommonJS builds, so both `import` and `require`
work out of the box.
+
+===== Module format changes
+
+The package now sets `"type": "module"` in `package.json` and uses conditional
`exports`:
+
+- ESM: `import gremlin from 'gremlin'` resolves to `build/esm/index.js`
+- CJS: `const gremlin = require('gremlin')` resolves to `build/cjs/index.cjs`
+
+Existing CommonJS applications using `require('gremlin')` will continue to
work without changes. Applications using
+ESM can now use `import` directly:
+
+[source,javascript]
+----
+// CommonJS (still works)
+const gremlin = require('gremlin');
+
+// ESM — default import
+import gremlin from 'gremlin';
+
+// ESM — named imports
+import { driver, process, structure } from 'gremlin';
+----
+
+===== TypeScript support
+
+Type declarations (`.d.ts`) are included in the published package. TypeScript
projects can import the driver directly
+without installing separate `@types` packages:
+
+[source,typescript]
+----
+import gremlin from 'gremlin';
+import type { ConnectionOptions } from
'gremlin/build/esm/driver/connection.js';
+
+const connection = new
gremlin.driver.DriverRemoteConnection('http://localhost:8182/gremlin');
+const g = gremlin.process.traversal().with_(connection);
+----
+
+===== Breaking changes to exports
+
+Several exports have been removed or renamed compared to 3.x:
+
+- `process.Bytecode` has been removed. Use `process.GremlinLang` instead.
+- `process.Translator` has been removed. To produce a canonical gremlin script
from a `Traversal`, use
+ `process.GremlinLang` instead (e.g.
`traversal.getGremlinLang().getGremlin()`).
+- `driver.auth.Authenticator` and `driver.auth.PlainTextSaslAuthenticator`
have been removed. Use `driver.auth.basic()`
+ and `driver.auth.sigv4()` interceptor factories instead.
+- `structure.io` (the serializer namespace) has been removed. Serialization is
now internal to the driver.
+- `Graph.traversal()` has been removed. Use the `process.traversal()` function
instead.
+
+For example, authentication that previously used `PlainTextSaslAuthenticator`:
+
+[source,javascript]
+----
+// 3.x
+const authenticator = new
gremlin.driver.auth.PlainTextSaslAuthenticator('username', 'password');
+const client = new gremlin.driver.Client('ws://localhost:8182/gremlin', {
authenticator });
+
+// 4.x
+const client = new gremlin.driver.Client('http://localhost:8182/gremlin', {
+ interceptors: gremlin.driver.auth.basic('username', 'password'),
+});
+----
+
+[[javascript-http-interceptor]]
+==== Gremlin-JavaScript HTTP and Interceptor Changes
+
+The `gremlin-javascript` driver has been updated to use HTTP instead of
WebSockets. The `Connection` class now uses
+Node.js `fetch` internally and sends requests via HTTP POST to Gremlin Server.
+
+`Bytecode` has been replaced with `GremlinLang`, which builds a gremlin-lang
compatible string representation of a
+traversal along with a map of named parameters. Traversals now produce
gremlin-lang strings that are sent to the server
+rather than serialized bytecode.
+
+HTTP interceptors have been added to `gremlin-javascript`. Interceptors can be
passed to the `Client` or
+`DriverRemoteConnection` constructor using the `interceptors` option. A
`RequestInterceptor` is a function that receives
+an `HttpRequest` object containing the HTTP method, URL, headers, and body,
and returns the (possibly modified) request
+or a `Promise` resolving to one. Interceptors are executed in order before the
request is sent.
+
+Authentication is now handled through interceptors rather than the previous
`authenticator` option. The `auth` module
+provides factory functions for built-in interceptors:
+
+[source,javascript]
+----
+import gremlin from 'gremlin';
+
+const { DriverRemoteConnection, auth } = gremlin.driver;
+
+// Basic authentication
+const connection = new
DriverRemoteConnection('https://localhost:8182/gremlin', {
+ interceptors: auth.basic('username', 'password'),
+});
+
+// SigV4 authentication
+const connection = new
DriverRemoteConnection('https://localhost:8182/gremlin', {
+ interceptors: auth.sigv4('service-region', 'service-name'),
+});
+----
+
+Setting the `writer` option to `null` prevents the `RequestMessage` from being
serialized before interceptors run,
+allowing an interceptor to handle serialization directly where desired.
+
==== Transactions Re-enabled
IMPORTANT: The remote transaction API is still under active discussion and the
specification has not been finalized.
diff --git a/gremlin-js/gremlin-javascript/README.md
b/gremlin-js/gremlin-javascript/README.md
index 706b3b1f05..4666d2d163 100644
--- a/gremlin-js/gremlin-javascript/README.md
+++ b/gremlin-js/gremlin-javascript/README.md
@@ -36,8 +36,7 @@ Gremlin-Javascript is designed to connect to a "server" that
is hosting a Tinker
could be [Gremlin Server][gs] or a [remote Gremlin provider][rgp] that exposes
protocols by which Gremlin-Javascript
can connect.
-A typical connection to a server running on "localhost" that supports the
Gremlin Server protocol using websockets
-looks like this:
+A typical connection to a server running on "localhost" that supports the
Gremlin Server protocol looks like this:
```javascript
const gremlin = require('gremlin');
@@ -47,6 +46,21 @@ const DriverRemoteConnection =
gremlin.driver.DriverRemoteConnection;
const g = traversal().with_(new
DriverRemoteConnection('http://localhost:8182/gremlin'));
```
+Some graph providers may require additional request customization to connect.
The driver supports request interceptors
+for these cases. For example, to connect with basic authentication:
+
+```javascript
+const gremlin = require('gremlin');
+const traversal = gremlin.process.AnonymousTraversalSource.traversal;
+const DriverRemoteConnection = gremlin.driver.DriverRemoteConnection;
+
+const g = traversal().with_(new
DriverRemoteConnection('http://localhost:8182/gremlin', {
+ interceptors: gremlin.driver.auth.basic('username', 'password')
+}));
+```
+
+Refer to your graph provider's documentation for specific connection
requirements.
+
Once "g" has been created using a connection, it is then possible to start
writing Gremlin traversals to query the
remote graph:
diff --git a/gremlin-js/gremlin-javascript/examples/node/basic-gremlin.js
b/gremlin-js/gremlin-javascript/examples/node/basic-gremlin.js
index a33d7505b9..509391810e 100644
--- a/gremlin-js/gremlin-javascript/examples/node/basic-gremlin.js
+++ b/gremlin-js/gremlin-javascript/examples/node/basic-gremlin.js
@@ -27,7 +27,7 @@ const vertexLabel = process.env.VERTEX_LABEL || 'person';
async function main() {
const dc = new DriverRemoteConnection(serverUrl);
- const g = traversal().withRemote(dc);
+ const g = traversal().with_(dc);
// Basic Gremlin: adding and retrieving data
const v1 = await g.addV(vertexLabel).property('name','marko').next();
diff --git a/gremlin-js/gremlin-javascript/examples/node/connections.js
b/gremlin-js/gremlin-javascript/examples/node/connections.js
index e8d8841214..4de55242e5 100644
--- a/gremlin-js/gremlin-javascript/examples/node/connections.js
+++ b/gremlin-js/gremlin-javascript/examples/node/connections.js
@@ -32,7 +32,7 @@ async function main() {
async function withRemote() {
// Connecting to the server
const dc = new DriverRemoteConnection(serverUrl);
- const g = traversal().withRemote(dc);
+ const g = traversal().with_(dc);
// Simple query to verify connection
const v = await g.addV(vertexLabel).iterate();
@@ -46,10 +46,10 @@ async function withRemote() {
async function withConfigs() {
// Connecting and customizing configurations
const dc = new DriverRemoteConnection(serverUrl, {
- rejectUnauthorized: false,
traversalSource: 'g',
+ headers: { 'X-Api-Key': 'your-api-key' },
});
- const g = traversal().withRemote(dc);
+ const g = traversal().with_(dc);
const v = await g.addV(vertexLabel).iterate();
const count = await g.V().hasLabel(vertexLabel).count().next();
diff --git a/gremlin-js/gremlin-javascript/examples/node/modern-traversals.js
b/gremlin-js/gremlin-javascript/examples/node/modern-traversals.js
index 1b07a18b15..728c619259 100644
--- a/gremlin-js/gremlin-javascript/examples/node/modern-traversals.js
+++ b/gremlin-js/gremlin-javascript/examples/node/modern-traversals.js
@@ -36,14 +36,14 @@ async function main() {
// Use gmodern in CI environment, default connection locally
const options = process.env.DOCKER_ENVIRONMENT ? { traversalSource:
'gmodern' } : {};
const dc = new DriverRemoteConnection(serverUrl, options);
- const g = traversal().withRemote(dc);
+ const g = traversal().with_(dc);
const e1 = await g.V(1).bothE().toList(); // (1)
const e2 = await g.V(1).bothE().where(__.otherV().hasId(2)).toList(); //
(2)
const v1 = await g.V(1).next();
const v2 = await g.V(2).next();
- const e3 = await
g.V(v1.value).bothE().where(__.otherV().is(v2.value)).toList(); // (3)
- const e4 = await
g.V(v1.value).outE().where(__.inV().is(v2.value)).toList(); // (4)
+ const e3 = await
g.V(v1.value).bothE().where(__.otherV().id().is(v2.value)).toList(); // (3)
+ const e4 = await
g.V(v1.value).outE().where(__.inV().id().is(v2.value)).toList(); // (4)
const e5 = await g.V(1).outE().where(__.inV().has(t.id,
p.within(2,3))).toList(); // (5)
const e6 = await g.V(1).out().where(__.in_().hasId(6)).toList(); // (6)
diff --git a/gremlin-js/gremlin-javascript/lib/index.ts
b/gremlin-js/gremlin-javascript/lib/index.ts
index b0d47a306f..fd40186eb6 100644
--- a/gremlin-js/gremlin-javascript/lib/index.ts
+++ b/gremlin-js/gremlin-javascript/lib/index.ts
@@ -88,3 +88,5 @@ export const structure = {
VertexProperty: graph.VertexProperty,
toLong: utils.toLong,
};
+
+export default { driver, process, structure };