Giter Club home page Giter Club logo

rdme's Introduction

Warning

These docs are for the forthcoming v9 release. You can view the docs for the current release (v8) here.

rdme

ReadMe's official command-line interface (CLI) and GitHub Action ๐ŸŒŠ

NPM Version Node Version MIT License Build status

With rdme, you can manage your API definition (we support OpenAPI, Swagger, and Postman) and sync it to your API reference docs on ReadMe. You can also access other parts of ReadMe's RESTful API, including syncing Markdown documentation with your ReadMe project and managing project versions.

Not using ReadMe for your docs? No worries. rdme has a variety of tools to help you identify issues with your API definition โ€” no ReadMe account required.

Table of Contents

CLI Configuration

Setup

Note

These setup instructions are for CLI usage only. For usage in GitHub Actions, see GitHub Actions Configuration below.

Node Version

To install the rdme CLI, you'll need to have Node.js installed. Node.js comes bundled with the npm CLI, which you'll need to install rdme. You can see our current Node.js version requirements in the green badge on the right.

Installing rdme to Your Local Machine

The simplest way to use rdme is to install it globally:

npm install -g rdme

With a global installation, you'll be able to run rdme within any directory on your local machine. If you log in once, you can quickly access your project without having to remember your API key (see the Authentication section below).

Installing rdme to a Project

The recommended approach for shared projects is to install rdme in your project's dependencies, that way you don't run into unexpected behavior with mismatching versions of rdme. We also suggest using the --save-dev flag since rdme is typically used as part of a CI process and is unlikely to be running in your production application:

npm install rdme --save-dev

Once installed in your project, you can use the npx prefix (which is included if you have npm installed) to run your CLI commands locally. For example:

npx rdme openapi:validate [file]

To ensure you're getting the latest features and security updates, we recommend using a tool like Dependabot to keep rdme (and your other dependencies) up-to-date.

Authentication

For local CLI usage with a single project, you can authenticate rdme to your ReadMe project using rdme login. Once you follow the prompts and are successfully authenticated, your API key will be saved to a local configuration file (~/.config/configstore/rdme-production.json) and you won't have to provide the --key option to commands that require it.

Warning

For security reasons, we strongly recommend providing a project API key via the --key option in automations or CI environments (GitHub Actions, CircleCI, Travis CI, etc.). It's also recommended if you're working with multiple ReadMe projects to avoid accidentally overwriting existing data.

You can also pass in your API key via environmental variable. Here is the order of precedence when passing your API key into rdme:

  1. The --key option. If that isn't present, we look for...
  2. The RDME_API_KEY environmental variable. If that isn't present, we look for...
  3. The README_API_KEY environmental variable. If that isn't present, we look for...
  4. The API key value stored in your local configuration file (i.e., the one set via rdme login)

rdme whoami is also available to you to determine who is logged in, and to what project. You can clear your stored credentials with rdme logout.

1Password

As a secure alternative to the rdme login approach to using the CLI locally, 1Password users can set up the ReadMe shell plugin. With this approach, you can store your ReadMe API key in 1Password and securely pass it in your rdme commands using biometrics. See below for a demo of this behavior:

readme-1p.mp4

To set this up, check out 1Password's documentation on the ReadMe shell plugin.

Proxy

rdme makes API requests to the ReadMe API, which is located at dash.readme.com. If you need to configure a proxy for these requests, you can do so by setting the HTTPS_PROXY environmental variable.

export HTTPS_PROXY=https://proxy.example.com:5678
rdme openapi

GitHub Actions Configuration

Note

For a full GitHub Workflow file example and additional information on GitHub Actions usage, check out our docs.

For usage in GitHub Actions, you can create a new GitHub Actions workflow file by including the --github flag with the command you wish to run in GitHub Actions. For example:

rdme openapi --github

This will run through the openapi command, ask you a few quick questions, and then automatically create a fully functional GitHub Actions workflow file for you. ๐Ÿช„

You can see examples featuring the latest version in our docs. We recommend configuring Dependabot to keep your actions up-to-date.

Usage

If you wish to get more information about any command within rdme, you can execute rdme help <command> or rdme <command> --help. You an also execute rdme help to see a global list of commands that rdme offers.

Common rdme Options

  • --key <string>: The API key associated with your ReadMe project. Note that most of the commands below require API key authentication, even though the --key flag is omitted from the examples. See the Authentication section above for more information.
  • --version <string>: Your project version. See our docs for more information.

API Definitions ๐Ÿ“š

With rdme, you have access to a variety of tools to manage your API definition, most of which don't require an account on ReadMe. These tools include:

rdme supports OpenAPI 3.1, OpenAPI 3.0, and Swagger 2.x.

You can also pass in Postman Collections. Postman Collections are converted to OpenAPI using postman-to-openapi prior to any syncing/validation/etc.

The following examples use JSON files, but rdme supports API Definitions that are written in either JSON or YAML.

Syncing an API Definition to ReadMe

rdme openapi locates your API definition (if you don't supply one), validates it, and then syncs it to your API reference on ReadMe.

Note

The rdme openapi command supports both OpenAPI and Swagger API definitions.

If you wish to programmatically access any of this script's results (such as the API definition ID or the link to the corresponding docs in your dashboard), supply the --raw flag and the command will return a JSON output.

This command also has a dry run mode, which can be useful for initial setup and debugging. You can perform a dry run by supplying the --dryRun flag.

Omitting the File Path

If you run rdme within a directory that contains your OpenAPI or Swagger definition, you can omit the file path. rdme will then look for JSON or YAML files (including in sub-directories) that contain a top-level openapi or swagger property.

Note

rdme will not scan anything in the following:

  • Any .git/ directories (if they exist)
  • Any files/directories specified in .gitignore files (including any .gitignore files in subdirectories, if they exist)
rdme openapi
Uploading a New API Definition to ReadMe

This will upload the API definition at the given URL or path to your project and return an ID and URL for you to later update your file, and view it in the client.

rdme openapi [url-or-local-path-to-file]

If you want to bypass the prompt to create or update an API definition, you can pass the --create flag:

rdme openapi [url-or-local-path-to-file] --version={project-version} --create
Editing (Re-Syncing) an Existing API Definition

This will edit (re-sync) an existing API definition (identified by --id) within your ReadMe project. This is the recommended approach for usage in CI environments.

rdme openapi [url-or-local-path-to-file] --id={existing-id}
Uploading or Editing an API Definition in a Project Version

You can additionally include a version flag, specifying the target version for your file's destination. This approach will provide you with CLI prompts, so we do not recommend this technique in CI environments.

rdme openapi [url-or-local-path-to-file] --version={project-version}

If you wish to use the version specified in the info.version field of your API definition, you can pass the --useSpecVersion option. For example, say the info object of your API definition looks like this:

{
  "version": "1.2.3",
  "title": "Single Path",
  "description": "This is a slimmed down single path version of the Petstore definition."
}

You can pass in the --useSpecVersion option, which would be equivalent to passing in --version=1.2.3:

rdme openapi [url-or-local-path-to-file] --useSpecVersion

You can add --update to the command so if there's only one API definition for the given project version to update, it will select it without any prompts:

rdme openapi [url-or-local-path-to-file] --version={project-version} --update
Override the Working Directory

By default, rdme bundles all references with paths based on the directory that rdme is being run in. You can override the working directory using the --workingDirectory option, which can be helpful for bundling certain external references (see here for an example file).

rdme openapi petstore.json --workingDirectory=[path to directory]

Validating an API Definition

You can also perform a local validation of your API definition (no ReadMe account required!), which can be useful when constructing or editing your API definition.

rdme openapi:validate [url-or-local-path-to-file]

Similar to the openapi command, you can also omit the file path.

Reducing an API Definition

We also offer a tool that allows you to reduce a large API definition down to a specific set of tags or paths (again, no ReadMe account required!). This can be useful if you're debugging a problematic schema somewhere, or if you have a file that is too big to maintain.

rdme openapi:reduce [url-or-local-path-to-file]

The command will ask you a couple questions about how you wish to reduce the file and then do so. If you wish to automate this command, you can pass in CLI arguments to bypass the prompts. Here's an example use case:

  • The input API definition is called petstore.json
  • The file is reduced to only the /pet/{id} path and the GET and PUT methods
  • The output file is called petstore.reduced.json

Here's what the resulting command looks like:

rdme openapi:reduce petstore.json --path /pet/{id} --method get --method put --out petstore.reduced.json

As with the openapi command, you can also omit the file path.

Inspecting an API Definition

This tool can also perform a comprehensive analysis (again, no ReadMe account required!) of your API definition to determine how it's utilizing aspects of the OpenAPI Specification (such as circular references, polymorphism, etc.) and any ReadMe-specific extensions you might be using.

rdme openapi:inspect [url-or-local-path-to-file]

This command contains a --feature flag so you can filter for one or several specific features. If you pass in one or more --feature flags, the command returns a 0 exit code if your definition contains all of the given features and a 1 exit code if your definition lacks any of the given features.

rdme openapi:inspect [url-or-local-path-to-file] --feature circularRefs --feature polymorphism

As with the openapi command, you can also omit the file path.

Converting an API definition

You can also convert any Swagger or Postman Collection to an OpenAPI 3.0 definition.

rdme openapi:convert [url-or-local-path-to-file]

Similar to the openapi command, you can also omit the file path.

Note

All of our OpenAPI commands already do this conversion automatically, but in case you need to utilize this exclusive functionality outside of the context of those, you can.

Docs (a.k.a. Guides) ๐Ÿ“–

The Markdown files will require YAML front matter with certain ReadMe documentation attributes. Check out our docs for more info on setting up your front matter.

Passing in a path to a directory will also sync any Markdown files that are located in subdirectories. The path input can also be individual Markdown files.

rdme docs [path] --version={project-version}

This command also has an alias called guides:

rdme guides [path] --version={project-version}

This command also has a dry run mode, which can be useful for initial setup and debugging. You can read more about dry run mode in our docs.

Prune

If you wish to delete documents from ReadMe that are no longer present in your local directory:

rdme docs:prune [path-to-directory-of-markdown]

Run with --confirm to bypass the confirmation prompt (useful for CI environments).

This command also has an alias called guides:prune:

rdme guides:prune path-to-directory-of-markdown

Changelog ๐Ÿ“ฃ

The Markdown files will require YAML front matter with certain ReadMe documentation attributes. Check out our docs for more info on setting up your front matter.

Passing in a path to a directory will also sync any Markdown files that are located in subdirectories. The path input can also be individual Markdown files.

rdme changelogs [path]

This command also has a dry run mode, which can be useful for initial setup and debugging. You can read more about dry run mode in our docs.

Custom Pages ๐Ÿ“„

Custom Pages has support for both Markdown and HTML files. These files will require YAML front matter with certain ReadMe documentation attributes. Check out our docs for more info on setting up your front matter.

Passing in a path to a directory will also sync any HTML/Markdown files that are located in subdirectories. The path input can also be individual HTML/Markdown files.

rdme custompages [path]

This command also has a dry run mode, which can be useful for initial setup and debugging. You can read more about dry run mode in our docs.

Versions โณ

Get All Versions Associated With Your Project

rdme versions
Get All Information About a Particular Version
rdme versions --version={project-version}

Create a New Version

rdme versions:create <version>

If you wish to automate the process of creating a new project version, and not have the CLI prompt you for input, you can do so by supplying the necessary flags to versions:create. The best way to ensure that you have supplied all the necessary flags is by running the command locally and verifying that the CLI does not prompt you.

For example, the following command contains all the flags to bypass the CLI prompts:

rdme versions:create <version> --fork={version-fork} --main={true|false} --beta={true|false} --deprecated={true|false} --hidden={true|false}

See rdme versions:create --help for a full list of flags.

Update a Version

rdme versions:update <version>

Like versions:create, if you wish to automate this process and not be blocked by CLI input, you can supply the necessary flags to this command. See rdme versions:update --help for a full list of flags.

Delete a Version

You can remove a specific version from your project, as well as all of the attached specs

rdme versions:delete <version>

Categories ๐Ÿชฃ

Get All Categories Associated to Your Project Version

rdme categories --version={project-version}

Create a New Category for your Project Version

rdme categories:create <title> --categoryType={category-type} --version={project-version}

categoryType is required and must be set to either guide or reference

If you want to prevent the creation of a duplicate category with a matching title and categoryType, supply the --preventDuplicates flag.

Open Your ReadMe Project in Your Browser

If you are logged in, this will open the project in your browser:

rdme open

Future

We are continually expanding and improving the offerings of this application as we expand our public API and are able. Some interactions may change over time, but we will do our best to retain backwards compatibility.

rdme's People

Contributors

benwaffle avatar darrenyong avatar dependabot-preview[bot] avatar dependabot[bot] avatar domharrington avatar erunion avatar garrett-wade avatar gkoberger avatar gratcliff avatar jdecool avatar kanadgupta avatar kellyjosephprice avatar mjcuva avatar ollyfg avatar pvorb avatar rahulhegdee avatar ryangwu82 avatar semantic-release-bot avatar shaiarmis avatar superic avatar t-tullis avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rdme's Issues

Can I set `parentDoc` etc. of a document with your API?

When retrieving document details via /api/v1/docs/slug I see a lot of juicy stuff that's reflected in the UI, for instance:

"parentDoc":"5c653f75f49e7d00516eb11e","__v":0,"updates":[],"next":{"pages":[],"description":""}

However, if I export a document I get a markdown doc with headers that does not contain that info. The header will usually just have title and category. All the other good stuff seems to be associated with the slug, but is stored somewhere server-side.

So the question is, can I update these other properties as well through API calls? I'm seeing options here:

https://github.com/readmeio/rdme/blob/master/lib/docs/edit.js#L63-L67

but I can't confirm what optional parameters do on the backend. i.e. is this intended / does it work:

slug = 'xxx'
version = 'v1.0'
url = host + "/api/v1/docs/" + slug
headers = {
    'x-readme-version': version,
    'content-type': "application/json",
}
# Note: headers need to be extracted from yaml
payload = json.dumps({
    'title': "xxx",
    'category': "5c653f7f24320544d0",
    'body': "Foo can be installed in two ways. bla bla"
    'parentDoc': "other-slug" # <-- TODO like this?
})

response = requests.request("PUT", url, data=payload, headers=headers, auth=auth)
print(response.text)

upload request timed out

Every time I try to upload my file:

rdme openapi swagger/v1/swagger.json --key=yyy --id=xxx

it raises:

We're sorry, your upload request timed out. Please try again or split your file up into smaller chunks.

Where can I find out more informations about it?
Size allowed?
What do?

Docs touch-ups

Noting some docs touch-ups here:

  • Update the markdown frontmatter examples in rdme.md to reflect the actual frontmatter of that page
  • Expand on GHA version guidance in README.md to talk about why we want the user to fix the version
  • Update link to knowledge base GHA usage to point to header

Update existing docs and creating new ones in practice

Hi readmeio team (@domharrington),

thanks for your work on this project - love it. I'd like to incorporate rdme in a docs project, but have some problems getting started.

Setup: I created a new readme.io project and started new docs, v1.0 and v1.1 to test functionality. Both have a Documents category. I exported and unzipped the project locally to use the CLI with it. rdme login works fine. rdme docs:edit <slug> works fine (except that it's unfortunate that the slug is not in the markdown header of the doc and you have to look it up for each doc).

Issue 1: I can't seem to update existing docs with rdme docs <folder> --version=<version>. I changed one of the files in the existing project and ran (file is called ./v1.0/Documentation/sandbox.md)

โ•ฐโ”€$ rdme docs ./v1.0/ --version=v1.0                                                                                                                                                                            
[]

The return value doesn't tell me much, but surely the doc does not update. I'm curious what I am supposed to see. If instead I run this (add Documentation):

โ•ฐโ”€$ rdme docs ./v1.0/Documentation/ --version=v1.0
Doc validation failed
{ category: 'Path `category` is required.' }

I get this interesting category error. From the test fixtures I see that for new docs a category seems required. But this is an existing one. This latter call seems to correspond to what I see in tests.

Issue 2: How do you create new documents in practice? It seems, as shown in tests, that I need the category ID to add a new document. Otherwise it will throw the same error as above. That information is, unlike slugs, not available in the readme.io UI. So the only way I see to retrieve this info seems to be to resort to the HTTP API. Is that correct? If so that makes it very difficult to work only with rdme.

My goal is to manage docs from a GitHub repo, pushing to readme.io through rdme for releases. This way it's much easier for me to test and manage code snippets.

docs should check that category ids match the specified version

Background

  • OS: Mac OSX 12.2.1
  • rdme: 7.2.0

Symptom

Running rdme docs ./folder --key <key> --version <version> where the category ids in the YAML Front Matter Blocks are for a different version than the one specified on the command line returns a confusing error:

Error uploading <file path>:

We couldn't save this doc (Page slug must be unique.).

If you need help, email [email protected] and include the following link to your API log: '<log url>'.

Expected Behavior

Instead of returning a "page slug must be unique" error, the rdme CLI should check the category ids in the Front Matter Blocks against those returned by the /categories API for the version specified to the rdme docs command and return a "category not found for this version" error.

Steps to Reproduce

  1. Create README project with multiple versions and categories. Create a few documents in one of the categories.
  2. Grab the category ids for one of the versions, use those in the YAML Front Matter Block
  3. Run rdme docs ... --version <different version id> for a different version id then the one chosen in step (2).

Worst Case

Also, if as a user you take the error message at its word (as I did) and change the page slug to be unique, then you get a really bad outcome. The category id in the YAML Front Matter block wins out over the version specified on the command line and the rdme docs command will update the version associated with the category id. This is very unexpected and in my case updated the "stable" version of my docs, duplicating all of the documents with new slugs.

Non-zero exit status on failure

It would be great to have a non-zero exit status if a command fails (specifically rdme openapi) that way our ci will fail the build instead of reporting success when it wasn't successful.

Thanks for all the hard work!

SyntaxError: Unexpected token '.' on w/ v7.0.0 upwards

โฏ npx rdme docs ../docs/ --version=1.4.5 --key xxx --dryRun
.../docs/node_modules/rdme/bin/rdme:23
    if (err?.message) {
            ^

SyntaxError: Unexpected token '.'
    at wrapSafe (internal/modules/cjs/loader.js:915:16)
    at Module._compile (internal/modules/cjs/loader.js:963:27)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:60:12)
    at internal/main/run_main_module.js:17:47

Running on

Distributor ID: Ubuntu
Description:    Ubuntu 18.04.6 LTS
Release:        18.04
Codename:       bionic

rdme/bin/rdme

Line 23 in bb69d37

if (err?.message) {

`rdme versions --raw` doesn't output the raw JSON response

It instead outputs the JS object version (the keys aren't stringified), which means you can't easily pipe it to a tool such as jq.

The reason I'm doing this in the first place is because it looks like there is no command to get the main version? And the reason I'm doing that is because it looks like there is no way to sync an API reference using the main version (without knowing which version is main)? (edit: I had a typo in the environment variable I was passing to the --id parameter, which I why I was seeing a prompt when running rdme openapi ... ๐Ÿคฆ๐Ÿผ)

If either of these assumptions are wrong, that'd make my life easier ๐Ÿ˜… But even in that case it'd probably be better for --raw to output raw JSON for any other use cases people might have.

Do not require to run actions/setup-node

Hey,

This is to make you aware that some of your customers may have disabled running actions other than those cloned to their own organization. In our use case, for security reasons we consider all third-party actions to be unsafe, therefore we clone an action we need to run in our GITHUB CI environment, which allows us to only run a select number of actions.

Therefore, in our case it's impossible to run readmeio/rdme since it depends on setup-node, so we see this error message:

Error: Bad request - actions/setup-node@v2 is not allowed to be used in <company_name>. Actions in this
workflow must be within a repository owned by <company_name> or match the following: actions/setup-node@v2.

The solution may be quite trivial: given that both NodeJS and npm are provisioned by default, you hardly even need to run that action.

Will you consider not using any third-party actions please?

Front Matter Block Category should support category slug instead of id

Background

  • OS: Mac OSX 12.2.1
  • rdme: 7.2.0

Symptom

See the error described in #497.

Description

I may be doing something wrong, but it seems like a common use case to want to upload a set of the same .md files to multiple versions, e.g. dev and prod. The fact that the rdme docs command accepts a version seems to support this use case. However, the user must preprocess the .md to ensure that the category ids in the YAML Front Matter blocks match the version specified to the rdme docs command.

Since the category slugs are consistent across versions, it would be nice to specify the category slug in the YAML Front Matter Block instead of the id, then the rdme docs command could programmatically find the appropriate category id based on the specified version.

6.0.0 won't install on the `node:lts-alpine` image

We sync our API docs on node:lts-alpine images via CircleCI. This has worked fine since we first started doing it in late September (meaning using rdme versions 5.1.4 and 5.2.0), but now blows up with the new 6.0.0 release.

The error message from npm is rather cryptic:

npm ERR! syscall spawn git
npm ERR! path git
npm ERR! errno -2
npm ERR! enoent An unknown git error occurred
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent 

Here are the full logs for the failed 6.0.0 install, along with logs from a subsequent successful install of 5.2.0 in the same VM.

npm-install-g-5-2-0.log
npm-install-g-6-0-0.log

I tried taking a look at both of these to see if there was anything obvious but couldn't spot it. timing idealTree Completed shows up in the 5.2.0 log but not the 6.0.0 log. I don't know what that line represents ๐Ÿคท๐Ÿผ

Add support for subfolder sync to rdme CLI

Hi

Just used rdme CLI to sync a bunch of find and replace changes across many files. It worked great, so thanks for providing this tool.

It would be really useful if the rdme CLI could support local subfolder recursion. I achieved this by creating my own batch file that called rdme for each subfolder.

Many thanks for considering this request.

Remove critical npm vulnerability

Screen Shot 2019-03-12 at 8 18 02 PM

I understand that this open package may be useful for login, but having the critically severe vulnerability warning in the npm warnings makes this package impossible to use in CI for anybody that has strict vulnerability standards.

Version creation does not work

I have an issue with versions creation via the rdme client. Expected to have one more version after creation, but does not exist neither in listing, nor in the dashboard.

$ docker run -it -v /path/to/my/apidocs:/proj node:14-alpine /bin/sh
/ # export README_API_KEY=xxxxxxxxxxxxxxxxx
/ # npm install rdme -g
npm WARN deprecated [email protected]: request has been deprecated, see https://github.com/request/request/issues/3142
/usr/local/bin/rdme -> /usr/local/lib/node_modules/rdme/rdme.js
+ [email protected]
added 287 packages from 188 contributors in 37.552s
/ # rdme versions --key=$README_API_KEY
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Version โ”‚ Codename โ”‚ Is deprecated โ”‚ Is hidden โ”‚ Is beta โ”‚ Is stable โ”‚ Created on               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 0       โ”‚ base     โ”‚ no            โ”‚ no        โ”‚ no      โ”‚ yes       โ”‚ 2020-06-16T13:22:32.017Z โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1.0.0   โ”‚ base     โ”‚ no            โ”‚ no        โ”‚ no      โ”‚ no        โ”‚ 2020-06-16T13:22:32.017Z โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
/ # rdme versions:create --version=1.0.1 --fork=1.0.0 --key=$README_API_KEY
/ # rdme versions --key=$README_API_KEY
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Version โ”‚ Codename โ”‚ Is deprecated โ”‚ Is hidden โ”‚ Is beta โ”‚ Is stable โ”‚ Created on               โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 0       โ”‚ base     โ”‚ no            โ”‚ no        โ”‚ no      โ”‚ yes       โ”‚ 2020-06-16T13:22:32.017Z โ”‚
โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1.0.0   โ”‚ base     โ”‚ no            โ”‚ no        โ”‚ no      โ”‚ no        โ”‚ 2020-06-16T13:22:32.017Z โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
/ # 

It works if I do a direct POST call to https://dash.readme.io/api/v1/version with curl.

How does doc syncing work?

I'm trying to sync docs but my changes are not reflected. Due to clashing slugs, I've changed all the file names by prepending a category eg api-${old_slug}. I have also changed the folder structure. Could those changes have caused issues?

  1. I get an empty array back and nothing happens. What does this mean? Is it an error?
  2. Are folders categories?
  3. Does it automatically create new categories?
  4. Does it automatically delete categories that are no longer there?
  5. How deeply can you nest folders?
  6. How are renamed files handled?

rdme swagger command throws error

Hey there,

I can't update our swagger definitions using the CLI right now. When I run rdme --key=<readme-key> --id=<readme-docs-id> swagger main.yaml it gives the error Cannot read property 'indexOf' of undefined.

After a bit of investigation, I've found out that this can be related to your API. The PUT /api-specification/:specId endpoint returns 500 with {"error":"Cannot read property 'indexOf' of undefined"} body from the call made with CLI.

Better error handling for incorrect categories added

It's possible to create a Markdown file that is "mostly" valid but may have an incorrect character in the category: field. When sync'ing with docs, these files are skipped with no error. For example:

---
title: "Update an existing pet"
slug: "updatepet"
category:ยท6154c7c5b68688042eee057b
---
This is body text for the page

If you attempt to sync this file, you will get an ambiguous status:

โฏ npx rdme docs test_folder
โœ” Would you like to use an existing version or create a new one to associate with your OAS file? ยท update
โœ” Select your desired version ยท 1.0
[]

Unable to update docs using docs command

Hi, I am trying to use the docs command to create or update our guides in an automated way in a CI pipeline, but instead of updating a doc that exists, the CLI keeps creating a new one. I have the slug for the doc defined in the front matter of the markdown file and the file name matches this slug.

Looking at the source code for the command here it looks like when the updateDoc function is called it gets passed undefined for existingDoc parameter, which should raise an error in the if-check in the beginning of the function, which makes it always create the doc instead.

`undefined` error with pages created with 'createDoc' API w/ [email protected]

I am currently trying to create one-way sync from Github to Readme so our repo is source of truth.

I am running into an error trying to sync pages after creating new page with createDoc API.

Returning an 'undefined' error

โฏ npx rdme ...docs/ --version=1.4.5 --key xxx

Error uploading ...docs/clustering-features/clustering/subclustering.md

undefined

Frontmatter of the file as stated herein the 'Syncing Docs via CLI / GitHub' docs.

---
title: "Subclustering"
slug: "subclustering"
excerpt: "Subclusetring example"
hidden: false
category: 623a96a3032c43002ef2c617
parentDoc: 623a96a3032c43002ef2c68d
---

Please let me know if I am doing sth wrong here!

โฏ npx rdme --version
6.5.0

Remove installation warnings

I get the following warnings when I install with yarn, the only warnings in our entire monorepo are being emitted by readmeio packages

warning rdme > [email protected]: The package has been renamed to `open`

`rdme help versions:create` throws chalk template error

Hi there!

If I run rdme versions:create with no arguments I receive the following output:

jamiebrynes /c/Workspace/Develop/trebuchet ๎œฅ (master)
ฮป rdme versions:create
No version provided. Please specify a semantic version. See `rdme help versions:create` for help.

but running rdme help versions:create returns an error:

jamiebrynes /c/Workspace/Develop/trebuchet ๎œฅ (master)
ฮป rdme help versions:create
Found extraneous } in Chalk template literal

You then have to dig around in the source to find the options - https://github.com/readmeio/rdme/blob/master/cmds/versions/create.js#L7

Docs duplicated and not sync'ed

I use the following command to attempt to sync my documents folder with the readme backend.

npx rdme docs ./v1.0/ --version=1.0 --key API_KEY-GOES_HERE

The output of my versions is

[
  {
    version: '1.0',
    version_clean: '1.0.0',
    codename: '',
    is_stable: true,
    is_beta: false,
    is_hidden: false,
    is_deprecated: false,
    _id: '620a5ec4dbe8a-half-removed,
    createdAt: '2022-02-14T13:53:08.575Z'
  }
]

Everytime I sync them with the above command, it duplicates the file and increments the slug with -1, -2, etc.
Screenshot 2022-02-21 at 08 38 33

My page headers are as follows:


---
title: "Best Practices"
excerpt: "brief description of best pracitces"
category: "620a5ec4dbe8a70-valid-category-id"
---
Some content here

There is no --verbose or --debug option to support with debugging.

Version 6.4.0

Github actions secrets correction in documentation

Currently in the main sync docs here the method used for using github secrets doesn't work. It requires the addition of $ at the start to yield the secret:

Old

- uses: readmeio/rdme@RDME_VERSION
  with:
    rdme: openapi [path-to-file.json] --key={{ secrets.README_API_KEY }} --id={{ secrets.README_API_DEFINITION_ID }}

New

- uses: readmeio/rdme@RDME_VERSION
  with:
    rdme: openapi [path-to-file.json] --key=${{ secrets.README_API_KEY }} --id=${{ secrets.README_API_DEFINITION_ID }}

Version indefined

Hello,

I am getting the following error when I run yarn run rdme swagger ./swagger.json

{"error":"Cannot read property 'version' of undefined"}

Add support for changelog endpoints

The readme API includes endpoints that relate to changelogs but the CLI doesn't currently support them. Would the maintainers be open to a PR that added support? Are there contributor guidelines?

PDF Generation!

Okay, one of our biggest feature requests is PDF generation. It's something we feel fits best in a CLI tool.

Syntax: rdme pdf filename.pdf

What it does: uses the API to download all the pages, and generates a PDF (including a table of contents)

Unknown error uploading json

We are currently running into the following error when trying to use this rdme cli, specifically the generic

There was an error uploading!

It would be helpful to have a --verbose flag to state what the error actually is or just actually put the error message directly in the string above.

Thanks!

rdme npm sdk methods are available?

Hi, I am someone who is trying to accommodate the rdme CLI commands through a nodejs script within the code.
I am trying to use execSync method of child_process in nodejs but not getting positive results. in Local it works but when I push to my bitbucket repository and when the bitbucket pipeline triggers 'ts-node testScript.ts', I get error like

"error: unknown option '--key=mykey'
Error: Command failed: npx -y [email protected] openapi 'temp/readme/myyamlfile.yaml' --key=mykey --id=mydefId"

So, here is my eventual question,

  • do we have sdk methods to achieve this task?
  • If not, can you suggest how should I do it? and how to remove this kind of error?

rdme swagger exits with exit code 0 on error

Problem

rdme swagger exits with exit code 0 on error

Steps for reproduce

run rdme swagger with invalid json
rdme will return json string with error message and 'There was an error uploading!'
but echo $? will return 0

Environment

rdme 2.2.2
node 8.14.0
alpine linux 3.8 docker container

Sync specs without requiring an API Definition ID

I'm attempting to sync a set of API specs in my project through Github Actions. In order to do so I require an API definition ID per spec. I can obtain this through the admin portal once I upload a spec file using the CLI or manual approach you've documented here.

I'd like to automate syncing specs through GH Actions and not require the initial step of having to upload manually in order to get this API definition ID. I'm still new to GH actions, but my desire is to store all my team's "published-ready" specs in one directory, and create an action that will iterate through each spec file in this directory and upload them to Readme.

Feature Request: Wondering if Readme can implicitly match and formulate this ID based on some properties (ex: info.title) within a spec file's definition without explicitly requiring it?

Syncing OpenAPI files to a version with a dash submits to the wrong version

I'm trying to sync a proof-of-concept OpenAPI document to my employer's ReadMe instance. We have a private staging version named v2-stage, as well as a live version named v2.

However, when I sync to v2-stage using the following command...

rdme openapi --version=v2-stage --key=$README_API_KEY ./openapi.yml

...rdme syncs to v2 instead. This resulted in heavily work-in-progress documentation briefly going live. Everything after the - was ignored.

As a workaround, I renamed v2-stage to v3. The command then worked as expected.

GET categories/<slug> does not work

Sorry for referring to the underlying HTTP API again, but in the end this is just a wrapper. I'm using Python to demonstrate my point. If I use:

# Get category for slug
slug = 'subpage'
version = 'v1.0'
url = host + "/api/v1/categories/" + slug
headers = {'x-readme-version': version}
response = requests.request("GET", url, headers=headers, auth=auth)
print(response.text) 

That will result in an error message, although the page exists and has a category. I can even confirm this by reading slug details for the same doc:

# Get doc/slug details WORKS
slug = 'subpage'
version = 'v1.0'
url = host + "/api/v1/docs/" + slug
headers = {'x-readme-version': version}
response = requests.request("GET", url, headers=headers, auth=auth)
print(response.text)
details = json.loads(response.content)
category = details.get('category')

so either I'm doing something fundamentally wrong or the endpoint doesn't work as expected

Setting the "parentDoc" for a document to itself prevents you from deleting that document

Hi,

Love the product so far! That being said, I did encounter one issue: during one test run of a CICD integration, I mistakenly set the parentDoc of a document to be its own ID:

GET https://dash.readme.io/api/v1/docs/{doc-slug}

{
    ...
    "parentDoc": "5f46b08d5688b911ed64801a",
    "id": "5f46b08d5688b911ed64801a",
}

This causes the document to not even show in the ReadMe dash under its category. However, it can be retrieved via the API. Also, you cannot delete the document from the system due to the circular reference:

DELETE https://dash.readme.io/api/v1/docs/{doc-slug}

{
    "error": "INTERNAL_ERROR",
    "message": "Unknown error (You cannot remove pages with children)",
    ...
}

This also prevents me from being able to delete the category containing the doc, since that document is stuck in there.

To work around this issue, you can make a PUT request and set the parentDoc of the API to null. Then, you can delete it. I believe it would be a better approach to have the API not allow cyclical references for parentDoc.

This is probably less of a CLI issue and more of an API issue, but this seemed like the next best place to report it.

Thanks for your time!

Failed to load lib/swagger.js

node v7.10.1 failed to load lib/swagger.js, have to get rid of the ',' at the end of line 16 and the other line a couple of blocks below.

Cannot find module 'ajv/dist/core'

Hello ๐Ÿ‘‹

I recently installed rdme as a dev dependency, but when I tried to run it for the first time, I got the following error:

Cannot find module 'ajv/dist/core'
Require stack:
- /src/node_modules/ajv-draft-04/dist/index.js
- /src/node_modules/@readme/openapi-parser/lib/validators/schema.js
- /src/node_modules/@readme/openapi-parser/lib/index.js
- /src/node_modules/oas-normalize/index.js
- /src/node_modules/rdme/src/lib/prepareOas.js
- /src/node_modules/rdme/src/cmds/openapi.js
- /src/node_modules/rdme/src/lib/commands.js
- /src/node_modules/rdme/src/lib/help.js
- /src/node_modules/rdme/src/index.js
- /src/node_modules/rdme/bin/rdme

Node version is v14.18.3 and npm version is 6.14.15

I tried running it in a container (node:14-alpine) that had nothing else installed but Node and NPM, and it seemed to be working.
My assumption is that this is due to the fact I have other dependencies that require lower versions of ajv:

How to set boolean flags to false for automation

Hey!

The docs on automation state that you should pass values to prevent being prompted for manual intervention during version creation. The example only shows setting the booleans to true. How do you set them to false?

I've tried --main=0, --main=false, --main=False, and -n but all give errors eg Unknown value: --main=0. I'm not sure if this is a bug or just a missing piece of documentation?

Add an underlying GET /categories endpoint and expose it to rdme

I have a use case in which I want to iterate through top level categories. Right now I can only get a category for a slug. So to get all categories I first need to know all slugs, then get all categories for them. This is a fairly simple and obvious endpoint to have, I think.

In general, for each entity you expose, it's a good idea to have GET /<entity> and wrap it in readme.

JavaScript heap out of memory

Everytime I try to upload my swagger.json file using either

rdme swagger.json --token=xxxxxxxxxxxx

or

oas host

my JS heap runs out of memory. The swagger.json file is barely 52 kB. Not sure why the heap keeps running out of memory.

Backend support for `cli-gh` source

As a follow up to #443, we need to add backend support for the new x-readme-source header we're using in GitHub Actions environments. This issue tracks that support.

YAML support

Currently we can only upload OpenAPI specification written in JSON.

It would be great to allow upload YAML specification.

Incorrect error given when sync'ing spec

When sync'ing a spec file like such:

$ rdme swagger swagger.json --key="API_KEY" --id=abcdef12345abcdef12345

You'll end up with an error:

The spec you uploaded isn't a valid JSON or YAML file. Here's the error we found:

Not valid YAML

The spec file is valid, the issue is that the id string isn't wrapped in ""

Fix Auth documentation

https://readme.readme.io/reference/authentication

Unclear to me why the auth endpoint is not documented and we only see a little sentence:

The ReadMe API uses basic authentication with the username as your API key and the password is blank.

In Python this would be:

host = 'https://dash.readme.io'
  
data = {'email': '[email protected]', 
        'password': 'adsfdafjkhadskhjf', 
        'project': 'my-project'} 
  
r = requests.post(url = host + '/api/v1/login', data = data) 
content = json.loads(r.content)
api_key = content.get('apiKey')

In the rdme source code you see a 2FA token as optional(?) argument, that I'd like to use. Documentation would help there

You can use readme.io to document your API, it's a great tool :D

`rdme versions:create` doesn't validate the version you give to it

As far as I can tell, readme.io allows versions similar to 4, 4.0, 4.0.1, and 4.0.1-commit-sha but not something like test.

However, the rdme CLI will allow you to attempt to create a version with an invalid version and returns a not particularly helpful error message:

ฮป rdme versions:create --version=test
โˆš Which version would you like to fork from? ยท 1.0.2
โˆš Would you like to make this version the main version for this project? (y/N) ยท false
โˆš Should this version be in beta? (y/N) ยท false
โˆš Would you like to make this version public? (y/N) ยท false
Failed to create a new version using your specified parameters.

Ideally, you get a nice

"Error: version `test` invalid, must be ..."

before you are even prompted for the extra information

Invalid JSON in Markdown upload response

I am uploading Markdown documents with:

rdme docs . --version="v1.0" --key=[key]

using versoin 3.5.0.

They get uploaded successfully and in the response a get a JSON-like object with information on the upload. I am using Python to parse this response, but since it is not valid JSON this is not so simple, to be a valid JSON structure it needs to have double quotes on the keys: docs

An object structure is represented as a pair of curly brackets
surrounding zero or more name/value pairs (or members). A name is a
string
. A single colon comes after each name, separating the name
from the value.

Could this please be updated so that the response object has quoted key names?

Response object (with my data removed):

[ { __v: 0,
    version: '[version-id]',
    updatedAt: '2019-12-09T10:45:01.875Z',
    createdAt: '2019-12-09T10:45:01.875Z',
    category: '[category-id]',
    lastUpdatedHash: '4dd02849e3f5a032a827077f91c4d1506c6cfbd9',
    updates: [],
    _id: '[id]',
    next: { pages: [], description: '' },
    link_external: false,
    link_url: '',
    sync_unique: '',
    hidden: true,
    api: { auth: 'required', params: [], url: '', method: 'get' },
    isReference: false,
    order: 999,
    body: '[body-text]',
    excerpt: '',
    slug: '[slug]',
    type: 'basic',
    metadata: { description: '', title: '', image: [] },
    title: '[title]',
    id: '[id]',
    isApi: false } ]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.