diff --git a/.gitignore b/.gitignore
index 20b91109c83988e51b2ad37fdc0750f3c58b5219..3956314a20c9b5f790ccc31cc03d55c70e53172a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,14 @@
/*/build
.externalNativeBuild
.cxx
+.project
+.classpath
+.settings/
+.yarnrc
+yarn.lock
+node_modules
+/npm/index.js
+/npm/bundle
+/npm/LICENSE
+/npm/README.md
+/npm/package-lock.json
diff --git a/README.md b/README.md
index 7de144f9ee8354cf56d9c63512e1c245c57f8966..ce80ebf564618b826cb7d7b986f4bb15f87641c1 100644
--- a/README.md
+++ b/README.md
@@ -1,34 +1,58 @@
# Git-REST API Wrapper
+[![](https://img.shields.io/npm/v/git-rest-wrapper?color=red&logo=npm)](https://www.npmjs.com/package/git-rest-wrapper)
+[![Discord](https://img.shields.io/discord/514625116706177035.svg?logo=discord&colorB=7289da)](https://discord.jfenn.me/)
+---
This is a cross-platform API wrapper for GitHub, GitLab, and Gitea, in an attempt to normalize their API endpoints and promote interoperability. It is being written in [Kotlin Multiplatform](https://kotlinlang.org/docs/reference/multiplatform.html) with [ktor](https://ktor.io/), and aims to target the JVM, Android, JS, and native platforms - in other words, (almost) everything that ktor supports.
## Usage
-What are you doing here? This project isn't finished yet! I'll update this once I have a better understanding of how kotlin-multiplatform works.
+What are you doing here? This project isn't finished yet! I'll update this once more of the target platforms are complete.
-### Development
+### JavaScript
-The `:gitrest:jsBrowserTest` task seems to fail sporadically due to trying to parse... `/etc/fonts/fonts.conf`? Well, it spits out a lot of logs about it, then fails to actually run the tests, so it's not doing very much. You can append `-x :gitrest:jsBrowserTest` to any gradle commands to prevent it from running.
+JavaScript projects can use the library through either the [NPM package](https://www.npmjs.com/package/git-rest-wrapper) or by using compiled bundle hosted on the [UNPKG CDN](https://unpkg.com/browse/git-rest-wrapper@0.0.1/).
-### Example Projects
+#### NPM Module
+
+```shell script
+npm install git-rest-wrapper
+```
+
+After installing the module through NPM, the API wrapper can be used as detailed in the code snippet below.
+
+```js
+const gitrest = require('git-rest-wrapper');
+const provider = new gitrest.RequestProvider();
-#### example-kotlinbrowser
+provider.fetchUser("fennifith").then((user) => console.log(user.name));
+```
-This is an example of the library being used in another Kotlin/JS project to build a simple webpage.
+#### Bundled JS
-- `./gradlew :example-web:run`: build and serve the website locally using Webpack
+```html
+
+```
-#### example-nodejs
+The bundled JS file works the same as the NPM module - except the `gitrest` package will be available in the global scope.
-This module is built using [yarn](https://yarnpkg.com/), to provide an example of JS library usage. The JS target contains its own "proxy" classes to work around property names being mangled by the Kotlin compiler.
+```js
+const provider = new gitrest.RequestProvider();
-- `./gradlew :example-nodejs:run`: execute the `src/index.js` file (with a few example tests/calls using Promises)
+provider.fetchUser("fennifith").then((user) => console.log(user.name));
+```
-#### example-js
+### Example Projects
+
+- [Kotlin/JS - Browser](./example-kotlinbrowser)
+- [NodeJS](./example-nodejs)
+- [JS (Bundle) - Browser](./example-js)
+
+### Development
-This module demonstrates the use of the bundled JS file in a webpage, without the use of Kotlin/JS.
+The project uses Gradle builds for... err... most things.
-- `./gradlew :example-js:run`: serve the `index.html` and `gitrest.js` files on `localhost:8080`.
+The `:gitrest:jsBrowserTest` task seems to fail sporadically trying to parse... `/etc/fonts/fonts.conf`? Well, it spits out a lot of logs about it, then fails to actually run any of its tests, so it's not doing very much. I recommend appending `-x :gitrest:jsBrowserTest` to any gradle commands to prevent it from running.
## Specification
diff --git a/example-js/README.md b/example-js/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..ee4d7d9333a87752edb2a3ab3858de3b014e653b
--- /dev/null
+++ b/example-js/README.md
@@ -0,0 +1,5 @@
+# example-js
+
+This module demonstrates the use of the bundled JS file in a webpage, without the use of Kotlin/JS.
+
+- `./gradlew :example-js:run`: serve the `index.html` and `gitrest.js` files on `localhost:8080`.
diff --git a/example-kotlinbrowser/README.md b/example-kotlinbrowser/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..d522742f59167d01fa6024e421a838fcd5d0d8da
--- /dev/null
+++ b/example-kotlinbrowser/README.md
@@ -0,0 +1,5 @@
+# example-kotlinbrowser
+
+This is an example of the library being used in another Kotlin/JS project to build a simple webpage.
+
+- `./gradlew :example-web:run`: build and serve the website locally using Webpack
diff --git a/example-nodejs/README.md b/example-nodejs/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..de4bc101bab3fc2b6c8487babc676936f2302d99
--- /dev/null
+++ b/example-nodejs/README.md
@@ -0,0 +1,5 @@
+# example-nodejs
+
+This module is built using [yarn](https://yarnpkg.com/), to provide an example of JS library usage. The JS target contains its own "proxy" classes to work around property names being mangled by the Kotlin compiler.
+
+- `./gradlew :example-nodejs:run`: execute the `src/index.js` file (with a few example tests/calls using Promises)
diff --git a/npm/package.json b/npm/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..7c30778ebc9c073b3e0216741062642c455e6b04
--- /dev/null
+++ b/npm/package.json
@@ -0,0 +1,46 @@
+{
+ "name": "git-rest-wrapper",
+ "version": "0.0.2",
+ "description": "A \"universal\" / normalized API wrapper for common git hosting services.",
+ "main": "index.js",
+ "files": [
+ "README.md",
+ "LICENSE",
+ "package.json",
+ "index.js",
+ "bundle/*"
+ ],
+ "repository": {
+ "type": "git",
+ "url": "git+https://code.horrific.dev/james/git-rest-wrapper.git"
+ },
+ "author": "James Fenn (https://jfenn.me/)",
+ "license": "MPL-2.0",
+ "bugs": {
+ "url": "https://code.horrific.dev/james/git-rest-wrapper/issues"
+ },
+ "homepage": "https://code.horrific.dev/james/git-rest-wrapper#user-content-git-rest-api-wrapper",
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "node-fetch": "^2.6.0",
+ "text-encoding": "^0.7.0"
+ },
+ "bundledDependencies": [
+ "kotlin",
+ "kotlin-source-map-loader",
+ "kotlin-test",
+ "kotlin-test-js-runner",
+ "kotlinx-atomicfu",
+ "kotlinx-coroutines-core",
+ "kotlinx-html-js",
+ "kotlinx-serialization-kotlinx-serialization-runtime",
+ "ktor-ktor-client-core",
+ "ktor-ktor-client-js",
+ "ktor-ktor-client-json",
+ "ktor-ktor-client-serialization",
+ "ktor-ktor-http",
+ "ktor-ktor-http-cio",
+ "ktor-ktor-io",
+ "ktor-ktor-utils"
+ ]
+}
diff --git a/npm/publish.sh b/npm/publish.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f80e291fd07b74d7169824d4aa09da382f663d16
--- /dev/null
+++ b/npm/publish.sh
@@ -0,0 +1,49 @@
+#!/bin/bash
+set -e
+
+# Build JS file (ignore browser tests...)
+( cd .. && ./gradlew :gitrest:build -x :gitrest:jsBrowserTest )
+
+# Copy generated git-rest-wrapper package
+cp ../build/js/packages/git-rest-wrapper-gitrest/kotlin/git-rest-wrapper-gitrest.js index.js
+
+# Copy browser bundle
+rm -rf bundle && mkdir bundle
+cp ../gitrest/build/distributions/* bundle/
+
+BUNDLE_PACKAGES=()
+function install_bundled_packages {
+ # Re-create node_modules; fill with bundled dependencies
+ rm -rf node_modules && mkdir node_modules
+ for pkg in ../build/js/packages_imported/*
+ do
+ pkg_dir=$(ls -d ${pkg}/*)
+ pkg_name=${pkg##*/}
+ cp -r "$pkg_dir" "node_modules/${pkg_name}"
+ BUNDLE_PACKAGES+=("\"$pkg_name\"")
+ done
+}
+
+install_bundled_packages
+
+# Update 'bundledDependencies' value in package.json
+PACKAGE_DEPENDENCIES=$(echo "${BUNDLE_PACKAGES[@]}" | jq -s '.')
+PACKAGE_JSON=$(jq --argjson dependencies "$PACKAGE_DEPENDENCIES" '.bundledDependencies = $dependencies' package.json)
+echo $PACKAGE_JSON > package.json
+
+# Install regular NPM dependencies for testing
+NPM_PACKAGES=$(jq '.dependencies | to_entries | map("\(.key)@\(.value|tostring)") | .[]' package.json)
+npm install ${NPM_PACKAGES//\"/} --no-package-lock
+
+npm dedupe
+node test.js # Make sure the package actually works
+
+# Re-install bundled packages (remove dependencies fetched from npm for testing)
+install_bundled_packages
+
+# Copy meta-files from root dir
+cp -f ../README.md .
+cp -f ../LICENSE .
+
+# Publish the package!
+npm publish
diff --git a/npm/test.js b/npm/test.js
new file mode 100644
index 0000000000000000000000000000000000000000..6fdb385adfa47a1b3e06ca96cd663eac0a40b18d
--- /dev/null
+++ b/npm/test.js
@@ -0,0 +1,10 @@
+const { RequestProvider } = require('./index.js');
+
+let provider = new RequestProvider();
+
+// simple usability test, probably shouldn't break anytime soon...
+provider.getUser("fennifith").then((user) => {
+ if (user.name === "James Fenn")
+ console.log("Test successful!");
+ else throw "Something's not quite right...";
+});