Skip to content

Commit

Permalink
Preparing the preview release of Deno driver (#1149)
Browse files Browse the repository at this point in the history
* Add preview alert when init the driver

* Add README.md

* Set version

* Alpha 01

* Add fix driver name

* Add script for bump deno version

* Add missing file

* Set correct version
  • Loading branch information
bigmontz committed Oct 19, 2023
1 parent e26619c commit 7b9cd09
Show file tree
Hide file tree
Showing 10 changed files with 321 additions and 50 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"scripts": {
"clean": "lerna clean -y && lerna run clean",
"build": "lerna bootstrap --ci",
"build::deno": "cd ./packages/neo4j-driver-deno && deno run --allow-read --allow-write --allow-net ./generate.ts --version=5.0.0-dev",
"set_version::deno": "cd ./packages/neo4j-driver-deno && deno run --allow-read --allow-write ./versioning.ts --output=. --filename=current.version.ts",
"build::deno": "cd ./packages/neo4j-driver-deno && deno run --allow-read --allow-write --allow-net ./generate.ts",
"build::notci": "lerna bootstrap",
"docs": "lerna run docs --stream --concurrency 1",
"test::unit": "lerna run test::unit --stream",
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/internal/bolt-agent/deno/bolt-agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ export function fromVersion (
const DENO_VERSION = `Deno/${systemInfo.denoVersion}`
const OS_NAME_VERSION = `${systemInfo.osVersion} ${systemInfo.osRelease}`.trim()

console.warn("WARNING! neo4j-driver-deno stills in preview.")

return {
product: `neo4j-javascript/${version}`,
platform: `${OS_NAME_VERSION}; ${systemInfo.hostArch}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,29 @@ Deno.test('Test full bolt agent for mocked values', () => {
languageDetails: `Deno/1.19.1 (v8 8.1.39)`
})
});

// @ts-ignore
Deno.test('Test full bolt agent for mocked values', () => {
const originalConsoleWarn = console.warn
const consoleWarnCalls = [] as any[][]
const myConsoleWarn = (...args: any[]) => consoleWarnCalls.push(args)

try {
console.warn = myConsoleWarn;

fromVersion('5.3')

assertEquals(consoleWarnCalls.length, 1)
assertEquals(consoleWarnCalls[0].length, 1)

const [[message]] = consoleWarnCalls

assertEquals(message, "WARNING! neo4j-driver-deno stills in preview.")
} finally {
console.warn = originalConsoleWarn
}

});


/* eslint-enable */
142 changes: 105 additions & 37 deletions packages/neo4j-driver-deno/README.md
Original file line number Diff line number Diff line change
@@ -1,63 +1,131 @@
# Neo4j Driver for Deno (Experimental)
# Neo4j Lite Driver for Deno (Preview)

This folder contains a script which can auto-generate a version of
`neo4j-driver-lite` that is fully compatible with Deno, including complete type
information.
> :warning: **This package stills a PREVIEW version.**
The resulting driver does not use any dependencies outside of the Deno standard
library.
This is the Deno version of the official Neo4j driver for JavaScript.

## Development instructions
This version of driver is based in the `neo4j-driver-lite`.
So, this version has the same capabilities as the Neo4j Driver except for the support of reactive sessions.
This means it doesn't have the `RxJS` dependency and the `Driver#rxSession` api.

To generate the driver, open a shell in this folder and run this command,
specifying what version number you want the driver to identify as:
Starting with 5.0, the Neo4j Drivers will be moving to a monthly release cadence. A minor version will be released on the last Friday of each month so as to maintain versioning consistency with the core product (Neo4j DBMS) which has also moved to a monthly cadence.

```
deno run --allow-read --allow-write --allow-net ./generate.ts --version=4.4.0
As a policy, patch versions will not be released except on rare occasions. Bug fixes and updates will go into the latest minor version and users should upgrade to that. Driver upgrades within a major version will never contain breaking API changes.

See also: https://neo4j.com/developer/kb/neo4j-supported-versions/

Resources to get you started:

- [API Documentation](https://neo4j.com/docs/api/javascript-driver/current/)
- [Neo4j Manual](https://neo4j.com/docs/)
- [Neo4j Refcard](https://neo4j.com/docs/cypher-refcard/current/)
- [TLS](#tls)

## What's New in 5.x

- [Changelog](https://github.com/neo4j/neo4j-javascript-driver/wiki/5.0-changelog)

## Usage

Importing the driver:

```typescript
import neo4j from "https://deno.land/x/neo4j_driver_lite@VERSION/mod.ts";
```

The script will:
Driver instance should be closed when application exits:

1. Copy `neo4j-driver-lite` and the Neo4j packages it uses into a subfolder here
called `lib`.
1. Rewrite all imports to Deno-compatible versions
1. Replace the "node channel" with the "deno channel"
1. Test that the resulting driver can be imported by Deno and passes type checks
```javascript
await driver.close()
```
otherwise the application shutdown might hang or exit with a non-zero exit code.

It is not necessary to do any other setup first; in particular, you don't need
to install any of the Node packages or run any of the driver monorepo's other
scripts. However, you do need to have Deno installed.
Application which uses the should use `--allow-net --allow-sys...` for running.
For Deno versions bellow `1.27.1`, you should use the flag `--allow-env` instead of `--allow-sys`.

## Usage instructions
### TLS

Once the driver is generated in the `lib` directory, you can import it and use
it as you would use `neo4j-driver-lite` (refer to its documentation).
For using system certificates, the `DENO_TLS_CA_STORE` should be set to `"system"`.
`TRUST_ALL_CERTIFICATES` should be handle by `--unsafely-ignore-certificate-errors` and not by driver configuration. See, https://deno.com/blog/v1.13#disable-tls-verification;

Here is an example:
### Basic Example

```typescript
import neo4j from "./lib/mod.ts";
const URI = "bolt://localhost:7687";
const driver = neo4j.driver(URI, neo4j.auth.basic("neo4j", "driverdemo"));
const session = driver.session();

const results = await session.run("MATCH (n) RETURN n LIMIT 25");
console.log(results.records);
const { records } = await driver.executeQuery("MATCH (n) RETURN n LIMIT 25");
console.log(records);

await session.close();
await driver.close();

```

You can use `deno run --allow-net --allow-sys...` or `deno repl` to run this example.
### Numbers and the Integer type

For Deno versions bellow `1.27.1`, you should use the flag `--allow-env` instead of `--allow-sys`.
The Neo4j type system uses 64-bit signed integer values. The range of values is between `-(2`<sup>`64`</sup>`- 1)` and `(2`<sup>`63`</sup>`- 1)`.

If you don't have a running Neo4j instance, you can use
`docker run --rm -p 7687:7687 -e NEO4J_AUTH=neo4j/driverdemo neo4j:4.4` to
quickly spin one up.
However, JavaScript can only safely represent integers between `Number.MIN_SAFE_INTEGER` `-(2`<sup>`53`</sup>`- 1)` and `Number.MAX_SAFE_INTEGER` `(2`<sup>`53`</sup>`- 1)`.

## TLS
In order to support the full Neo4j type system, the driver will not automatically convert to javascript integers.
Any time the driver receives an integer value from Neo4j, it will be represented with an internal integer type by the driver.

For using system certificates, the `DENO_TLS_CA_STORE` should be set to `"system"`.
`TRUST_ALL_CERTIFICATES` should be handle by `--unsafely-ignore-certificate-errors` and not by driver configuration. See, https://deno.com/blog/v1.13#disable-tls-verification;
_**Any javascript number value passed as a parameter will be recognized as `Float` type.**_

#### Writing integers

Numbers written directly e.g. `session.run("CREATE (n:Node {age: $age})", {age: 22})` will be of type `Float` in Neo4j.

To write the `age` as an integer the `neo4j.int` method should be used:

```javascript
session.run('CREATE (n {age: $myIntParam})', { myIntParam: neo4j.int(22) })
```

To write an integer value that are not within the range of `Number.MIN_SAFE_INTEGER` `-(2`<sup>`53`</sup>`- 1)` and `Number.MAX_SAFE_INTEGER` `(2`<sup>`53`</sup>`- 1)`, use a string argument to `neo4j.int`:

```javascript
session.run('CREATE (n {age: $myIntParam})', {
myIntParam: neo4j.int('9223372036854775807')
})
```

#### Reading integers

In Neo4j, the type Integer can be larger what can be represented safely as an integer with JavaScript Number.

It is only safe to convert to a JavaScript Number if you know that the number will be in the range `Number.MIN_SAFE_INTEGER` `-(2`<sup>`53`</sup>`- 1)` and `Number.MAX_SAFE_INTEGER` `(2`<sup>`53`</sup>`- 1)`.

In order to facilitate working with integers the driver include `neo4j.isInt`, `neo4j.integer.inSafeRange`, `neo4j.integer.toNumber`, and `neo4j.integer.toString`.

```javascript
var smallInteger = neo4j.int(123)
if (neo4j.integer.inSafeRange(smallInteger)) {
var aNumber = smallInteger.toNumber()
}
```

If you will be handling integers that is not within the JavaScript safe range of integers, you should convert the value to a string:

```javascript
var largeInteger = neo4j.int('9223372036854775807')
if (!neo4j.integer.inSafeRange(largeInteger)) {
var integerAsString = largeInteger.toString()
}
```

#### Enabling native numbers

Starting from 1.6 version of the driver it is possible to configure it to only return native numbers instead of custom `Integer` objects.
The configuration option affects all integers returned by the driver. **Enabling this option can result in a loss of precision and incorrect numeric
values being returned if the database contains integer numbers outside of the range** `[Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER]`.
To enable potentially lossy integer values use the driver's configuration object:

```javascript
var driver = neo4j.driver(
'neo4j://localhost',
neo4j.auth.basic('neo4j', 'password'),
{ disableLosslessIntegers: true }
)
```

20 changes: 20 additions & 0 deletions packages/neo4j-driver-deno/current.version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [http://neo4j.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

export default "5.14.0-alpha01" // Specified using --version when running generate.ts
18 changes: 7 additions & 11 deletions packages/neo4j-driver-deno/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import * as log from "https://deno.land/std@0.119.0/log/mod.ts";
import { parse } from "https://deno.land/std@0.119.0/flags/mod.ts";
import { ensureDir } from "https://deno.land/std@0.119.0/fs/mod.ts";
import { join, relative } from "https://deno.land/std@0.119.0/path/mod.ts";
import { setVersion } from "./versioning.ts"

const isDir = (path: string) => {
try {
Expand Down Expand Up @@ -45,7 +46,7 @@ const parsedArgs = parse(Deno.args, {
// Should we rewrite imports or simply copy the files unmodified?
// Copying without changes can be useful to later generate a diff of the transforms
const doTransform = parsedArgs["transform"];
const version = parsedArgs.version ?? "0.0.0dev";
const version = parsedArgs.version;

////////////////////////////////////////////////////////////////////////////////
// Clear out the destination folder
Expand Down Expand Up @@ -174,22 +175,17 @@ await copyAndTransform(
await copyAndTransform("../neo4j-driver-lite/src", rootOutDir);
// Deno convention is to use "mod.ts" not "index.ts", so let's do that at least for the main/root import:
await Deno.rename(join(rootOutDir, "index.ts"), join(rootOutDir, "mod.ts"))
const copyright = await Deno.readTextFile("./copyright.txt");
await Deno.writeTextFile(
join(rootOutDir, "version.ts"),
[copyright, `export default "${version}" // Specified using --version when running generate.ts\n`].join('\n'),
);
await setVersion(rootOutDir, version)

// Copy README.md
const readmeFileName = "README.md"
await Deno.copyFile(join(`./`, readmeFileName), join(rootOutDir, readmeFileName))

////////////////////////////////////////////////////////////////////////////////
// Warnings show up at the end
if (!doTransform) {
log.warning("Transform step was skipped.");
}
if (!parsedArgs.version) {
log.warning(
"No version specified. Specify a version like this: --version=4.4.0",
);
}

////////////////////////////////////////////////////////////////////////////////
// Now test the driver
Expand Down
Loading

0 comments on commit 7b9cd09

Please sign in to comment.