diff --git a/.deepsource.toml b/.deepsource.toml deleted file mode 100644 index 82583e262..000000000 --- a/.deepsource.toml +++ /dev/null @@ -1,7 +0,0 @@ -version = 1 - -[[analyzers]] -name = "javascript" - -[[transformers]] -name = "prettier" \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..997807e90 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,56 @@ +--- +name: New Bug Report +about: Use this template for reporting new bugs. +title: "[BUG]: bug description here" +labels: bug +--- + + + +## Issue Type + + + +## Context (Environment, Version, Language) + + + +Input Format: +Output Language: + + + +CLI, npm, or app.quicktype.io: +Version: + +## Description + + + + +## Input Data + + + + +## Expected Behaviour / Output + + + +## Current Behaviour / Output + + + +## Steps to Reproduce + + + + +1. +2. +3. +4. + +## Possible Solution + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..dd39e6d26 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +# contact_links: +# - name: GitHub Community Support +# url: https://github.com/orgs/community/discussions +# about: Please ask and answer questions here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..5aab66de0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,40 @@ +--- +name: Feature Request +about: Use this template for requesting new features. +title: "[FEATURE]: feature description here" +labels: enhancement +--- + + + +## Context (Input, Language) + + + +Input Format: +Output Language: + +## Description + + + + +## Current Behaviour / Output + + + +## Proposed Behaviour / Output + + + +## Solution + + + +## Alternatives + + + +## Context + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..86eeba010 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,29 @@ +## Description + + + +## Related Issue + + + + + +## Motivation and Context + + + + +## Previous Behaviour / Output + + + +## New Behaviour / Output + + + +## How Has This Been Tested? + + + + +## Screenshots (if appropriate): diff --git a/.github/workflows/master.yaml b/.github/workflows/master.yaml index 852ae762d..363eec663 100644 --- a/.github/workflows/master.yaml +++ b/.github/workflows/master.yaml @@ -6,10 +6,13 @@ on: jobs: publish: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - uses: ./.github/workflows/setup + env: + PUBLISH: true - run: npm run pub env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + VSCE_TOKEN: ${{ secrets.VSCE_TOKEN }} diff --git a/.github/workflows/setup/action.yaml b/.github/workflows/setup/action.yaml index 89c7367ee..6eb937510 100644 --- a/.github/workflows/setup/action.yaml +++ b/.github/workflows/setup/action.yaml @@ -19,7 +19,7 @@ runs: echo "source_key=$SOURCE_KEY" >> $GITHUB_ENV - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ env.node_version }} cache: npm diff --git a/.github/workflows/test-pr.yaml b/.github/workflows/test-pr.yaml index b9af1b9f2..d497d9b1c 100644 --- a/.github/workflows/test-pr.yaml +++ b/.github/workflows/test-pr.yaml @@ -3,9 +3,10 @@ on: pull_request: branches: - master + - "release/**" jobs: build: - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - uses: actions/checkout@v3 - uses: ./.github/workflows/setup @@ -31,11 +32,12 @@ jobs: - csharp,schema-csharp,schema-json-csharp,graphql-csharp,csharp-SystemTextJson - json-ts-csharp - dart,schema-dart - - swift,schema-swift + # - swift,schema-swift # pgp issue - javascript-prop-types - ruby - php - scala3,schema-scala3 + - elixir,schema-elixir,graphql-elixir # Partially working # - schema-typescript # TODO Unify with typescript once fixed @@ -43,7 +45,7 @@ jobs: # Implementation is too outdated to test in GitHub Actions # - elm,schema-elm - # Language is too niche / obscure to test easily on ubuntu-latest + # Language is too niche / obscure to test easily on ubuntu-22.04 # - pike,schema-pike # Not yet started @@ -54,18 +56,18 @@ jobs: # Never tested? # - crystal - runs-on: [ubuntu-latest] + runs-on: [ubuntu-22.04] include: # Rust is very slow, so we use a larger runner - fixture: rust,schema-rust - runs-on: ubuntu-latest-8-cores + runs-on: ubuntu-latest-16-cores # Kotlin is also slow - fixture: kotlin,schema-kotlin,kotlin-jackson,schema-kotlin-jackson - runs-on: ubuntu-latest-8-cores + runs-on: ubuntu-latest-16-cores - - fixture: objective-c - runs-on: macos-11 + # - fixture: objective-c # segfault on compiled test cmd + # runs-on: macos-latest name: ${{ matrix.fixture }} steps: @@ -176,10 +178,20 @@ jobs: - run: echo '@main def hello() = println("We need this spam print statement for bloop to exit correctly...")' | scala-cli _ if: ${{ contains(matrix.fixture, 'scala3') }} + - name: Install Elixir + if: ${{ contains(matrix.fixture, 'elixir') }} + uses: erlef/setup-beam@v1 + with: + elixir-version: "1.15.7" + otp-version: "26.0" + - run: QUICKTEST=true FIXTURE=${{ matrix.fixture }} npm test test-complete: + if: ${{ cancelled() || contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'failure') }} needs: test - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 steps: - - run: echo πŸŽ‰ + - run: | + echo "Some workflows have failed!" + exit 1 diff --git a/.gitignore b/.gitignore index f800a1642..7178f4122 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,3 @@ test/fixtures/objective-c/quicktype /.bsp .metals .scala-build -.vscode diff --git a/.nvmrc b/.nvmrc index 9dfef4721..517f38666 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v18.12.0 +v22.14.0 diff --git a/.prettierrc b/.prettierrc deleted file mode 100644 index 1e80e79ea..000000000 --- a/.prettierrc +++ /dev/null @@ -1 +0,0 @@ -{ "tabWidth": 4, "printWidth": 120, "trailingComma": "none", "arrowParens": "avoid" } diff --git a/.vscode/launch.json b/.vscode/launch.json index 7c36e6c8a..1cbad2c56 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,40 +1,40 @@ { - // Use IntelliSense to learn about possible Node.js debug attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "quicktype", - "type": "node", - "request": "launch", - "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", - "runtimeArgs": ["--nolazy"], - "args": [ - "--project", - "src/cli/tsconfig.json", - "src/cli/index.ts", - "--lang", - "dart", - "--src-lang", - "json", - "./test/inputs/json/priority/blns-object.json" - ], - "cwd": "${workspaceRoot}", - "protocol": "inspector" - }, - { - "name": "test", - "type": "node", - "request": "launch", - "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", - "args": ["--project", "test/tsconfig.json", "test/test.ts"], - "cwd": "${workspaceRoot}", - "protocol": "inspector", - "env": { - "CPUs": "1", - "FIXTURE": "golang" - } - } - ] + // Use IntelliSense to learn about possible Node.js debug attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "quicktype", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", + "runtimeArgs": ["--nolazy"], + "args": [ + "--project", + "src/cli/tsconfig.json", + "src/cli/index.ts", + "--lang", + "dart", + "--src-lang", + "json", + "./test/inputs/json/priority/blns-object.json" + ], + "cwd": "${workspaceRoot}", + "protocol": "inspector" + }, + { + "name": "test", + "type": "node", + "request": "launch", + "program": "${workspaceRoot}/node_modules/ts-node/dist/_bin.js", + "args": ["--project", "test/tsconfig.json", "test/test.ts"], + "cwd": "${workspaceRoot}", + "protocol": "inspector", + "env": { + "CPUs": "1", + "FIXTURE": "golang" + } + } + ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index ea68a90d3..b666505db 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,25 +1,39 @@ { - // Place your settings in this file to overwrite default and user settings. - "editor.formatOnSave": true, - "spellright.ignoreFiles": [ - "**/.gitignore", - "**/.spellignore" - ], - "search.exclude": { - "**/.git": true, - "**/node_modules": true, - "**/bower_components": true, - "**/tmp": true, - "output": true, - "**/obj": true, - "**/bin": true, - "test/inputs": true, - "test/runs": true, - "app/build": true, - "elm-stuff": true, - "dist": true - }, - "explorer.excludeGitIgnore": false, - "spellright.documentTypes": [], - "java.configuration.updateBuildConfiguration": "automatic" -} \ No newline at end of file + // Place your settings in this file to overwrite default and user settings. + "editor.formatOnSave": true, + "search.exclude": { + "**/.git": true, + "**/node_modules": true, + "**/bower_components": true, + "**/tmp": true, + "output": true, + "**/obj": true, + "**/bin": true, + "test/inputs": true, + "test/runs": true, + "app/build": true, + "elm-stuff": true, + "dist": true + }, + "explorer.excludeGitIgnore": false, + "java.configuration.updateBuildConfiguration": "automatic", + + "files.associations": { + "*.schema": "jsonc" + }, + + "[json]": { + "editor.defaultFormatter": "biomejs.biome", + "editor.wordWrap": "on", + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.detectIndentation": false + }, + "[jsonc]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.wordWrap": "on", + "editor.insertSpaces": true, + "editor.tabSize": 4, + "editor.detectIndentation": false + } +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index d41fa1af8..000000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - // See https://go.microsoft.com/fwlink/?LinkId=733558 - // for the documentation about the tasks.json format - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "tslint", - "group": "build", - "problemMatcher": [ - "$tslint5" - ] - } - ] -} \ No newline at end of file diff --git a/PACKAGES.md b/PACKAGES.md deleted file mode 100644 index 59ab3a0ef..000000000 --- a/PACKAGES.md +++ /dev/null @@ -1,36 +0,0 @@ -# The packages - -* `quicktype-core`: This is the engine of quicktype. It takes JSON, JSON Schema, and GraphQL input and produces output in a variety of programming languages. We're trying to keep this lean in terms of download size so that it can be embedded, such as in [quicktype-playground](https://github.com/quicktype/quicktype-playground). - -* `quicktype-typescript-input`: This is a bit of code that allows TypeScript code to be fed as input to `quicktype-core`, by transforming it to JSON Schema with [typescript-json-schema](https://github.com/YousefED/typescript-json-schema). It depends on `quicktype-core`. - -* `quicktype-graphql-input`: This is the GraphQL input module. It's split off into a separate package because it's not used in the web UI and `quicktype-playgrounds`, and it uses the moderately sized `graphql` dependency. - -* `quicktype`: This is the command line interface for quicktype. It's a monolithic package that doesn't depend on the other packages, but contains all their code directly. This is mainly for ease of development. Packages that want to use quicktype's CLI interface, such as [json-to-azure-node-schema](https://github.com/json-helpers/json-to-azure-node-schema) will have to use this package. - -# Module resolution - -`quicktype-typescript-input` and `quicktype-graphql-input` have to work both as their own packages, depending on the `quicktype-core` package, as well as part of `quicktype`, referring to the files in the local `src/quicktype-core` directory. - -In addition, since those two input packages depend on `quicktype-core`, we would have to first build `quicktype-core`, publish it, and then build the input packages, depending on the just published `quicktype-core`. This is bad for development, since we couldn't do modifications to all packages without publishing, if we want to test independent of the `quicktype` package. The same goes for CI. Therefore, the two have to build as packages depending on the local `build/quicktype-core` package, but have to be published depending on the proper `quicktype-core` NPM package. We solve this the following way: - -* All packages, including `quicktype-typescript-input` and `quicktype-graphql-input`, import files with local paths, such as `"../quicktype-core"`. This seems the only way to make VSCode's TypeScript integration, as well as `ts-node` happy. Unfortunately, since local paths can's use `tsc`'s path mapping, we have to rewrite those paths _before_ compiling, which is done in `build/quicktype-*-input/build.ts`: it copies all the sources, rewrites them, compiles, and then deletes the copied sources again. - -* Depending on whether we build the input packages, or publish them, their `package.json`s will have to refer to either the local `quicktype-core` package, or the NPM one. This is also done by the build script, which replaces the dependency with the right one for the job. - -## Issues - -Module resolution in Node is such that if a package is not found in the local `node_modules` directory, it goes up the directory hierarchy and tries every `node_modules` directory it finds. We have a `node_modules` in the root directory of our repo, so a subpackage build will fall back to that if it can't find a package locally. The main consequence of that seems to be that the build won't catch missing dependencies in those packages if they're present in the root package. Moving the root `package.json` to `build/quicktype` screws with lots of tooling. - -# Building - -The root `quicktype` package does everything from its `package.json`. - -The other packages each have a `build.js` in their `build/PACKAGE` directory. It is required to build the root package before building the others, because it will install the `semver` package which the build script for the other packages depend on. It's also required to build `quicktype-core` before building the ones that depend on it. This is how to build everything: - -```shell -npm install -( cd build/quicktype-core ; node build.js ) -( cd build/quicktype-typescript-input ; node build.js ) -( cd build/quicktype-graphql-input ; node build.js ) -``` diff --git a/README.md b/README.md index d58334102..9d9fcbbf9 100644 --- a/README.md +++ b/README.md @@ -43,15 +43,6 @@ For the best CLI, we recommend installing `quicktype` globally via `npm`: npm install -g quicktype ``` -Other options: - -- [Homebrew](http://formulae.brew.sh/formula/quicktype) _(infrequently updated)_ -- [Xcode extension](https://itunes.apple.com/us/app/paste-json-as-code-quicktype/id1330801220?mt=12)\* -- [VSCode extension](https://marketplace.visualstudio.com/items/quicktype.quicktype)\* -- [Visual Studio extension](https://marketplace.visualstudio.com/items?itemName=typeguard.quicktype-vs)\* - -\* limited functionality - ## Using `quicktype` ```bash @@ -195,6 +186,11 @@ main(); The argument to `quicktype` is a complex object with many optional properties. [Explore its definition](https://github.com/quicktype/quicktype/blob/master/packages/quicktype-core/src/Run.ts#L637) to understand what options are allowed. +### Adding Custom logic or Rendering: + +Quicktype supports creating your own custom languages and rendering output, you can extend existing classes or create your own to be using by the `quicktype function`.
+Check out [this guide](./doc/CustomRenderer.md) for more info. + ## Contributing `quicktype` is [Open Source](LICENSE) and we love contributors! In fact, we have a [list of issues](https://github.com/quicktype/quicktype/issues?utf8=βœ“&q=is%3Aissue+is%3Aopen+label%3Ahelp-wanted) that are low-priority for us, but for which we'd happily accept contributions. Support for new target languages is also strongly desired. If you'd like to contribute, need help with anything at all, or would just like to talk things over, come [join us on Slack](http://slack.quicktype.io/). diff --git a/biome.json b/biome.json new file mode 100644 index 000000000..a1af651fa --- /dev/null +++ b/biome.json @@ -0,0 +1,16 @@ +{ + "files": { + "ignore": [ + "test/runs", + "test/inputs", + "dist", + "node_modules", + "packages/*/dist", + "packages/*/node_modules" + ] + }, + "formatter": { + "indentStyle": "space", + "indentWidth": 4 + } +} diff --git a/doc/CustomRenderer.md b/doc/CustomRenderer.md new file mode 100644 index 000000000..42040e393 --- /dev/null +++ b/doc/CustomRenderer.md @@ -0,0 +1,145 @@ +# Extending quicktype functionality with a Custom Renderer + +## quicktype Interface + +To customise your rendering output, you can extend existing quicktype classes and override existing methods to achieve the behaviour you want. + +This process requires 3 main steps: + +1. [Extending a `Renderer` Class](#creating-a-custom-renderer) +2. [Wrapping your `Renderer` in a `TargetLanguage` Class](#creating-a-targetlanguage) +3. [Using your new classes in the `quicktype` function](#using-your-custom-language) +4. [Advanced Usage: Creating an entirely new Language](#creating-a-new-language) + +## Creating a custom `Renderer` + +Adding custom render logic for an existing language often involves extending a Renderer class and simply overriding or amending one of the `emit` methods: + +```ts +// MyCustomRenderer.ts +import { CSharpRenderer } from "quicktype-core"; + +export class MyCustomRenderer extends CSharpRenderer { + // Add your custom logic here, feel free to reference the source code for how existing methods work + // + // ex. + protected superclassForType(t: Type): Sourcelike | undefined { + // if the type is a class, it should extend `GameObject` when rendered in C# + if (t instanceof ClassType) { + return "GameObject"; + } + return undefined; + } + // See: http://blog.quicktype.io/customizing-quicktype/ for more context +} +``` + +## Creating a `TargetLanguage` + +If you just want to change the rendering logic for an existing language, you can just extend an exported Language class (`CSharpTargetLanguage` in this example) and override the `makeRenderer` method: + +```ts +// MyCustomLanguage.ts +import { CSharpTargetLanguage } from "quicktype-core"; + +import { MyCustomRenderer } from "./MyCustomRenderer"; + +export class MyCustomLanguage extends CSharpTargetLanguage { + // `makeRenderer` instantiates the Renderer class for the TargetLanguage + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: Record + ): MyCustomRenderer { + // use your new custom renderer class here + return new MyCustomRenderer(this, renderContext, getOptionValues(cSharpOptions, untypedOptionValues)); + } +} +``` + +## Using your custom Language + +```ts +import { quicktype } from "quicktype-core"; + +import { MyCustomLanguage } from './MyCustomLanguage'; + +const lang = new MyCustomLanguage(); + +const lines = await quicktype({ + lang: lang, // use your new TargetLanguage in the `lang` field here + ... +}); + +console.log(lines); +``` + +## Creating a new Language + +If none of the existing `quicktype` Language classes suit your needs, you can creating your own `TargetLanguge` and `Renderer` classes from scratch. If this satisfies your use cases for a language we don't currently support, please consider opening a PR with your new language and we'd love to take a look. + +If you run into any issues, you can open a GitHub issue and we'll help you take a look. + +### Creating a `TargetLanguage` from scratch + +Instead of just extending an existing language, a new Language requires two additional steps: + +- Defining the language config +- Adding any language-specific options + +```ts +import { TargetLanguage, BooleanOption } from "quicktype-core"; + +// language config +const brandNewLanguageConfig = { + displayName: "Scratch", // these can be the same + names: ["scratch"], // these can be the same + extension: "sb" // the file extension that this language commonly has +} as const; + +// language options +const brandNewLanguageOptions = { + allowFoo: new BooleanOption( + "allow-foo", // option name + "Allows Foo", // description + true // default value + ) + // The default available Option classes are: StringOption, BooleanOption, EnumOption + // Please visit the source code for more examples and usage +}; + +class BrandNewLanguage extends TargetLanguage { + public constructor() { + super(brandNewLanguageConfig); + } + + public getOptions(): typeof brandNewLanguageOptions { + return brandNewLanguageOptions; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: Record + ): BrandNewRenderer { + return new BrandNewRenderer(this, renderContext, getOptionValues(brandNewLanguageOptions, untypedOptionValues)); + } +} +``` + +### Creating a `Renderer` from scratch + +Creating a brand new `Renderer` class is very similar to extending an existing class: + +```ts +export class BrandNewRenderer extends ConvenienceRenderer { + public constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { + super(targetLanguage, renderContext); + } + + // Additional render methods go here + // Please reference existing Renderer classes and open a GitHub issue if you need help +} +``` + +## Links + +Blog post with an older example: http://blog.quicktype.io/customizing-quicktype/ diff --git a/package-lock.json b/package-lock.json index ad7704b81..06837b485 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,20 +1,21 @@ { "name": "quicktype", - "version": "23.0.0", - "lockfileVersion": 2, + "version": "23.2.0", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "quicktype", - "version": "23.0.0", + "version": "23.2.0", "license": "Apache-2.0", "workspaces": [ "./packages/quicktype-core", "./packages/quicktype-graphql-input", - "./packages/quicktype-typescript-input" + "./packages/quicktype-typescript-input", + "./packages/quicktype-vscode" ], "dependencies": { - "@glideapps/ts-necessities": "^2.1.3", + "@glideapps/ts-necessities": "^2.2.3", "chalk": "^4.1.2", "collection-utils": "^1.0.1", "command-line-args": "^5.2.1", @@ -22,37 +23,40 @@ "cross-fetch": "^4.0.0", "graphql": "^0.11.7", "lodash": "^4.17.21", - "moment": "^2.29.4", + "moment": "^2.30.1", "quicktype-core": "20.0.12", "quicktype-graphql-input": "20.0.2", "quicktype-typescript-input": "20.0.2", - "readable-stream": "^4.4.2", + "readable-stream": "^4.5.2", "stream-json": "1.8.0", "string-to-stream": "^3.0.1", - "typescript": "4.9.5" + "typescript": "~5.8.3" }, "bin": { "quicktype": "dist/index.js" }, "devDependencies": { + "@biomejs/biome": "^1.9.4", "@tsconfig/node18": "^1.0.1", "@types/command-line-args": "^5.2.0", - "@types/command-line-usage": "^5.0.2", + "@types/command-line-usage": "^5.0.4", "@types/graphql": "^0.11.7", - "@types/lodash": "^4.14.197", + "@types/lodash": "^4.17.0", "@types/semver": "^7.5.0", - "@types/shelljs": "^0.8.12", + "@types/shelljs": "^0.8.15", "@types/stream-json": "^1.7.3", - "@types/urijs": "^1.19.19", + "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", "ajv": "^5.5.2", - "deep-equal": "^2.2.2", + "deep-equal": "^2.2.3", + "esbuild": "^0.20.2", "exit": "^0.1.2", - "prettier": "^3.0.1", "promise-timeout": "^1.3.0", "semver": "^7.5.4", "shelljs": "^0.8.5", - "ts-node": "^10.9.1", - "tslint": "^6.1.3", + "ts-node": "^10.9.2", "watch": "^1.0.2" }, "engines": { @@ -61,8 +65,7 @@ }, "node_modules/@75lb/deep-merge": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.1.tgz", - "integrity": "sha512-xvgv6pkMGBA6GwdyJbNAnDmfAIR/DfWhrj9jgWh3TY7gRm3KO46x/GPjRg6wJ0nOepwqrNxFfojebh0Df4h4Tw==", + "license": "MIT", "dependencies": { "lodash.assignwith": "^4.2.0", "typical": "^7.1.1" @@ -73,16 +76,191 @@ }, "node_modules/@75lb/deep-merge/node_modules/typical": { "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "license": "MIT", "engines": { "node": ">=12.17" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@biomejs/biome": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-1.9.4.tgz", + "integrity": "sha512-1rkd7G70+o9KkTn5KLmDYXihGoTaIGO9PIIN2ZB7UJxFrWw04CZHPYiMRjYsaDvVV7hP1dYNRLxSANLaBFGpog==", + "dev": true, + "hasInstallScript": true, + "license": "MIT OR Apache-2.0", + "bin": { + "biome": "bin/biome" + }, + "engines": { + "node": ">=14.21.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/biome" + }, + "optionalDependencies": { + "@biomejs/cli-darwin-arm64": "1.9.4", + "@biomejs/cli-darwin-x64": "1.9.4", + "@biomejs/cli-linux-arm64": "1.9.4", + "@biomejs/cli-linux-arm64-musl": "1.9.4", + "@biomejs/cli-linux-x64": "1.9.4", + "@biomejs/cli-linux-x64-musl": "1.9.4", + "@biomejs/cli-win32-arm64": "1.9.4", + "@biomejs/cli-win32-x64": "1.9.4" + } + }, + "node_modules/@biomejs/cli-darwin-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-1.9.4.tgz", + "integrity": "sha512-bFBsPWrNvkdKrNCYeAp+xo2HecOGPAy9WyNyB/jKnnedgzl4W4Hb9ZMzYNbf8dMCGmUdSavlYHiR01QaYR58cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-darwin-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-1.9.4.tgz", + "integrity": "sha512-ngYBh/+bEedqkSevPVhLP4QfVPCpb+4BBe2p7Xs32dBgs7rh9nY2AIYUL6BgLw1JVXV8GlpKmb/hNiuIxfPfZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-1.9.4.tgz", + "integrity": "sha512-fJIW0+LYujdjUgJJuwesP4EjIBl/N/TcOX3IvIHJQNsAqvV2CHIogsmA94BPG6jZATS4Hi+xv4SkBBQSt1N4/g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-arm64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-1.9.4.tgz", + "integrity": "sha512-v665Ct9WCRjGa8+kTr0CzApU0+XXtRgwmzIf1SeKSGAv+2scAlW6JR5PMFo6FzqqZ64Po79cKODKf3/AAmECqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-1.9.4.tgz", + "integrity": "sha512-lRCJv/Vi3Vlwmbd6K+oQ0KhLHMAysN8lXoCI7XeHlxaajk06u7G+UsFSO01NAs5iYuWKmVZjmiOzJ0OJmGsMwg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-linux-x64-musl": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-1.9.4.tgz", + "integrity": "sha512-gEhi/jSBhZ2m6wjV530Yy8+fNqG8PAinM3oV7CyO+6c3CEh16Eizm21uHVsyVBEB6RIM8JHIl6AGYCv6Q6Q9Tg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-arm64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-1.9.4.tgz", + "integrity": "sha512-tlbhLk+WXZmgwoIKwHIHEBZUwxml7bRJgk0X2sPyNR3S93cdRq6XulAZRQJ17FYGGzWne0fgrXBKpl7l4M87Hg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, + "node_modules/@biomejs/cli-win32-x64": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-1.9.4.tgz", + "integrity": "sha512-8Y5wMhVIPaWe6jw2H+KlEm4wP/f7EW3810ZLmDlrEEy5KvBsb9ECEfu/kMWD484ijfQ8+nIi0giMgu9g1UAuuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=14.21.3" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -90,28 +268,259 @@ "node": ">=12" } }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@glideapps/ts-necessities": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.3.tgz", - "integrity": "sha512-q9U8v/n9qbkd2zDYjuX3qtlbl+OIyI9zF+zQhZjfYOE9VMDH7tfcUSJ9p0lXoY3lxmGFne09yi4iiNeQUwV7AA==" + "version": "2.2.3", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -119,8 +528,7 @@ }, "node_modules/@mark.probst/typescript-json-schema": { "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", - "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", + "license": "BSD-3-Clause", "dependencies": { "@types/json-schema": "^7.0.9", "@types/node": "^16.9.2", @@ -137,13 +545,11 @@ }, "node_modules/@mark.probst/typescript-json-schema/node_modules/@types/node": { "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" + "license": "MIT" }, "node_modules/@mark.probst/typescript-json-schema/node_modules/typescript": { "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -152,55 +558,95 @@ "node": ">=4.2.0" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "license": "MIT" }, "node_modules/@tsconfig/node16": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + "license": "MIT" }, "node_modules/@tsconfig/node18": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.1.tgz", - "integrity": "sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/browser-or-node": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/browser-or-node/-/browser-or-node-1.3.0.tgz", - "integrity": "sha512-MVetr65IR7RdJbUxVHsaPFaXAO8fi89zv1g8L/mHygh1Q7xnnK02XZLwfMh57FOpTO6gtnagoPMQ/UOFfctXRQ==", - "dev": true + "version": "1.3.2", + "dev": true, + "license": "MIT" }, "node_modules/@types/command-line-args": { "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", - "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/command-line-usage": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.2.tgz", - "integrity": "sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==", - "dev": true + "version": "5.0.4", + "dev": true, + "license": "MIT" }, "node_modules/@types/glob": { "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" @@ -208,75 +654,85 @@ }, "node_modules/@types/graphql": { "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.11.8.tgz", - "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/is-url": { + "version": "1.2.32", + "resolved": "https://registry.npmjs.org/@types/is-url/-/is-url-1.2.32.tgz", + "integrity": "sha512-46VLdbWI8Sc+hPexQ6NLNR2YpoDyDZIpASHkJQ2Yr+Kf9Giw6LdCTkwOdsnHKPQeh7xTjTmSnxbE8qpxYuCiHA==", "dev": true }, - "node_modules/@types/js-base64": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", - "integrity": "sha512-Zw33oQNAvDdAN9b0IE5stH0y2MylYvtU7VVTKEJPxhyM2q57CVaNJhtJW258ah24NRtaiA23tptUmVn3dmTKpw==", - "deprecated": "This is a stub types definition. js-base64 provides its own type definitions, so you do not need this installed.", + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", "dev": true, - "dependencies": { - "js-base64": "*" - } + "license": "MIT" }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" + "version": "7.0.15", + "license": "MIT" }, "node_modules/@types/lodash": { - "version": "4.14.197", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", - "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "node_modules/@types/minimatch": { "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@types/mocha": { + "version": "10.0.6", + "dev": true, + "license": "MIT" }, "node_modules/@types/node": { - "version": "18.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", - "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/node-persist": { + "version": "3.1.8", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } }, "node_modules/@types/pako": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.0.tgz", - "integrity": "sha1-6q6DZNG391LiY7w/1o3+yY5hNsU=", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/pluralize": { "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.30.tgz", - "integrity": "sha512-kVww6xZrW/db5BR9OqiT71J9huRdQ+z/r+LbDuT7/EK50mCmj5FoaIARnVv0rvjUS/YpDox0cDU9lpQT011VBA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", + "version": "4.0.10", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "safe-buffer": "~5.1.1" } }, "node_modules/@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true + "version": "7.5.8", + "dev": true, + "license": "MIT" }, "node_modules/@types/shelljs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.12.tgz", - "integrity": "sha512-ZA8U81/gldY+rR5zl/7HSHrG2KDfEb3lzG6uCUDhW1DTQE9yC/VBQ45fXnXq8f3CgInfhZmjtdu/WOUlrXRQUg==", + "version": "0.8.15", "dev": true, + "license": "MIT", "dependencies": { "@types/glob": "~7.2.0", "@types/node": "*" @@ -284,18 +740,16 @@ }, "node_modules/@types/stream-chain": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz", - "integrity": "sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/stream-json": { "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.3.tgz", - "integrity": "sha512-Jqsyq5VPOTWorvEmzWhEWH5tJnHA+bB8vt/Zzb11vSDj8esfSHDMj2rbVjP0mfJQzl3YBJSXBBq08iiyaBK3KA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*", "@types/stream-chain": "*" @@ -303,443 +757,520 @@ }, "node_modules/@types/unicode-properties": { "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/unicode-properties/-/unicode-properties-1.3.0.tgz", - "integrity": "sha512-kDVlxpdkCfgvzfXcglkr7j4OSMjCEEo/Jloj4tFuldYZpQ9Uypy7FGXPhNstoj4eGvhddwuu5n0EfI+XdWVoVA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/urijs": { - "version": "1.19.19", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.19.tgz", - "integrity": "sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg==" + "version": "1.19.25", + "license": "MIT" + }, + "node_modules/@types/vscode": { + "version": "1.88.0", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/wordwrap": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/wordwrap/-/wordwrap-1.0.3.tgz", + "integrity": "sha512-jx39cOYWJxZxVOZeNHvLVoDLRUFcYtIJaurC6C0qzCovIB3GPDbMDbYvoWi9D1B2PtIE16rElQOFR4Y+8QbUgw==", + "dev": true }, - "node_modules/@types/yaml": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", - "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", - "deprecated": "This is a stub types definition. yaml provides its own type definitions, so you do not need this installed.", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "dependencies": { - "yaml": "*" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "dev": true, "dependencies": { - "event-target-shim": "^5.0.0" + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" }, "engines": { - "node": ">=6.5" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" + }, "engines": { - "node": ">=0.4.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "dependencies": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "dev": true, "engines": { - "node": ">=8" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": ">=4" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, "dependencies": { - "sprintf-js": "~1.0.2" + "balanced-match": "^1.0.0" } }, - "node_modules/array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=6" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, + "dependencies": { + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" + }, "engines": { - "node": ">= 0.4" + "node": "^16.0.0 || >=18.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "dev": true, + "license": "ISC" }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "node_modules/@vscode/test-cli": { + "version": "0.0.6", + "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@types/mocha": "^10.0.2", + "c8": "^9.1.0", + "chokidar": "^3.5.3", + "enhanced-resolve": "^5.15.0", + "glob": "^10.3.10", + "minimatch": "^9.0.3", + "mocha": "^10.2.0", + "supports-color": "^9.4.0", + "yargs": "^17.7.2" + }, + "bin": { + "vscode-test": "out/bin.mjs" } }, - "node_modules/browser-or-node": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", - "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" - }, - "node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "node_modules/@vscode/test-cli/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "balanced-match": "^1.0.0" } }, - "node_modules/builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "node_modules/@vscode/test-cli/node_modules/glob": { + "version": "10.3.12", "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.6", + "minimatch": "^9.0.1", + "minipass": "^7.0.4", + "path-scurry": "^1.10.2" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, "engines": { - "node": ">=0.10.0" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/@vscode/test-cli/node_modules/minimatch": { + "version": "9.0.4", "dev": true, + "license": "ISC", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "node_modules/@vscode/test-cli/node_modules/supports-color": { + "version": "9.4.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", + "node_modules/@vscode/test-cli/node_modules/yargs": { + "version": "17.7.2", + "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^4.1.2" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { "node": ">=12" + } + }, + "node_modules/@vscode/test-electron": { + "version": "2.3.9", + "dev": true, + "license": "MIT", + "dependencies": { + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "jszip": "^3.10.1", + "semver": "^7.5.2" }, - "funding": { - "url": "https://github.com/chalk/chalk-template?sponsor=1" + "engines": { + "node": ">=16" } }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@vscode/vsce": { + "version": "2.25.0", + "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "azure-devops-node-api": "^12.5.0", + "chalk": "^2.4.2", + "cheerio": "^1.0.0-rc.9", + "cockatiel": "^3.1.2", + "commander": "^6.2.1", + "form-data": "^4.0.0", + "glob": "^7.0.6", + "hosted-git-info": "^4.0.2", + "jsonc-parser": "^3.2.0", + "leven": "^3.1.0", + "markdown-it": "^12.3.2", + "mime": "^1.3.4", + "minimatch": "^3.0.3", + "parse-semver": "^1.1.1", + "read": "^1.0.7", + "semver": "^7.5.2", + "tmp": "^0.2.1", + "typed-rest-client": "^1.8.4", + "url-join": "^4.0.1", + "xml2js": "^0.5.0", + "yauzl": "^2.3.1", + "yazl": "^2.2.2" + }, + "bin": { + "vsce": "vsce" }, "engines": { - "node": ">=8" + "node": ">= 16" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "optionalDependencies": { + "keytar": "^7.7.0" } }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/@vscode/vsce/node_modules/chalk": { + "version": "2.4.2", + "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=4" } }, - "node_modules/chalk/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "node_modules/@vscode/vsce/node_modules/commander": { + "version": "6.2.1", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 6" } }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/abort-controller": { + "version": "3.0.0", + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "event-target-shim": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=6.5" } }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" + "node_modules/acorn": { + "version": "8.11.3", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=12" + "node": ">=0.4.0" } }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "node_modules/acorn-jsx": { + "version": "5.3.2", "dev": true, - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/collection-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", - "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==" + "node_modules/acorn-walk": { + "version": "8.2.0", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } }, - "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/agent-base": { + "version": "6.0.2", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/color-convert/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dependencies": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" + "debug": "4" }, "engines": { - "node": ">=4.0.0" + "node": ">= 6.0.0" } }, - "node_modules/command-line-usage": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.1.tgz", - "integrity": "sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==", + "node_modules/ajv": { + "version": "5.5.2", + "dev": true, + "license": "MIT", "dependencies": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^3.0.0", - "typical": "^7.1.1" - }, - "engines": { - "node": ">=12.20.0" + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" } }, - "node_modules/command-line-usage/node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "node_modules/ansi-colors": { + "version": "4.1.1", + "dev": true, + "license": "MIT", "engines": { - "node": ">=12.17" + "node": ">=6" } }, - "node_modules/command-line-usage/node_modules/typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", "engines": { - "node": ">=12.17" + "node": ">=8" } }, - "node_modules/commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" - }, - "node_modules/cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", + "node_modules/ansi-styles": { + "version": "3.2.1", + "dev": true, + "license": "MIT", "dependencies": { - "node-fetch": "^2.6.12" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, - "node_modules/deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "node_modules/anymatch": { + "version": "3.1.3", "dev": true, + "license": "ISC", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 8" } }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "node_modules/arg": { + "version": "4.1.3", + "license": "MIT" }, - "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/array-back": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, "dependencies": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -748,771 +1279,717 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, "engines": { - "node": ">=0.3.1" + "node": ">=8" } }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "dependencies": { - "iconv-lite": "^0.6.2" - } + "node_modules/asynckit": { + "version": "0.4.0", + "dev": true, + "license": "MIT" }, - "node_modules/es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/available-typed-arrays": { + "version": "1.0.7", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "node_modules/azure-devops-node-api": { + "version": "12.5.0", "dev": true, - "engines": { - "node": ">=0.8.0" + "license": "MIT", + "dependencies": { + "tunnel": "0.0.6", + "typed-rest-client": "^1.8.4" } }, - "node_modules/esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/balanced-match": { + "version": "1.0.0", + "license": "MIT" }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", + "node_modules/base64-js": { + "version": "1.5.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" + "node_modules/bl": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/exec-sh": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", - "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", + "node_modules/bl/node_modules/buffer": { + "version": "5.7.1", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, "dependencies": { - "merge": "^1.1.3" + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">= 0.8.0" + "node": ">= 6" } }, - "node_modules/fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "node_modules/boolbase": { + "version": "1.0.0", + "dev": true, + "license": "ISC" }, - "node_modules/fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "node_modules/brace-expansion": { + "version": "1.1.11", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } }, - "node_modules/find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", + "node_modules/braces": { + "version": "3.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "array-back": "^3.0.1" + "fill-range": "^7.0.1" }, "engines": { - "node": ">=4.0.0" + "node": ">=8" } }, - "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/brfs": { + "version": "1.6.1", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "quote-stream": "^1.0.1", + "resolve": "^1.1.5", + "static-module": "^2.2.0", + "through2": "^2.0.0" + }, + "bin": { + "brfs": "bin/cmd.js" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "node_modules/browser-or-node": { + "version": "3.0.0", + "license": "MIT" }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "node_modules/browser-stdout": { + "version": "1.3.1", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "ISC" }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", - "dev": true, + "node_modules/buffer": { + "version": "6.0.3", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "dev": true, + "license": "MIT", "engines": { "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/buffer-equal": { + "version": "0.0.1", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "engines": { + "node": ">=0.4.0" } }, - "node_modules/graphql": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", - "integrity": "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==", + "node_modules/buffer-from": { + "version": "1.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/c8": { + "version": "9.1.0", + "dev": true, + "license": "ISC", "dependencies": { - "iterall": "1.1.3" + "@bcoe/v8-coverage": "^0.2.3", + "@istanbuljs/schema": "^0.1.3", + "find-up": "^5.0.0", + "foreground-child": "^3.1.1", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-reports": "^3.1.6", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.0.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1" + }, + "bin": { + "c8": "bin/c8.js" + }, + "engines": { + "node": ">=14.14.0" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/c8/node_modules/yargs": { + "version": "17.7.2", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1" + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">= 0.4.0" + "node": ">=12" } }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "node_modules/call-bind": { + "version": "1.0.7", "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "node_modules/callsites": { + "version": "3.1.0", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=6" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/camelcase": { + "version": "6.3.0", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.1" + "license": "MIT", + "engines": { + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, + "node_modules/chalk-template": { + "version": "0.4.0", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, - "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", - "dev": true, + "node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "node_modules/chalk/node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "color-name": "~1.1.4" }, "engines": { - "node": ">=0.10.0" + "node": ">=7.0.0" } }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" } }, - "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" - }, - "node_modules/internal-slot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", - "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", - "dev": true, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "has-flag": "^4.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=8" } }, - "node_modules/interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "node_modules/is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/cheerio": { + "version": "1.0.0-rc.12", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "htmlparser2": "^8.0.1", + "parse5": "^7.0.0", + "parse5-htmlparser2-tree-adapter": "^7.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/cheerio-select": { + "version": "2.1.0", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/chokidar": { + "version": "3.6.0", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/chownr": { + "version": "1.1.4", "dev": true, + "license": "ISC", + "optional": true + }, + "node_modules/cliui": { + "version": "8.0.1", + "license": "ISC", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "node_modules/co": { + "version": "4.6.0", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" } }, - "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/cockatiel": { + "version": "3.1.2", "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=16" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "engines": { - "node": ">=8" - } + "node_modules/collection-utils": { + "version": "1.0.1", + "license": "Apache-2.0" }, - "node_modules/is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "node_modules/color-convert": { + "version": "1.9.3", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" } }, - "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/color-convert/node_modules/color-name": { + "version": "1.1.3", "dev": true, - "dependencies": { - "has-tostringtag": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/is-regex": { + "node_modules/color-name": { "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "delayed-stream": "~1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", - "dev": true, + "node_modules/command-line-args": { + "version": "5.2.1", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "array-back": "^3.1.0", + "find-replace": "^3.0.0", + "lodash.camelcase": "^4.3.0", + "typical": "^4.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", - "dev": true, + "node_modules/command-line-usage": { + "version": "7.0.1", + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "array-back": "^6.2.2", + "chalk-template": "^0.4.0", + "table-layout": "^3.0.0", + "typical": "^7.1.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12.20.0" } }, - "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.2" - }, + "node_modules/command-line-usage/node_modules/array-back": { + "version": "6.2.2", + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12.17" } }, - "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - }, + "node_modules/command-line-usage/node_modules/typical": { + "version": "7.1.1", + "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12.17" } }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" }, - "node_modules/is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "node_modules/concat-stream": { + "version": "1.6.2", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" } }, - "node_modules/is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "node_modules/concat-stream/node_modules/readable-stream": { + "version": "2.3.8", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "node_modules/convert-source-map": { + "version": "2.0.0", + "dev": true, + "license": "MIT" }, - "node_modules/iterall": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", - "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==" + "node_modules/core-util-is": { + "version": "1.0.3", + "license": "MIT" }, - "node_modules/js-base64": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", - "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" + "node_modules/create-require": { + "version": "1.1.1", + "license": "MIT" }, - "node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, + "node_modules/cross-fetch": { + "version": "4.0.0", + "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" + "node-fetch": "^2.6.12" } }, - "node_modules/js-yaml/node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "node_modules/cross-spawn": { + "version": "7.0.3", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">= 8" } }, - "node_modules/json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.assignwith": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==" - }, - "node_modules/lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/css-select": { + "version": "5.1.0", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "yallist": "^4.0.0" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" - }, - "node_modules/merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true + "node_modules/css-what": { + "version": "6.1.0", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/debug": { + "version": "4.3.4", + "dev": true, + "license": "MIT", "dependencies": { - "brace-expansion": "^1.1.7" + "ms": "2.1.2" }, "engines": { - "node": "*" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", + "node_modules/decamelize": { + "version": "4.0.0", "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/decompress-response": { + "version": "6.0.0", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "minimist": "^1.2.6" + "mimic-response": "^3.1.0" }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", "engines": { - "node": "*" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "node_modules/deep-equal": { + "version": "2.2.3", + "dev": true, + "license": "MIT", "dependencies": { - "whatwg-url": "^5.0.0" + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", + "is-arguments": "^1.1.1", + "is-array-buffer": "^3.0.2", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "isarray": "^2.0.5", + "object-is": "^1.1.5", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "side-channel": "^1.0.4", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.13" }, "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "node_modules/deep-equal/node_modules/isarray": { + "version": "2.0.5", "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "license": "MIT" + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=4.0.0" } }, - "node_modules/object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "node_modules/deep-is": { + "version": "0.1.4", "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -1521,24 +1998,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "node_modules/define-properties": { + "version": "1.2.1", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, "engines": { @@ -1548,2818 +2014,4289 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" + "node_modules/delayed-stream": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" } }, - "node_modules/pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" - }, - "node_modules/path-equal": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", - "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "node_modules/detect-libc": { + "version": "2.0.3", + "dev": true, + "license": "Apache-2.0", + "optional": true, "engines": { - "node": ">=0.10.0" + "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "node_modules/diff": { + "version": "4.0.2", + "license": "BSD-3-Clause", "engines": { - "node": ">=4" + "node": ">=0.3.1" } }, - "node_modules/prettier": { + "node_modules/dir-glob": { "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, - "bin": { - "prettier": "bin/prettier.cjs" + "dependencies": { + "path-type": "^4.0.0" }, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" + "node": ">=8" } }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "node_modules/doctrine": { + "version": "3.0.0", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, "engines": { - "node": ">= 0.6.0" + "node": ">=6.0.0" } }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/promise-timeout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", - "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", - "dev": true - }, - "node_modules/quicktype-core": { - "resolved": "packages/quicktype-core", - "link": true - }, - "node_modules/quicktype-graphql-input": { - "resolved": "packages/quicktype-graphql-input", - "link": true - }, - "node_modules/quicktype-typescript-input": { - "resolved": "packages/quicktype-typescript-input", - "link": true - }, - "node_modules/readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "node_modules/dom-serializer": { + "version": "2.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/readable-stream/node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "node_modules/domelementtype": { + "version": "2.3.0", + "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "url": "https://github.com/sponsors/fb55" } - ] - }, - "node_modules/readable-stream/node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } + ], + "license": "BSD-2-Clause" }, - "node_modules/rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "node_modules/domhandler": { + "version": "5.0.3", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "resolve": "^1.1.6" + "domelementtype": "^2.3.0" }, "engines": { - "node": ">= 0.10" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "node_modules/domutils": { + "version": "3.1.0", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" - }, - "engines": { - "node": ">= 0.4" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "engines": { - "node": ">=0.10.0" + "node_modules/duplexer2": { + "version": "0.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" } }, - "node_modules/resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "node_modules/duplexer2/node_modules/readable-stream": { + "version": "2.3.8", "dev": true, + "license": "MIT", "dependencies": { - "path-parse": "^1.0.5" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "node_modules/eastasianwidth": { + "version": "0.2.0", + "dev": true, + "license": "MIT" }, - "node_modules/safe-stable-stringify": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", - "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==", - "engines": { - "node": ">=10" - } + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "node_modules/encoding": { + "version": "0.1.13", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.2" + } }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/end-of-stream": { + "version": "1.4.4", "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "once": "^1.4.0" } }, - "node_modules/shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", + "node_modules/enhanced-resolve": { + "version": "5.16.0", "dev": true, + "license": "MIT", "dependencies": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - }, - "bin": { - "shjs": "bin/shjs" + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" }, "engines": { - "node": ">=4" + "node": ">=10.13.0" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/entities": { + "version": "4.5.0", "dev": true, - "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "node_modules/stop-iteration-iterator": { + "node_modules/es-define-property": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", "dev": true, + "license": "MIT", "dependencies": { - "internal-slot": "^1.0.4" + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" } }, - "node_modules/stream-chain": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", - "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==" + "node_modules/es-errors": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "node_modules/stream-json": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz", - "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==", + "node_modules/es-get-iterator": { + "version": "1.1.3", + "dev": true, + "license": "MIT", "dependencies": { - "stream-chain": "^2.2.5" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/stream-read-all": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/stream-read-all/-/stream-read-all-3.0.1.tgz", - "integrity": "sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A==", + "node_modules/es-get-iterator/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/esbuild": { + "version": "0.20.2", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, "engines": { - "node": ">=10" + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" + "node_modules/escalade": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" } }, - "node_modules/string-to-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz", - "integrity": "sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==", - "dependencies": { - "readable-stream": "^3.4.0" + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" } }, - "node_modules/string-to-stream/node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "node_modules/escodegen": { + "version": "1.9.1", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" }, "engines": { - "node": ">= 6" + "node": ">=4.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" } }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, + "node_modules/escodegen/node_modules/estraverse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "node_modules/escodegen/node_modules/levn": { + "version": "0.3.0", + "dev": true, + "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" }, "engines": { - "node": ">=8" + "node": ">= 0.8.0" } }, - "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/escodegen/node_modules/optionator": { + "version": "0.8.3", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" }, "engines": { - "node": ">=4" + "node": ">= 0.8.0" } }, - "node_modules/table-layout": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-3.0.2.tgz", - "integrity": "sha512-rpyNZYRw+/C+dYkcQ3Pr+rLxW4CfHpXjPDnG7lYhdRoUcZTUt+KEsX+94RGp/aVp/MQU35JCITv2T/beY4m+hw==", - "dependencies": { - "@75lb/deep-merge": "^1.1.1", - "array-back": "^6.2.2", - "command-line-args": "^5.2.1", - "command-line-usage": "^7.0.0", - "stream-read-all": "^3.0.1", - "typical": "^7.1.1", - "wordwrapjs": "^5.1.0" - }, - "bin": { - "table-layout": "bin/cli.js" - }, - "engines": { - "node": ">=12.17" - } - }, - "node_modules/table-layout/node_modules/array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==", + "node_modules/escodegen/node_modules/prelude-ls": { + "version": "1.1.2", + "dev": true, "engines": { - "node": ">=12.17" + "node": ">= 0.8.0" } }, - "node_modules/table-layout/node_modules/typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==", + "node_modules/escodegen/node_modules/type-check": { + "version": "0.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "~1.1.2" + }, "engines": { - "node": ">=12.17" + "node": ">= 0.8.0" } }, - "node_modules/tiny-inflate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", - "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", + "node_modules/eslint": { + "version": "8.57.0", + "dev": true, + "license": "MIT", "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" }, "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" + "eslint": "bin/eslint.js" }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/ts-node/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "bin": { - "acorn": "bin/acorn" + "node_modules/eslint-scope": { + "version": "7.2.2", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=0.4.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, - "node_modules/tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", - "deprecated": "TSLint has been deprecated in favor of ESLint. Please see https://github.com/palantir/tslint/issues/4534 for more information.", + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "bin": { - "tslint": "bin/tslint" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", "engines": { - "node": ">=4.8.0" + "node": ">=10" }, - "peerDependencies": { - "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/tslint/node_modules/@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "node_modules/eslint/node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", "dev": true, + "license": "ISC", "dependencies": { - "@babel/highlight": "^7.0.0" + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" } }, - "node_modules/tslint/node_modules/@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.0", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "node_modules/tslint/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/espree": { + "version": "9.6.1", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">=4" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/tslint/node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/tslint/node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "node_modules/esprima": { + "version": "3.1.3", "dev": true, + "license": "BSD-2-Clause", "bin": { - "semver": "bin/semver" + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" } }, - "node_modules/tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/esquery": { + "version": "1.5.0", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "tslib": "^1.8.1" + "estraverse": "^5.1.0" }, - "peerDependencies": { - "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" + "engines": { + "node": ">=0.10" } }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" + "node_modules/esrecurse": { + "version": "4.3.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" }, "engines": { - "node": ">=4.2.0" + "node": ">=4.0" } }, - "node_modules/typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", + "node_modules/estraverse": { + "version": "5.3.0", + "dev": true, + "license": "BSD-2-Clause", "engines": { - "node": ">=8" + "node": ">=4.0" } }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" + "node_modules/esutils": { + "version": "2.0.2", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, - "node_modules/unicode-properties/node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + "node_modules/event-target-shim": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/unicode-properties/node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" + "node_modules/events": { + "version": "3.3.0", + "license": "MIT", + "engines": { + "node": ">=0.8.x" } }, - "node_modules/urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" + "node_modules/exec-sh": { + "version": "0.2.1", + "dev": true, + "license": "MIT", + "dependencies": { + "merge": "^1.1.3" + } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "node_modules/exit": { + "version": "0.1.2", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "node_modules/expand-template": { + "version": "2.0.3", + "dev": true, + "license": "(MIT OR WTFPL)", + "optional": true, + "engines": { + "node": ">=6" + } }, - "node_modules/watch": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", + "node_modules/falafel": { + "version": "2.2.5", "dev": true, + "license": "MIT", "dependencies": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" + "acorn": "^7.1.1", + "isarray": "^2.0.1" }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/falafel/node_modules/acorn": { + "version": "7.4.1", + "dev": true, + "license": "MIT", "bin": { - "watch": "cli.js" + "acorn": "bin/acorn" }, "engines": { - "node": ">=0.1.95" + "node": ">=0.4.0" } }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "node_modules/falafel/node_modules/isarray": { + "version": "2.0.5", + "dev": true, + "license": "MIT" }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + "node_modules/fast-deep-equal": { + "version": "1.1.0", + "dev": true, + "license": "MIT" }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" } }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "node_modules/fast-json-stable-stringify": { + "version": "2.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", "dev": true, + "license": "ISC", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "reusify": "^1.0.4" } }, - "node_modules/which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "node_modules/fd-slicer": { + "version": "1.1.0", "dev": true, + "license": "MIT", "dependencies": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "pend": "~1.2.0" } }, - "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/file-entry-cache": { + "version": "6.0.1", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "flat-cache": "^3.0.4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" - }, - "node_modules/wordwrapjs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", - "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==", + "node_modules/fill-range": { + "version": "7.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": ">=12.17" + "node": ">=8" } }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "node_modules/find-replace": { + "version": "3.0.0", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "array-back": "^3.0.1" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": ">=4.0.0" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/find-up": { + "version": "5.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/flat": { + "version": "5.0.2", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "dev": true, + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=7.0.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "node_modules/flatted": { + "version": "3.3.1", + "dev": true, + "license": "ISC" }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "engines": { - "node": ">=10" + "node_modules/for-each": { + "version": "0.3.3", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "node_modules/foreground-child": { + "version": "3.1.1", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, "engines": { - "node": ">= 14" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", + "node_modules/form-data": { + "version": "4.0.0", + "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=12" + "node": ">= 6" } }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "engines": { - "node": ">=12" + "node_modules/fs-constants": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/function-bind": { + "version": "1.1.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "node_modules/functions-have-names": { + "version": "1.2.3", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", "engines": { - "node": ">=6" + "node": "6.* || 8.* || >= 10.*" } }, - "packages/quicktype-core": { - "version": "18.0.15", - "license": "Apache-2.0", + "node_modules/get-intrinsic": { + "version": "1.2.4", + "dev": true, + "license": "MIT", "dependencies": { - "@glideapps/ts-necessities": "2.1.3", - "@types/urijs": "^1.19.19", - "browser-or-node": "^2.1.1", - "collection-utils": "^1.0.1", - "cross-fetch": "^4.0.0", - "is-url": "^1.2.4", - "js-base64": "^3.7.5", - "lodash": "^4.17.21", - "pako": "^1.0.6", - "pluralize": "^8.0.0", - "readable-stream": "4.4.2", - "unicode-properties": "^1.4.1", - "urijs": "^1.19.1", - "wordwrap": "^1.0.0", - "yaml": "^2.3.1" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, - "devDependencies": { - "@types/browser-or-node": "^1.3.0", - "@types/js-base64": "^3.3.1", - "@types/node": "18.14.0", - "@types/pako": "^1.0.0", - "@types/pluralize": "0.0.30", - "@types/readable-stream": "2.3.15", - "@types/unicode-properties": "^1.3.0", - "@types/yaml": "^1.9.7", - "tslint": "^6.1.3", - "typescript": "4.9.5" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/quicktype-core/node_modules/browser-or-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", - "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==" - }, - "packages/quicktype-core/node_modules/js-base64": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", - "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" + "node_modules/github-from-package": { + "version": "0.0.0", + "dev": true, + "license": "MIT", + "optional": true }, - "packages/quicktype-core/node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=4" + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "packages/quicktype-graphql-input": { - "version": "18.0.15", - "license": "Apache-2.0", + "node_modules/glob-parent": { + "version": "5.1.2", + "dev": true, + "license": "ISC", "dependencies": { - "collection-utils": "^1.0.1", - "graphql": "^0.11.7", - "quicktype-core": "file:../quicktype-core" + "is-glob": "^4.0.1" }, - "devDependencies": { - "@types/graphql": "^0.11.7", - "@types/node": "18.14.0", - "tslint": "^6.1.3", - "typescript": "4.9.5" + "engines": { + "node": ">= 6" } }, - "packages/quicktype-typescript-input": { - "version": "18.0.15", - "license": "Apache-2.0", + "node_modules/globals": { + "version": "13.24.0", + "dev": true, + "license": "MIT", "dependencies": { - "@mark.probst/typescript-json-schema": "0.55.0", - "quicktype-core": "file:../quicktype-core", - "typescript": "4.9.5" + "type-fest": "^0.20.2" }, - "devDependencies": { - "@types/node": "18.14.0", - "tslint": "^6.1.3" + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/quicktype-typescript-input/node_modules/@glideapps/ts-necessities": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.2.tgz", - "integrity": "sha512-tLjfhinr6doUBcWi7BWnkT2zT6G5UhiZftsiIH6xVvykeXE+FU7Wr0MyqwmqideWlDD5rG+VjVLptLviGo04CA==" - }, - "packages/quicktype-typescript-input/node_modules/isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "dependencies": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/quicktype-typescript-input/node_modules/node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", + "node_modules/gopd": { + "version": "1.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "packages/quicktype-typescript-input/node_modules/quicktype-core": { - "version": "20.0.0", - "resolved": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-20.0.0.tgz", - "integrity": "sha512-zuvQAk/i4STnhLC4t3nNWPr6u5ArHBW+TME3jA7YQQMp1UdDsFD+4lzqt49b73aYhhmrk9BlO/fX7PcRR5l6YQ==", - "dependencies": { - "@glideapps/ts-necessities": "2.1.2", - "@types/urijs": "^1.19.8", - "browser-or-node": "^1.2.1", - "collection-utils": "^1.0.1", - "is-url": "^1.2.4", - "isomorphic-fetch": "^2.2.1", - "js-base64": "^2.4.3", - "lodash": "^4.17.21", - "pako": "^1.0.6", - "pluralize": "^7.0.0", - "readable-stream": "2.3.7", - "unicode-properties": "^1.4.1", - "urijs": "^1.19.1", - "wordwrap": "^1.0.0", - "yaml": "^1.5.0" - } + "node_modules/graceful-fs": { + "version": "4.2.11", + "dev": true, + "license": "ISC" }, - "packages/quicktype-typescript-input/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "node_modules/graphemer": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/graphql": { + "version": "0.11.7", + "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "iterall": "1.1.3" } }, - "packages/quicktype-typescript-input/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/has": { + "version": "1.0.3", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.1" + }, "engines": { - "node": ">= 6" - } - } - }, - "dependencies": { - "@75lb/deep-merge": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@75lb/deep-merge/-/deep-merge-1.1.1.tgz", - "integrity": "sha512-xvgv6pkMGBA6GwdyJbNAnDmfAIR/DfWhrj9jgWh3TY7gRm3KO46x/GPjRg6wJ0nOepwqrNxFfojebh0Df4h4Tw==", - "requires": { - "lodash.assignwith": "^4.2.0", - "typical": "^7.1.1" - }, - "dependencies": { - "typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" - } + "node": ">= 0.4.0" } }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "requires": { - "@jridgewell/trace-mapping": "0.3.9" + "node_modules/has-bigints": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@glideapps/ts-necessities": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.3.tgz", - "integrity": "sha512-q9U8v/n9qbkd2zDYjuX3qtlbl+OIyI9zF+zQhZjfYOE9VMDH7tfcUSJ9p0lXoY3lxmGFne09yi4iiNeQUwV7AA==" - }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - }, - "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "node_modules/has-flag": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" } }, - "@mark.probst/typescript-json-schema": { - "version": "0.55.0", - "resolved": "https://registry.npmjs.org/@mark.probst/typescript-json-schema/-/typescript-json-schema-0.55.0.tgz", - "integrity": "sha512-jI48mSnRgFQxXiE/UTUCVCpX8lK3wCFKLF1Ss2aEreboKNuLQGt3e0/YFqWVHe/WENxOaqiJvwOz+L/SrN2+qQ==", - "requires": { - "@types/json-schema": "^7.0.9", - "@types/node": "^16.9.2", - "glob": "^7.1.7", - "path-equal": "^1.1.2", - "safe-stable-stringify": "^2.2.0", - "ts-node": "^10.9.1", - "typescript": "4.9.4", - "yargs": "^17.1.1" - }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "dev": true, + "license": "MIT", "dependencies": { - "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==" - }, - "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==" - } + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" - }, - "@tsconfig/node16": { + "node_modules/has-proto": { "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" - }, - "@tsconfig/node18": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node18/-/node18-1.0.1.tgz", - "integrity": "sha512-sNFeK6X2ATlhlvzyH4kKYQlfHXE2f2/wxtB9ClvYXevWpmwkUT7VaSrjIN9E76Qebz8qP5JOJJ9jD3QoD/Z9TA==", - "dev": true - }, - "@types/browser-or-node": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/browser-or-node/-/browser-or-node-1.3.0.tgz", - "integrity": "sha512-MVetr65IR7RdJbUxVHsaPFaXAO8fi89zv1g8L/mHygh1Q7xnnK02XZLwfMh57FOpTO6gtnagoPMQ/UOFfctXRQ==", - "dev": true - }, - "@types/command-line-args": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.2.0.tgz", - "integrity": "sha512-UuKzKpJJ/Ief6ufIaIzr3A/0XnluX7RvFgwkV89Yzvm77wCh1kFaFmqN8XEnGcN62EuHdedQjEMb8mYxFLGPyA==", - "dev": true - }, - "@types/command-line-usage": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@types/command-line-usage/-/command-line-usage-5.0.2.tgz", - "integrity": "sha512-n7RlEEJ+4x4TS7ZQddTmNSxP+zziEG0TNsMfiRIxcIVXt71ENJ9ojeXmGO3wPoTdn7pJcU2xc3CJYMktNT6DPg==", - "dev": true - }, - "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@types/graphql": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@types/graphql/-/graphql-0.11.8.tgz", - "integrity": "sha512-xGWx4kx9JKlqxDrZA12gw5qi2lvxPNLxnQQcoTXVX83MuGcXcpb7TADatGyGW51GaaXQOQTbjw3x4HuL3ULBaA==", - "dev": true - }, - "@types/js-base64": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@types/js-base64/-/js-base64-3.3.1.tgz", - "integrity": "sha512-Zw33oQNAvDdAN9b0IE5stH0y2MylYvtU7VVTKEJPxhyM2q57CVaNJhtJW258ah24NRtaiA23tptUmVn3dmTKpw==", + "node_modules/has-symbols": { + "version": "1.0.3", "dev": true, - "requires": { - "js-base64": "*" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" - }, - "@types/lodash": { - "version": "4.14.197", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.197.tgz", - "integrity": "sha512-BMVOiWs0uNxHVlHBgzTIqJYmj+PgCo4euloGF+5m4okL3rEYzM2EEv78mw8zWSMM57dM7kVIgJ2QDvwHSoCI5g==", - "dev": true - }, - "@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "@types/node": { - "version": "18.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.0.tgz", - "integrity": "sha512-5EWrvLmglK+imbCJY0+INViFWUHg1AHel1sq4ZVSfdcNqGy9Edv3UB9IIzzg+xPaUcAgZYcfVs2fBcwDeZzU0A==" - }, - "@types/pako": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@types/pako/-/pako-1.0.0.tgz", - "integrity": "sha1-6q6DZNG391LiY7w/1o3+yY5hNsU=", - "dev": true - }, - "@types/pluralize": { - "version": "0.0.30", - "resolved": "https://registry.npmjs.org/@types/pluralize/-/pluralize-0.0.30.tgz", - "integrity": "sha512-kVww6xZrW/db5BR9OqiT71J9huRdQ+z/r+LbDuT7/EK50mCmj5FoaIARnVv0rvjUS/YpDox0cDU9lpQT011VBA==", - "dev": true - }, - "@types/readable-stream": { - "version": "2.3.15", - "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", - "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", + "node_modules/has-tostringtag": { + "version": "1.0.2", "dev": true, - "requires": { - "@types/node": "*", - "safe-buffer": "~5.1.1" + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "@types/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", - "dev": true - }, - "@types/shelljs": { - "version": "0.8.12", - "resolved": "https://registry.npmjs.org/@types/shelljs/-/shelljs-0.8.12.tgz", - "integrity": "sha512-ZA8U81/gldY+rR5zl/7HSHrG2KDfEb3lzG6uCUDhW1DTQE9yC/VBQ45fXnXq8f3CgInfhZmjtdu/WOUlrXRQUg==", + "node_modules/hasown": { + "version": "2.0.2", "dev": true, - "requires": { - "@types/glob": "~7.2.0", - "@types/node": "*" + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" } }, - "@types/stream-chain": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/stream-chain/-/stream-chain-2.0.1.tgz", - "integrity": "sha512-D+Id9XpcBpampptkegH7WMsEk6fUdf9LlCIX7UhLydILsqDin4L0QT7ryJR0oycwC7OqohIzdfcMHVZ34ezNGg==", + "node_modules/he": { + "version": "1.2.0", "dev": true, - "requires": { - "@types/node": "*" + "license": "MIT", + "bin": { + "he": "bin/he" } }, - "@types/stream-json": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@types/stream-json/-/stream-json-1.7.3.tgz", - "integrity": "sha512-Jqsyq5VPOTWorvEmzWhEWH5tJnHA+bB8vt/Zzb11vSDj8esfSHDMj2rbVjP0mfJQzl3YBJSXBBq08iiyaBK3KA==", + "node_modules/hosted-git-info": { + "version": "4.1.0", "dev": true, - "requires": { - "@types/node": "*", - "@types/stream-chain": "*" + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" } }, - "@types/unicode-properties": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@types/unicode-properties/-/unicode-properties-1.3.0.tgz", - "integrity": "sha512-kDVlxpdkCfgvzfXcglkr7j4OSMjCEEo/Jloj4tFuldYZpQ9Uypy7FGXPhNstoj4eGvhddwuu5n0EfI+XdWVoVA==", - "dev": true - }, - "@types/urijs": { - "version": "1.19.19", - "resolved": "https://registry.npmjs.org/@types/urijs/-/urijs-1.19.19.tgz", - "integrity": "sha512-FDJNkyhmKLw7uEvTxx5tSXfPeQpO0iy73Ry+PmYZJvQy0QIWX8a7kJ4kLWRf+EbTPJEPDSgPXHaM7pzr5lmvCg==" - }, - "@types/yaml": { - "version": "1.9.7", - "resolved": "https://registry.npmjs.org/@types/yaml/-/yaml-1.9.7.tgz", - "integrity": "sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA==", + "node_modules/html-escaper": { + "version": "2.0.2", "dev": true, - "requires": { - "yaml": "*" - } + "license": "MIT" }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" + "node_modules/htmlparser2": { + "version": "8.0.2", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" } }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" - }, - "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "node_modules/http-proxy-agent": { + "version": "4.0.1", "dev": true, - "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "license": "MIT", + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "ansi-regex": { + "node_modules/https-proxy-agent": { "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, - "requires": { - "color-convert": "^1.9.0" + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" } }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" + "node_modules/iconv-lite": { + "version": "0.6.3", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" } }, - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==" + "node_modules/ieee754": { + "version": "1.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" }, - "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "node_modules/ignore": { + "version": "5.3.1", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "license": "MIT", + "engines": { + "node": ">= 4" } }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" - }, - "base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + "node_modules/immediate": { + "version": "3.0.6", + "dev": true, + "license": "MIT" }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "node_modules/import-fresh": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "browser-or-node": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-1.2.1.tgz", - "integrity": "sha512-sVIA0cysIED0nbmNOm7sZzKfgN1rpFmrqvLZaFWspaBAftfQcezlC81G6j6U2RJf4Lh66zFxrCeOsvkUXIcPWg==" + "node_modules/imurmurhash": { + "version": "0.1.4", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } }, - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" } }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" }, - "call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "node_modules/ini": { + "version": "1.3.8", "dev": true, - "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" - } + "license": "ISC", + "optional": true }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "requires": { - "has-flag": "^4.0.0" - } - } + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" } }, - "chalk-template": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/chalk-template/-/chalk-template-0.4.0.tgz", - "integrity": "sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg==", - "requires": { - "chalk": "^4.1.2" - } + "node_modules/interpret": { + "version": "1.1.0", + "dev": true, + "license": "MIT" }, - "cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "collection-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collection-utils/-/collection-utils-1.0.1.tgz", - "integrity": "sha512-LA2YTIlR7biSpXkKYwwuzGjwL5rjWEZVOSnvdUc7gObvWe4WkjxOpfrdhoP7Hs09YWDVfg0Mal9BpAqLfVEzQg==" - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "node_modules/is-arguments": { + "version": "1.1.1", "dev": true, - "requires": { - "color-name": "1.1.3" - }, + "license": "MIT", "dependencies": { - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - } + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "requires": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "command-line-usage": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-7.0.1.tgz", - "integrity": "sha512-NCyznE//MuTjwi3y84QVUGEOT+P5oto1e1Pk/jFPVdPPfsG03qpTIl3yw6etR+v73d0lXsoojRpvbru2sqePxQ==", - "requires": { - "array-back": "^6.2.2", - "chalk-template": "^0.4.0", - "table-layout": "^3.0.0", - "typical": "^7.1.1" - }, + "node_modules/is-bigint": { + "version": "1.0.4", + "dev": true, + "license": "MIT", "dependencies": { - "array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==" - }, - "typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" - } + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "commander": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", - "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" - }, - "core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" - }, - "cross-fetch": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.0.0.tgz", - "integrity": "sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==", - "requires": { - "node-fetch": "^2.6.12" + "node_modules/is-binary-path": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" } }, - "deep-equal": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.2.tgz", - "integrity": "sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==", + "node_modules/is-boolean-object": { + "version": "1.1.2", "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", + "license": "MIT", + "dependencies": { "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.3", - "get-intrinsic": "^1.2.1", - "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.2", - "is-date-object": "^1.0.5", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "isarray": "^2.0.5", - "object-is": "^1.1.5", - "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "side-channel": "^1.0.4", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "has-tostringtag": "^1.0.0" }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "node_modules/is-callable": { + "version": "1.2.7", "dev": true, - "requires": { - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" - }, - "encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", - "requires": { - "iconv-lite": "^0.6.2" + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "es-get-iterator": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", - "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "node_modules/is-core-module": { + "version": "2.13.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", + "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "has-symbols": "^1.0.3", - "is-arguments": "^1.1.1", - "is-map": "^2.0.2", - "is-set": "^2.0.2", - "is-string": "^1.0.7", - "isarray": "^2.0.5", - "stop-iteration-iterator": "^1.0.0" - }, "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-string-regexp": { + "node_modules/is-date-object": { "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "esutils": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", - "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", - "dev": true - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "exec-sh": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/exec-sh/-/exec-sh-0.2.1.tgz", - "integrity": "sha512-aLt95pexaugVtQerpmE51+4QfWrNc304uez7jvj6fWnN8GeEHpttB8F36n8N7uVhUMbH/1enbxQ9HImZ4w/9qg==", "dev": true, - "requires": { - "merge": "^1.1.3" + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw=", - "dev": true - }, - "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true - }, - "fast-json-stable-stringify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "node_modules/is-extglob": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "find-replace": { + "node_modules/is-fullwidth-code-point": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "requires": { - "array-back": "^3.0.1" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "node_modules/is-glob": { + "version": "4.0.3", "dev": true, - "requires": { - "is-callable": "^1.1.3" + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "node_modules/is-map": { + "version": "2.0.2", "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" - } - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "node_modules/is-number": { + "version": "7.0.0", "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">=0.12.0" } }, - "graphql": { - "version": "0.11.7", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-0.11.7.tgz", - "integrity": "sha512-x7uDjyz8Jx+QPbpCFCMQ8lltnQa4p4vSYHx6ADe8rVYRTdsyhCJbvSty5DAsLVmU6cGakl+r8HQYolKHxk/tiw==", - "requires": { - "iterall": "1.1.3" + "node_modules/is-number-object": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "node_modules/is-path-inside": { + "version": "3.0.3", "dev": true, - "requires": { - "function-bind": "^1.1.1" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "node_modules/is-plain-obj": { + "version": "2.1.0", "dev": true, - "requires": { - "get-intrinsic": "^1.1.1" + "license": "MIT", + "engines": { + "node": ">=8" } }, - "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true - }, - "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "node_modules/is-regex": { + "version": "1.1.4", "dev": true, - "requires": { - "has-symbols": "^1.0.2" + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3.0.0" + "node_modules/is-set": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" + "node_modules/is-stream": { + "version": "1.1.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + "node_modules/is-string": { + "version": "1.0.7", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "internal-slot": { + "node_modules/is-symbol": { "version": "1.0.4", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", - "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", "dev": true, - "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "is-arguments": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", - "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "node_modules/is-url": { + "version": "1.2.4", + "license": "MIT" + }, + "node_modules/is-weakmap": { + "version": "2.0.1", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "node_modules/is-weakset": { + "version": "2.0.2", "dev": true, - "requires": { + "license": "MIT", + "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", "dev": true, - "requires": { - "has-bigints": "^1.0.1" + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" } }, - "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "node_modules/istanbul-lib-report": { + "version": "3.0.1", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" } }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true + "node_modules/istanbul-lib-report/node_modules/has-flag": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "node_modules/istanbul-lib-report/node_modules/supports-color": { + "version": "7.2.0", "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" } }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "node_modules/istanbul-reports": { + "version": "3.1.7", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } }, - "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", - "dev": true + "node_modules/iterall": { + "version": "1.1.3", + "license": "MIT" }, - "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "node_modules/jackspeak": { + "version": "2.3.6", "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, - "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "node_modules/js-base64": { + "version": "3.7.7", + "license": "BSD-3-Clause" + }, + "node_modules/json-buffer": { + "version": "3.0.1", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" - } + "license": "MIT" }, - "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", - "dev": true + "node_modules/json-schema-traverse": { + "version": "0.3.1", + "dev": true, + "license": "MIT" }, - "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", "dev": true, - "requires": { - "call-bind": "^1.0.2" - } + "license": "MIT" }, - "is-stream": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + "node_modules/jsonc-parser": { + "version": "3.2.1", + "dev": true, + "license": "MIT" }, - "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "node_modules/jszip": { + "version": "3.10.1", "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" + "license": "(MIT OR GPL-3.0-or-later)", + "dependencies": { + "lie": "~3.3.0", + "pako": "~1.0.2", + "readable-stream": "~2.3.6", + "setimmediate": "^1.0.5" } }, - "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "node_modules/jszip/node_modules/readable-stream": { + "version": "2.3.8", "dev": true, - "requires": { - "has-symbols": "^1.0.2" + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "node_modules/keytar": { + "version": "7.9.0", "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "node-addon-api": "^4.3.0", + "prebuild-install": "^7.0.1" } }, - "is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==" - }, - "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", - "dev": true - }, - "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "node_modules/keyv": { + "version": "4.5.4", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" } }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "node_modules/leven": { + "version": "3.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "iterall": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.1.3.tgz", - "integrity": "sha512-Cu/kb+4HiNSejAPhSaN1VukdNTTi/r4/e+yykqjlG/IW+1gZH5b4+Bq3whDX4tvbYugta3r8KTMUiqT3fIGxuQ==" + "node_modules/levn": { + "version": "0.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } }, - "js-base64": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", - "integrity": "sha512-H7ErYLM34CvDMto3GbD6xD0JLUGYXR3QTcH6B/tr4Hi/QpSThnCsIp+Sy5FRTw3B0d6py4HcNkW7nO/wdtGWEw==" + "node_modules/lie": { + "version": "3.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", + "node_modules/linkify-it": { + "version": "3.0.3", "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, + "license": "MIT", "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } + "uc.micro": "^1.0.1" } }, - "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "node_modules/locate-path": { + "version": "6.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "lodash": { + "node_modules/lodash": { "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "license": "MIT" }, - "lodash.assignwith": { + "node_modules/lodash.assignwith": { "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.assignwith/-/lodash.assignwith-4.2.0.tgz", - "integrity": "sha512-ZznplvbvtjK2gMvnQ1BR/zqPFZmS6jbK4p+6Up4xcRYA7yMIwxHCfbTcrYxXKzzqLsQ05eJPVznEW3tuwV7k1g==" + "license": "MIT" }, - "lodash.camelcase": { + "node_modules/lodash.camelcase": { "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "dev": true, + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "lru-cache": { + "node_modules/lru-cache": { "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, - "requires": { + "license": "ISC", + "dependencies": { "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, - "make-error": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.4.tgz", - "integrity": "sha512-0Dab5btKVPhibSalc9QGXb559ED7G7iLjFXBaj9Wq8O3vorueR5K5jaE3hkG6ZQINyhA/JgG6Qk4qdFQjsYV6g==" - }, - "merge": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.1.tgz", - "integrity": "sha512-VjFo4P5Whtj4vsLzsYBu5ayHhoHJ0UqNm7ibvShmbmoz7tGi0vXaoJbGdB+GmDMLUdg8DpQXEIeVDAe8MaABvQ==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" + "node_modules/magic-string": { + "version": "0.22.5", + "dev": true, + "license": "MIT", + "dependencies": { + "vlq": "^0.2.2" } }, - "minimist": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", - "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/make-dir": { + "version": "4.0.0", "dev": true, - "requires": { - "minimist": "^1.2.6" + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==" + "node_modules/make-error": { + "version": "1.3.4", + "license": "ISC" }, - "node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", - "requires": { - "whatwg-url": "^5.0.0" + "node_modules/markdown-it": { + "version": "12.3.2", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "~2.1.0", + "linkify-it": "^3.0.1", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" } }, - "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", - "dev": true + "node_modules/markdown-it/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" }, - "object-is": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", - "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "node_modules/markdown-it/node_modules/entities": { + "version": "2.1.0", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.3" + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "pako": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.6.tgz", - "integrity": "sha512-lQe48YPsMJAig+yngZ87Lus+NF+3mtu7DVOBu6b/gHO1YpKwIj5AWjZ/TOS7i46HD/UixzWb1zeWDZfGZ3iYcg==" - }, - "path-equal": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz", - "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==" - }, - "path-is-absolute": { + "node_modules/mdurl": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "pluralize": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==" - }, - "prettier": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.1.tgz", - "integrity": "sha512-fcOWSnnpCrovBsmFZIGIy9UqK2FaI7Hqax+DIO0A9UxeVoY4iweyaFjS5TavZN97Hfehph0nhsZnjlVKzEQSrQ==", - "dev": true - }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + "dev": true, + "license": "MIT" }, - "promise-timeout": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/promise-timeout/-/promise-timeout-1.3.0.tgz", - "integrity": "sha512-5yANTE0tmi5++POym6OgtFmwfDvOXABD9oj/jLQr5GPEyuNEb7jH4wbbANJceJid49jwhi1RddxnhnEAb/doqg==", - "dev": true + "node_modules/merge": { + "version": "1.2.1", + "dev": true, + "license": "MIT" }, - "quicktype-core": { - "version": "file:packages/quicktype-core", - "requires": { - "@glideapps/ts-necessities": "2.1.3", - "@types/browser-or-node": "^1.3.0", - "@types/js-base64": "^3.3.1", - "@types/node": "18.14.0", - "@types/pako": "^1.0.0", - "@types/pluralize": "0.0.30", - "@types/readable-stream": "2.3.15", - "@types/unicode-properties": "^1.3.0", - "@types/urijs": "^1.19.19", - "@types/yaml": "^1.9.7", - "browser-or-node": "^2.1.1", - "collection-utils": "^1.0.1", - "cross-fetch": "^4.0.0", - "is-url": "^1.2.4", - "js-base64": "^3.7.5", - "lodash": "^4.17.21", - "pako": "^1.0.6", - "pluralize": "^8.0.0", - "readable-stream": "4.4.2", - "tslint": "^6.1.3", - "typescript": "4.9.5", - "unicode-properties": "^1.4.1", - "urijs": "^1.19.1", - "wordwrap": "^1.0.0", - "yaml": "^2.3.1" - }, + "node_modules/merge-source-map": { + "version": "1.0.4", + "dev": true, + "license": "MIT", "dependencies": { - "browser-or-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/browser-or-node/-/browser-or-node-2.1.1.tgz", - "integrity": "sha512-8CVjaLJGuSKMVTxJ2DpBl5XnlNDiT4cQFeuCJJrvJmts9YrTZDizTX7PjC2s6W4x+MBGZeEY6dGMrF04/6Hgqg==" - }, - "js-base64": { - "version": "3.7.5", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-3.7.5.tgz", - "integrity": "sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==" - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==" - } + "source-map": "^0.5.6" } }, - "quicktype-graphql-input": { - "version": "file:packages/quicktype-graphql-input", - "requires": { - "@types/graphql": "^0.11.7", - "@types/node": "18.14.0", - "collection-utils": "^1.0.1", - "graphql": "^0.11.7", - "quicktype-core": "file:../quicktype-core", - "tslint": "^6.1.3", - "typescript": "4.9.5" + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.5.7", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" } }, - "quicktype-typescript-input": { - "version": "file:packages/quicktype-typescript-input", - "requires": { - "@mark.probst/typescript-json-schema": "0.55.0", - "@types/node": "18.14.0", - "quicktype-core": "file:../quicktype-core", - "tslint": "^6.1.3", - "typescript": "4.9.5" - }, - "dependencies": { - "@glideapps/ts-necessities": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@glideapps/ts-necessities/-/ts-necessities-2.1.2.tgz", - "integrity": "sha512-tLjfhinr6doUBcWi7BWnkT2zT6G5UhiZftsiIH6xVvykeXE+FU7Wr0MyqwmqideWlDD5rG+VjVLptLviGo04CA==" - }, - "isomorphic-fetch": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==", - "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" - } - }, - "node-fetch": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", - "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", - "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" - } - }, - "quicktype-core": { - "version": "https://registry.npmjs.org/quicktype-core/-/quicktype-core-20.0.0.tgz", - "integrity": "sha512-zuvQAk/i4STnhLC4t3nNWPr6u5ArHBW+TME3jA7YQQMp1UdDsFD+4lzqt49b73aYhhmrk9BlO/fX7PcRR5l6YQ==", - "requires": { - "@glideapps/ts-necessities": "2.1.2", - "@types/urijs": "^1.19.8", - "browser-or-node": "^1.2.1", - "collection-utils": "^1.0.1", - "is-url": "^1.2.4", - "isomorphic-fetch": "^2.2.1", - "js-base64": "^2.4.3", - "lodash": "^4.17.21", - "pako": "^1.0.6", - "pluralize": "^7.0.0", - "readable-stream": "2.3.7", - "unicode-properties": "^1.4.1", - "urijs": "^1.19.1", - "wordwrap": "^1.0.0", - "yaml": "^1.5.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==" - } + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" } }, - "readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, + "node_modules/micromatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "dev": true, "dependencies": { - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - } + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" } }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "node_modules/mime": { + "version": "1.6.0", "dev": true, - "requires": { - "resolve": "^1.1.6" + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" } }, - "regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "node_modules/mime-db": { + "version": "1.52.0", "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "node_modules/mime-types": { + "version": "2.1.35", "dev": true, - "requires": { - "path-parse": "^1.0.5" + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" } }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "safe-stable-stringify": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", - "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==" - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/mimic-response": { + "version": "3.1.0", "dev": true, - "requires": { - "lru-cache": "^6.0.0" + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "node_modules/minimatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/minimist": { + "version": "1.2.7", "dev": true, - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "stop-iteration-iterator": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", - "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "node_modules/minipass": { + "version": "7.0.4", "dev": true, - "requires": { - "internal-slot": "^1.0.4" + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" } }, - "stream-chain": { - "version": "2.2.5", - "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", - "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==" + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "dev": true, + "license": "MIT", + "optional": true }, - "stream-json": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.8.0.tgz", - "integrity": "sha512-HZfXngYHUAr1exT4fxlbc1IOce1RYxp2ldeaf97LYCOPSoOqY/1Psp7iGvpb+6JIOgkra9zDYnPX01hGAHzEPw==", - "requires": { - "stream-chain": "^2.2.5" + "node_modules/mocha": { + "version": "10.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-colors": "4.1.1", + "browser-stdout": "1.3.1", + "chokidar": "3.5.3", + "debug": "4.3.4", + "diff": "5.0.0", + "escape-string-regexp": "4.0.0", + "find-up": "5.0.0", + "glob": "8.1.0", + "he": "1.2.0", + "js-yaml": "4.1.0", + "log-symbols": "4.1.0", + "minimatch": "5.0.1", + "ms": "2.1.3", + "serialize-javascript": "6.0.0", + "strip-json-comments": "3.1.1", + "supports-color": "8.1.1", + "workerpool": "6.2.1", + "yargs": "16.2.0", + "yargs-parser": "20.2.4", + "yargs-unparser": "2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": ">= 14.0.0" } }, - "stream-read-all": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/stream-read-all/-/stream-read-all-3.0.1.tgz", - "integrity": "sha512-EWZT9XOceBPlVJRrYcykW8jyRSZYbkb/0ZK36uLEmoWVO5gxBOnntNTseNzfREsqxqdfEGQrD8SXQ3QWbBmq8A==" - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "requires": { - "safe-buffer": "~5.1.0" - } + "node_modules/mocha/node_modules/argparse": { + "version": "2.0.1", + "dev": true, + "license": "Python-2.0" }, - "string-to-stream": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/string-to-stream/-/string-to-stream-3.0.1.tgz", - "integrity": "sha512-Hl092MV3USJuUCC6mfl9sPzGloA3K5VwdIeJjYIkXY/8K+mUvaeEabWJgArp+xXrsWxCajeT2pc4axbVhIZJyg==", - "requires": { - "readable-stream": "^3.4.0" - }, + "node_modules/mocha/node_modules/brace-expansion": { + "version": "2.0.1", + "dev": true, + "license": "MIT", "dependencies": { - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - } + "balanced-match": "^1.0.0" } }, - "string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "node_modules/mocha/node_modules/chokidar": { + "version": "3.5.3", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" + "node_modules/mocha/node_modules/cliui": { + "version": "7.0.4", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" } }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/mocha/node_modules/diff": { + "version": "5.0.0", "dev": true, - "requires": { - "has-flag": "^3.0.0" + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" } }, - "table-layout": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-3.0.2.tgz", - "integrity": "sha512-rpyNZYRw+/C+dYkcQ3Pr+rLxW4CfHpXjPDnG7lYhdRoUcZTUt+KEsX+94RGp/aVp/MQU35JCITv2T/beY4m+hw==", - "requires": { - "@75lb/deep-merge": "^1.1.1", - "array-back": "^6.2.2", - "command-line-args": "^5.2.1", - "command-line-usage": "^7.0.0", - "stream-read-all": "^3.0.1", - "typical": "^7.1.1", - "wordwrapjs": "^5.1.0" + "node_modules/mocha/node_modules/escape-string-regexp": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" }, - "dependencies": { - "array-back": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-6.2.2.tgz", - "integrity": "sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==" - }, - "typical": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/typical/-/typical-7.1.1.tgz", - "integrity": "sha512-T+tKVNs6Wu7IWiAce5BgMd7OZfNYUndHwc5MknN+UHOudi7sGZzuHdCadllRuqJ3fPtgFtIH9+lt9qRv6lmpfA==" - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "tiny-inflate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.2.tgz", - "integrity": "sha1-k9nez/yIBb1X6uQxDwt0Xptvs6c=" - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" - }, - "ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", "dependencies": { - "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==" - } + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tslint": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/tslint/-/tslint-6.1.3.tgz", - "integrity": "sha512-IbR4nkT96EQOvKE2PW/djGz8iGNeJ4rF2mBfiYaR/nvUWYKJhLwimoJKgjIFEIDibBtOevj7BqCRL4oHeWWUCg==", + "node_modules/mocha/node_modules/has-flag": { + "version": "4.0.0", "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "builtin-modules": "^1.1.1", - "chalk": "^2.3.0", - "commander": "^2.12.1", - "diff": "^4.0.1", - "glob": "^7.1.1", - "js-yaml": "^3.13.1", - "minimatch": "^3.0.4", - "mkdirp": "^0.5.3", - "resolve": "^1.3.2", - "semver": "^5.3.0", - "tslib": "^1.13.0", - "tsutils": "^2.29.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", - "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", - "dev": true, - "requires": { - "@babel/highlight": "^7.0.0" - } - }, - "@babel/highlight": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", - "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", - "dev": true, - "requires": { - "chalk": "^2.0.0", - "esutils": "^2.0.2", - "js-tokens": "^4.0.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - } + "license": "MIT", + "engines": { + "node": ">=8" } }, - "tsutils": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.29.0.tgz", - "integrity": "sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA==", + "node_modules/mocha/node_modules/js-yaml": { + "version": "4.1.0", "dev": true, - "requires": { - "tslib": "^1.8.1" + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==" - }, - "typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==" - }, - "unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "requires": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - }, + "node_modules/mocha/node_modules/minimatch": { + "version": "5.0.1", + "dev": true, + "license": "ISC", "dependencies": { - "pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" - }, - "unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "requires": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } - } + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" } }, - "urijs": { - "version": "1.19.11", - "resolved": "https://registry.npmjs.org/urijs/-/urijs-1.19.11.tgz", - "integrity": "sha512-HXgFDgDommxn5/bIv0cnQZsPhHDA90NPHD6+c/v21U5+Sx5hoP8+dP9IZXBU1gIfvdRfhG8cel9QNPeionfcCQ==" + "node_modules/mocha/node_modules/ms": { + "version": "2.1.3", + "dev": true, + "license": "MIT" }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "node_modules/mocha/node_modules/supports-color": { + "version": "8.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "node_modules/mocha/node_modules/yargs": { + "version": "16.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mocha/node_modules/yargs-parser": { + "version": "20.2.4", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "dev": true, + "license": "MIT" + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "dev": true, + "license": "ISC" }, - "watch": { + "node_modules/napi-build-utils": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/watch/-/watch-1.0.2.tgz", - "integrity": "sha1-NApxe952Vyb6CqB9ch4BR6VR3ww=", "dev": true, - "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" + "license": "MIT", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.57.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" } }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "node_modules/node-addon-api": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "optional": true }, - "whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==" + "node_modules/node-fetch": { + "version": "2.6.12", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" + "node_modules/node-persist": { + "version": "4.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.12.0" } }, - "which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "node_modules/normalize-path": { + "version": "3.0.0", "dev": true, - "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "license": "MIT", + "engines": { + "node": ">=0.10.0" } }, - "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "node_modules/nth-check": { + "version": "2.1.1", "dev": true, - "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "node_modules/object-is": { + "version": "1.1.5", "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", + "license": "MIT", + "dependencies": { "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + "node_modules/object-keys": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, - "wordwrapjs": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-5.1.0.tgz", - "integrity": "sha512-JNjcULU2e4KJwUNv6CHgI46UvDGitb6dGryHajXTDiLgg1/RiGoPSDw4kZfYnwGtEXf2ZMeIewDQgFGzkCB2Sg==" + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "requires": { - "color-name": "~1.1.4" - } - } + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + "node_modules/p-locate": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" + "node_modules/pako": { + "version": "1.0.6", + "license": "(MIT AND Zlib)" }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "node_modules/parent-module": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } }, - "yaml": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", - "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==" + "node_modules/parse-semver": { + "version": "1.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^5.1.0" + } }, - "yargs": { - "version": "17.6.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz", - "integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==", - "requires": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.2", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" } }, - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==" + "node_modules/parse5": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^4.4.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "domhandler": "^5.0.2", + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-equal": { + "version": "1.2.5", + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } }, - "yn": { + "node_modules/path-key": { "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.10.2", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.2.0", + "dev": true, + "license": "ISC", + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pend": { + "version": "1.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.2", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^1.0.1", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/process": { + "version": "0.11.10", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/promise-timeout": { + "version": "1.3.0", + "dev": true, + "license": "MIT" + }, + "node_modules/pump": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.12.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quicktype": { + "resolved": "packages/quicktype-vscode", + "link": true + }, + "node_modules/quicktype-core": { + "resolved": "packages/quicktype-core", + "link": true + }, + "node_modules/quicktype-graphql-input": { + "resolved": "packages/quicktype-graphql-input", + "link": true + }, + "node_modules/quicktype-typescript-input": { + "resolved": "packages/quicktype-typescript-input", + "link": true + }, + "node_modules/quote-stream": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "0.0.1", + "minimist": "^1.1.3", + "through2": "^2.0.0" + }, + "bin": { + "quote-stream": "bin/cmd.js" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "dev": true, + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "optional": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read": { + "version": "1.0.7", + "dev": true, + "license": "ISC", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/readable-stream": { + "version": "4.5.2", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.2.1", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/readable-stream/node_modules/string_decoder": { + "version": "1.3.0", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.6.2", + "dev": true, + "dependencies": { + "resolve": "^1.1.6" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.2", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.3.0", + "dev": true, + "license": "ISC" + }, + "node_modules/semver": { + "version": "7.6.0", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "dev": true, + "license": "MIT" + }, + "node_modules/shallow-copy": { + "version": "0.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shelljs": { + "version": "0.8.5", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "glob": "^7.0.0", + "interpret": "^1.0.0", + "rechoir": "^0.6.2" + }, + "bin": { + "shjs": "bin/shjs" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true + }, + "node_modules/simple-get": { + "version": "4.0.1", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "dev": true, + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-eval": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "dependencies": { + "escodegen": "^2.1.0" + } + }, + "node_modules/static-eval/node_modules/escodegen": { + "version": "2.1.0", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/static-eval/node_modules/esprima": { + "version": "4.0.1", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/static-module": { + "version": "2.2.5", + "dev": true, + "license": "MIT", + "dependencies": { + "concat-stream": "~1.6.0", + "convert-source-map": "^1.5.1", + "duplexer2": "~0.1.4", + "escodegen": "~1.9.0", + "falafel": "^2.1.0", + "has": "^1.0.1", + "magic-string": "^0.22.4", + "merge-source-map": "1.0.4", + "object-inspect": "~1.4.0", + "quote-stream": "~1.0.2", + "readable-stream": "~2.3.3", + "shallow-copy": "~0.0.1", + "static-eval": "^2.0.0", + "through2": "~2.0.3" + } + }, + "node_modules/static-module/node_modules/convert-source-map": { + "version": "1.9.0", + "dev": true, + "license": "MIT" + }, + "node_modules/static-module/node_modules/object-inspect": { + "version": "1.4.1", + "dev": true, + "license": "MIT" + }, + "node_modules/static-module/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.8.0", + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/stream-read-all": { + "version": "3.0.1", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-to-stream": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "readable-stream": "^3.4.0" + } + }, + "node_modules/string-to-stream/node_modules/readable-stream": { + "version": "3.6.0", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/table-layout": { + "version": "3.0.2", + "license": "MIT", + "dependencies": { + "@75lb/deep-merge": "^1.1.1", + "array-back": "^6.2.2", + "command-line-args": "^5.2.1", + "command-line-usage": "^7.0.0", + "stream-read-all": "^3.0.1", + "typical": "^7.1.1", + "wordwrapjs": "^5.1.0" + }, + "bin": { + "table-layout": "bin/cli.js" + }, + "engines": { + "node": ">=12.17" + } + }, + "node_modules/table-layout/node_modules/array-back": { + "version": "6.2.2", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/table-layout/node_modules/typical": { + "version": "7.1.1", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-fs": { + "version": "2.1.1", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "dev": true, + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "dev": true, + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "2.3.8", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/tiny-inflate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.2.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-4.1.1.tgz", + "integrity": "sha512-2lv/66T7e5yNyhAAC4NaKe5nVavzuGJQVVtRYLyQ2OI8tsJ61PMLlelehb0wi2Hx6+hT/OJUWZcw8MjlSRnxvw==", + "license": "MIT", + "dependencies": { + "punycode": "^2.3.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-node": { + "version": "10.9.2", + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tunnel": { + "version": "0.0.6", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.11 <=0.7.0 || >=0.7.3" + } + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-rest-client": { + "version": "1.8.11", + "dev": true, + "license": "MIT", + "dependencies": { + "qs": "^6.9.1", + "tunnel": "0.0.6", + "underscore": "^1.12.1" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/typescript": { + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typical": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "dev": true, + "license": "MIT" + }, + "node_modules/underscore": { + "version": "1.13.6", + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, + "node_modules/unicode-properties": { + "version": "1.4.1", + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.0", + "unicode-trie": "^2.0.0" + } + }, + "node_modules/unicode-properties/node_modules/pako": { + "version": "0.2.9", + "license": "MIT" + }, + "node_modules/unicode-properties/node_modules/unicode-trie": { + "version": "2.0.0", + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie": { + "version": "0.3.1", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "^0.2.5", + "tiny-inflate": "^1.0.0" + } + }, + "node_modules/unicode-trie/node_modules/pako": { + "version": "0.2.9", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/urijs": { + "version": "1.19.11", + "license": "MIT" + }, + "node_modules/url-join": { + "version": "4.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "license": "MIT" + }, + "node_modules/v8-to-istanbul": { + "version": "9.2.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/v8-to-istanbul/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/vlq": { + "version": "0.2.3", + "dev": true, + "license": "MIT" + }, + "node_modules/watch": { + "version": "1.0.2", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "exec-sh": "^0.2.0", + "minimist": "^1.2.0" + }, + "bin": { + "watch": "cli.js" + }, + "engines": { + "node": ">=0.1.95" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-13.0.0.tgz", + "integrity": "sha512-9WWbymnqj57+XEuqADHrCJ2eSXzn8WXIW/YSGaZtb2WKAInQ6CHfaUUcTyyver0p8BDg5StLQq8h1vtZuwmOig==", + "license": "MIT", + "dependencies": { + "tr46": "^4.1.1", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/which": { + "version": "2.0.2", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/wordwrapjs": { + "version": "5.1.0", + "license": "MIT", + "engines": { + "node": ">=12.17" + } + }, + "node_modules/workerpool": { + "version": "6.2.1", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/xml2js": { + "version": "0.5.0", + "dev": true, + "license": "MIT", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.4.1", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.6.2", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yazl": { + "version": "2.5.1", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/quicktype-core": { + "version": "18.0.15", + "license": "Apache-2.0", + "dependencies": { + "@glideapps/ts-necessities": "2.2.3", + "browser-or-node": "^3.0.0", + "collection-utils": "^1.0.1", + "cross-fetch": "^4.0.0", + "is-url": "^1.2.4", + "js-base64": "^3.7.7", + "lodash": "^4.17.21", + "pako": "^1.0.6", + "pluralize": "^8.0.0", + "readable-stream": "4.5.2", + "unicode-properties": "^1.4.1", + "urijs": "^1.19.1", + "wordwrap": "^1.0.0", + "yaml": "^2.4.1" + }, + "devDependencies": { + "@types/browser-or-node": "^1.3.2", + "@types/is-url": "^1.2.32", + "@types/node": "~22.14.0", + "@types/pako": "^1.0.0", + "@types/pluralize": "0.0.30", + "@types/readable-stream": "4.0.10", + "@types/unicode-properties": "^1.3.0", + "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", + "command-line-args": "^5.2.1", + "typescript": "~5.8.3" + } + }, + "packages/quicktype-core/node_modules/pluralize": { + "version": "8.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "packages/quicktype-graphql-input": { + "version": "18.0.15", + "license": "Apache-2.0", + "dependencies": { + "collection-utils": "^1.0.1", + "graphql": "^0.11.7", + "quicktype-core": "file:../quicktype-core" + }, + "devDependencies": { + "@types/graphql": "^0.11.7", + "@types/node": "~22.14.0", + "typescript": "~5.8.3" + } + }, + "packages/quicktype-typescript-input": { + "version": "18.0.15", + "license": "Apache-2.0", + "dependencies": { + "@mark.probst/typescript-json-schema": "0.55.0", + "quicktype-core": "file:../quicktype-core", + "typescript": "4.9.5" + }, + "devDependencies": { + "@types/node": "~22.14.0" + } + }, + "packages/quicktype-typescript-input/node_modules/@glideapps/ts-necessities": { + "version": "2.1.2", + "license": "MIT" + }, + "packages/quicktype-typescript-input/node_modules/browser-or-node": { + "version": "1.3.0", + "license": "MIT" + }, + "packages/quicktype-typescript-input/node_modules/isomorphic-fetch": { + "version": "2.2.1", + "license": "MIT", + "dependencies": { + "node-fetch": "^1.0.1", + "whatwg-fetch": ">=0.10.0" + } + }, + "packages/quicktype-typescript-input/node_modules/js-base64": { + "version": "2.6.4", + "license": "BSD-3-Clause" + }, + "packages/quicktype-typescript-input/node_modules/node-fetch": { + "version": "1.7.3", + "license": "MIT", + "dependencies": { + "encoding": "^0.1.11", + "is-stream": "^1.0.1" + } + }, + "packages/quicktype-typescript-input/node_modules/quicktype-core": { + "version": "20.0.0", + "license": "Apache-2.0", + "dependencies": { + "@glideapps/ts-necessities": "2.1.2", + "@types/urijs": "^1.19.8", + "browser-or-node": "^1.2.1", + "collection-utils": "^1.0.1", + "is-url": "^1.2.4", + "isomorphic-fetch": "^2.2.1", + "js-base64": "^2.4.3", + "lodash": "^4.17.21", + "pako": "^1.0.6", + "pluralize": "^7.0.0", + "readable-stream": "2.3.7", + "unicode-properties": "^1.4.1", + "urijs": "^1.19.1", + "wordwrap": "^1.0.0", + "yaml": "^1.5.0" + } + }, + "packages/quicktype-typescript-input/node_modules/readable-stream": { + "version": "2.3.7", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "packages/quicktype-typescript-input/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "packages/quicktype-typescript-input/node_modules/yaml": { + "version": "1.10.2", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "packages/quicktype-vscode": { + "name": "quicktype", + "version": "23.0.122", + "devDependencies": { + "@types/mocha": "^10.0.6", + "@types/node": "~22.14.0", + "@types/node-persist": "^3.1.8", + "@types/readable-stream": "^4.0.10", + "@types/vscode": "^1.87.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.7.0", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9", + "@vscode/vsce": "^2.25.0", + "eslint": "^8.56.0", + "node-persist": "^4.0.1", + "quicktype-core": "file:../quicktype-core", + "quicktype-typescript-input": "file:../quicktype-typescript-input", + "typescript": "~5.8.3", + "unicode-properties": "github:quicktype/unicode-properties#dist" + }, + "engines": { + "vscode": "^1.87.0" + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.8.0.tgz", + "integrity": "sha512-gFTT+ezJmkwutUPmB0skOj3GZJtlEGnlssems4AjkVweUPGj7jRwwqg0Hhg7++kPGJqKtTYx+R05Ftww372aIg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/type-utils": "7.8.0", + "@typescript-eslint/utils": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/parser": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.8.0.tgz", + "integrity": "sha512-KgKQly1pv0l4ltcftP59uQZCi4HUYswCLbTqVZEJu7uLX8CTLyswqMLqLN+2QFz4jCptqWVV4SB7vdxcH2+0kQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/typescript-estree": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/scope-manager": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz", + "integrity": "sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/type-utils": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.8.0.tgz", + "integrity": "sha512-H70R3AefQDQpz9mGv13Uhi121FNMh+WEaRqcXTX09YEDky21km4dV1ZXJIp8QjXc4ZaVkXVdohvWDzbnbHDS+A==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.8.0", + "@typescript-eslint/utils": "7.8.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/types": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.8.0.tgz", + "integrity": "sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/typescript-estree": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz", + "integrity": "sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/visitor-keys": "7.8.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/utils": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.8.0.tgz", + "integrity": "sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.15", + "@types/semver": "^7.5.8", + "@typescript-eslint/scope-manager": "7.8.0", + "@typescript-eslint/types": "7.8.0", + "@typescript-eslint/typescript-estree": "7.8.0", + "semver": "^7.6.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "packages/quicktype-vscode/node_modules/@typescript-eslint/visitor-keys": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz", + "integrity": "sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.8.0", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "packages/quicktype-vscode/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "packages/quicktype-vscode/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "packages/quicktype-vscode/node_modules/unicode-properties": { + "version": "1.1.0", + "resolved": "git+ssh://git@github.com/quicktype/unicode-properties.git#d5fddfea1ef9d05c6479a979e225476063e13f52", + "dev": true, + "license": "MIT", + "dependencies": { + "brfs": "^1.4.0", + "unicode-trie": "^0.3.0" + } } } } diff --git a/package.json b/package.json index 70e7cecef..fb19d8882 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "quicktype", - "version": "23.0.0", + "version": "23.2.0", "license": "Apache-2.0", "main": "dist/index.js", "types": "dist/index.d.ts", @@ -10,19 +10,22 @@ }, "scripts": { "pub": "script/publish.sh", - "build": "npm run build --workspaces --if-present && tsc", + "build": "npm run clean && npm run build --workspaces --if-present && tsc", "test": "script/test", "start": "script/watch", - "clean": "rm -rf dist node_modules *~ packages/*/{dist,node_modules}", - "debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js" + "clean": "rm -rf dist *~ packages/*/{dist,out}", + "debug": "node --inspect-brk --max-old-space-size=4096 ./dist/index.js", + "lint": "eslint src/** packages/*/src/**", + "lint:fix": "eslint --fix src/** packages/*/src/**" }, "workspaces": [ "./packages/quicktype-core", "./packages/quicktype-graphql-input", - "./packages/quicktype-typescript-input" + "./packages/quicktype-typescript-input", + "./packages/quicktype-vscode" ], "dependencies": { - "@glideapps/ts-necessities": "^2.1.3", + "@glideapps/ts-necessities": "^2.2.3", "chalk": "^4.1.2", "collection-utils": "^1.0.1", "command-line-args": "^5.2.1", @@ -30,38 +33,46 @@ "cross-fetch": "^4.0.0", "graphql": "^0.11.7", "lodash": "^4.17.21", - "moment": "^2.29.4", + "moment": "^2.30.1", "quicktype-core": "20.0.12", "quicktype-graphql-input": "20.0.2", "quicktype-typescript-input": "20.0.2", - "readable-stream": "^4.4.2", + "readable-stream": "^4.5.2", "stream-json": "1.8.0", "string-to-stream": "^3.0.1", - "typescript": "4.9.5" + "typescript": "~5.8.3" }, "devDependencies": { + "@biomejs/biome": "^1.9.4", "@tsconfig/node18": "^1.0.1", "@types/command-line-args": "^5.2.0", - "@types/command-line-usage": "^5.0.2", + "@types/command-line-usage": "^5.0.4", "@types/graphql": "^0.11.7", - "@types/lodash": "^4.14.197", + "@types/lodash": "^4.17.0", "@types/semver": "^7.5.0", - "@types/shelljs": "^0.8.12", + "@types/shelljs": "^0.8.15", "@types/stream-json": "^1.7.3", - "@types/urijs": "^1.19.19", + "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", + "@typescript-eslint/eslint-plugin": "^6.3.0", + "@typescript-eslint/parser": "^6.3.0", "ajv": "^5.5.2", - "deep-equal": "^2.2.2", + "deep-equal": "^2.2.3", + "esbuild": "^0.20.2", "exit": "^0.1.2", - "prettier": "^3.0.1", "promise-timeout": "^1.3.0", "semver": "^7.5.4", "shelljs": "^0.8.5", - "ts-node": "^10.9.1", - "tslint": "^6.1.3", + "ts-node": "^10.9.2", "watch": "^1.0.2" }, - "files": [ - "dist" - ], + "overrides": { + "cross-fetch": { + "node-fetch": { + "whatwg-url": "^13.0.0" + } + } + }, + "files": ["dist"], "bin": "dist/index.js" } diff --git a/packages/quicktype-core/env.sh b/packages/quicktype-core/env.sh new file mode 100755 index 000000000..9d14844ae --- /dev/null +++ b/packages/quicktype-core/env.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +if [[ $PUBLISH == true ]]; then + echo 'HAS PUBLISH, exit' + exit 0 +fi + +if [[ $CI ]]; then + if [[ "$OSTYPE" == "darwin"* ]]; then + grep -rl '$fetch' src | xargs sed -i '' -e 's/$fetch/$fetch.ci/g' + else + grep -rl '$fetch' src | xargs sed -i -e 's/$fetch/$fetch.ci/g' + fi +fi diff --git a/packages/quicktype-core/package.json b/packages/quicktype-core/package.json index 1ca3eb970..769199b79 100644 --- a/packages/quicktype-core/package.json +++ b/packages/quicktype-core/package.json @@ -8,41 +8,45 @@ "repository": "https://github.com/quicktype/quicktype", "scripts": { "clean": "rm -rf dist node_modules *~", - "build": "tsc", - "tslint": "tslint --project ." + "build": "./env.sh && tsc" }, "dependencies": { - "@glideapps/ts-necessities": "2.1.3", - "@types/urijs": "^1.19.19", - "browser-or-node": "^2.1.1", + "@glideapps/ts-necessities": "2.2.3", + "browser-or-node": "^3.0.0", "collection-utils": "^1.0.1", - "is-url": "^1.2.4", "cross-fetch": "^4.0.0", - "js-base64": "^3.7.5", + "is-url": "^1.2.4", + "js-base64": "^3.7.7", "lodash": "^4.17.21", "pako": "^1.0.6", "pluralize": "^8.0.0", - "readable-stream": "4.4.2", + "readable-stream": "4.5.2", "unicode-properties": "^1.4.1", "urijs": "^1.19.1", "wordwrap": "^1.0.0", - "yaml": "^2.3.1" + "yaml": "^2.4.1" }, "devDependencies": { - "@types/browser-or-node": "^1.3.0", - "@types/js-base64": "^3.3.1", - "@types/node": "18.14.0", + "@types/browser-or-node": "^1.3.2", + "@types/is-url": "^1.2.32", + "@types/node": "~22.14.0", "@types/pako": "^1.0.0", "@types/pluralize": "0.0.30", - "@types/readable-stream": "2.3.15", + "@types/readable-stream": "4.0.10", "@types/unicode-properties": "^1.3.0", - "@types/yaml": "^1.9.7", - "tslint": "^6.1.3", - "typescript": "4.9.5" + "@types/urijs": "^1.19.25", + "@types/wordwrap": "^1.0.3", + "command-line-args": "^5.2.1", + "typescript": "~5.8.3" + }, + "overrides": { + "cross-fetch": { + "node-fetch": { + "whatwg-url": "^13.0.0" + } + } }, - "files": [ - "dist" - ], + "files": ["dist"], "browser": { "fs": false } diff --git a/packages/quicktype-core/src/Annotation.ts b/packages/quicktype-core/src/Annotation.ts index 8a912f305..61431cde0 100644 --- a/packages/quicktype-core/src/Annotation.ts +++ b/packages/quicktype-core/src/Annotation.ts @@ -1,14 +1,15 @@ +// eslint-disable-next-line @typescript-eslint/no-extraneous-class export class AnnotationData {} export class IssueAnnotationData extends AnnotationData { - constructor(readonly message: string) { + public constructor(public readonly message: string) { super(); } } export const anyTypeIssueAnnotation = new IssueAnnotationData( - "quicktype cannot infer this type because there is no data about it in the input." + "quicktype cannot infer this type because there is no data about it in the input.", ); export const nullTypeIssueAnnotation = new IssueAnnotationData( - "The only value for this in the input is null, which means you probably need a more complete input sample." + "The only value for this in the input is null, which means you probably need a more complete input sample.", ); diff --git a/packages/quicktype-core/src/ConvenienceRenderer.ts b/packages/quicktype-core/src/ConvenienceRenderer.ts index 774906783..41ae7e4dd 100644 --- a/packages/quicktype-core/src/ConvenienceRenderer.ts +++ b/packages/quicktype-core/src/ConvenienceRenderer.ts @@ -1,31 +1,84 @@ import { - setUnion, - setFilter, iterableEnumerate, iterableSome, mapFilter, - mapSortBy, mapFilterMap, - mapSome + mapSome, + mapSortBy, + setFilter, + setUnion, } from "collection-utils"; +import _wordwrap from "wordwrap"; -import { Type, ClassType, EnumType, UnionType, TypeKind, ClassProperty, MapType, ObjectType } from "./Type"; -import { separateNamedTypes, nullableFromUnion, matchTypeExhaustive, isNamedType } from "./TypeUtils"; -import { Namespace, Name, Namer, FixedName, SimpleName, DependencyName, keywordNamespace } from "./Naming"; -import { Renderer, BlankLineConfig, RenderContext, ForEachPosition } from "./Renderer"; -import { defined, panic, nonNull, assert } from "./support/Support"; -import { trimEnd } from "./support/Strings"; -import { Sourcelike, sourcelikeToSource, serializeRenderResult } from "./Source"; - -import { declarationsForGraph, DeclarationIR, cycleBreakerTypesForGraph, Declaration } from "./DeclarationIR"; -import { TypeAttributeStoreView } from "./TypeGraph"; +import { + enumCaseNames, + getAccessorName, + objectPropertyNames, + unionMemberName, +} from "./attributes/AccessorNames"; +import { + descriptionTypeAttributeKind, + propertyDescriptionsTypeAttributeKind, +} from "./attributes/Description"; import { TypeAttributeKind } from "./attributes/TypeAttributes"; -import { descriptionTypeAttributeKind, propertyDescriptionsTypeAttributeKind } from "./attributes/Description"; -import { enumCaseNames, objectPropertyNames, unionMemberName, getAccessorName } from "./attributes/AccessorNames"; -import { transformationForType, followTargetType, Transformation } from "./Transformers"; -import { TargetLanguage } from "./TargetLanguage"; +import { + type Declaration, + type DeclarationIR, + cycleBreakerTypesForGraph, + declarationsForGraph, +} from "./DeclarationIR"; +import { + DependencyName, + FixedName, + type Name, + type Namer, + Namespace, + SimpleName, + keywordNamespace, +} from "./Naming"; +import { + type BlankLineConfig, + type ForEachPosition, + type RenderContext, + Renderer, +} from "./Renderer"; +import { + type Sourcelike, + serializeRenderResult, + sourcelikeToSource, +} from "./Source"; +import { + type Comment, + type CommentOptions, + isStringComment, +} from "./support/Comments"; +import { trimEnd } from "./support/Strings"; +import { assert, defined, nonNull, panic } from "./support/Support"; +import type { TargetLanguage } from "./TargetLanguage"; +import { + type Transformation, + followTargetType, + transformationForType, +} from "./Transformers"; +import { + type ClassProperty, + ClassType, + EnumType, + MapType, + ObjectType, + type Type, + type TypeKind, + UnionType, +} from "./Type"; +import { TypeAttributeStoreView } from "./Type/TypeGraph"; +import { + isNamedType, + matchTypeExhaustive, + nullableFromUnion, + separateNamedTypes, +} from "./Type/TypeUtils"; -const wordWrap: (s: string) => string = require("wordwrap")(90); +const wordWrap: (s: string) => string = _wordwrap(90); export const topLevelNameOrder = 1; @@ -40,55 +93,92 @@ const assignedEnumCaseNameOrder = 10; const unionMemberNameOrder = 40; -function splitDescription(descriptions: Iterable | undefined): string[] | undefined { +function splitDescription( + descriptions: Iterable | undefined, +): string[] | undefined { if (descriptions === undefined) return undefined; const description = Array.from(descriptions).join("\n\n").trim(); if (description === "") return undefined; return wordWrap(description) .split("\n") - .map(l => l.trim()); + .map((l) => l.trim()); } -export type ForbiddenWordsInfo = { names: (Name | string)[]; includeGlobalForbidden: boolean }; +export interface ForbiddenWordsInfo { + includeGlobalForbidden: boolean; + names: Array; +} const assignedNameAttributeKind = new TypeAttributeKind("assignedName"); -const assignedPropertyNamesAttributeKind = new TypeAttributeKind>("assignedPropertyNames"); -const assignedMemberNamesAttributeKind = new TypeAttributeKind>("assignedMemberNames"); -const assignedCaseNamesAttributeKind = new TypeAttributeKind>("assignedCaseNames"); +const assignedPropertyNamesAttributeKind = new TypeAttributeKind< + ReadonlyMap +>("assignedPropertyNames"); +const assignedMemberNamesAttributeKind = new TypeAttributeKind< + ReadonlyMap +>("assignedMemberNames"); +const assignedCaseNamesAttributeKind = new TypeAttributeKind< + ReadonlyMap +>("assignedCaseNames"); export abstract class ConvenienceRenderer extends Renderer { private _globalForbiddenNamespace: Namespace | undefined; + private _otherForbiddenNamespaces: Map | undefined; + private _globalNamespace: Namespace | undefined; + private _nameStoreView: TypeAttributeStoreView | undefined; - private _propertyNamesStoreView: TypeAttributeStoreView> | undefined; - private _memberNamesStoreView: TypeAttributeStoreView> | undefined; - private _caseNamesStoreView: TypeAttributeStoreView> | undefined; + + private _propertyNamesStoreView: + | TypeAttributeStoreView> + | undefined; + + private _memberNamesStoreView: + | TypeAttributeStoreView> + | undefined; + + private _caseNamesStoreView: + | TypeAttributeStoreView> + | undefined; + private _namesForTransformations: Map | undefined; private _namedTypeNamer: Namer | undefined; - // @ts-ignore: FIXME: Make this `Namer | undefined` + + // @ts-expect-error: FIXME: Make this `Namer | undefined` private _unionMemberNamer: Namer | null; - // @ts-ignore: FIXME: Make this `Namer | undefined` + + // @ts-expect-error: FIXME: Make this `Namer | undefined` private _enumCaseNamer: Namer | null; private _declarationIR: DeclarationIR | undefined; - private _namedTypes: ReadonlyArray | undefined; + + private _namedTypes: readonly Type[] | undefined; + private _namedObjects: Set | undefined; + private _namedEnums: Set | undefined; + private _namedUnions: Set | undefined; + private _haveUnions: boolean | undefined; + private _haveMaps: boolean | undefined; + private _haveOptionalProperties: boolean | undefined; + private _cycleBreakerTypes?: Set | undefined; private _alphabetizeProperties = false; - constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + ) { super(targetLanguage, renderContext); } - get topLevels(): ReadonlyMap { + public get topLevels(): ReadonlyMap { return this.typeGraph.topLevels; } @@ -99,7 +189,7 @@ export abstract class ConvenienceRenderer extends Renderer { * that can conflict with that, such as reserved keywords or common type * names. */ - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return []; } @@ -113,33 +203,54 @@ export abstract class ConvenienceRenderer extends Renderer { * Note: That doesn't mean that the names in the global namespace will be * forbidden, too! */ - protected forbiddenForObjectProperties(_o: ObjectType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties( + _o: ObjectType, + _className: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: false }; } - protected makeTopLevelDependencyNames(_t: Type, _topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames( + _t: Type, + _topLevelName: Name, + ): DependencyName[] { return []; } - protected makeNamedTypeDependencyNames(_t: Type, _name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames( + _t: Type, + _name: Name, + ): DependencyName[] { return []; } protected abstract makeNamedTypeNamer(): Namer; - protected abstract namerForObjectProperty(o: ObjectType, p: ClassProperty): Namer | null; + protected abstract namerForObjectProperty( + o: ObjectType, + p: ClassProperty, + ): Namer | null; protected abstract makeUnionMemberNamer(): Namer | null; protected abstract makeEnumCaseNamer(): Namer | null; protected abstract emitSourceStructure(givenOutputFilename: string): void; - protected makeNameForTransformation(_xf: Transformation, _typeName: Name | undefined): Name | undefined { + protected makeNameForTransformation( + _xf: Transformation, + _typeName: Name | undefined, + ): Name | undefined { return undefined; } @@ -147,6 +258,7 @@ export abstract class ConvenienceRenderer extends Renderer { if (isNamedType(type)) { return type; } + return undefined; } @@ -163,7 +275,9 @@ export abstract class ConvenienceRenderer extends Renderer { } protected canBeForwardDeclared(_t: Type): boolean { - return panic("If needsTypeDeclarationBeforeUse returns true, canBeForwardDeclared must be implemented"); + return panic( + "If needsTypeDeclarationBeforeUse returns true, canBeForwardDeclared must be implemented", + ); } protected unionNeedsName(u: UnionType): boolean { @@ -179,29 +293,41 @@ export abstract class ConvenienceRenderer extends Renderer { } protected descriptionForType(t: Type): string[] | undefined { - let description = this.typeGraph.attributeStore.tryGet(descriptionTypeAttributeKind, t); + const description = this.typeGraph.attributeStore.tryGet( + descriptionTypeAttributeKind, + t, + ); return splitDescription(description); } - protected descriptionForClassProperty(o: ObjectType, name: string): string[] | undefined { - const descriptions = this.typeGraph.attributeStore.tryGet(propertyDescriptionsTypeAttributeKind, o); + protected descriptionForClassProperty( + o: ObjectType, + name: string, + ): string[] | undefined { + const descriptions = this.typeGraph.attributeStore.tryGet( + propertyDescriptionsTypeAttributeKind, + o, + ); if (descriptions === undefined) return undefined; return splitDescription(descriptions.get(name)); } protected setUpNaming(): ReadonlySet { - this._nameStoreView = new TypeAttributeStoreView(this.typeGraph.attributeStore, assignedNameAttributeKind); + this._nameStoreView = new TypeAttributeStoreView( + this.typeGraph.attributeStore, + assignedNameAttributeKind, + ); this._propertyNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedPropertyNamesAttributeKind + assignedPropertyNamesAttributeKind, ); this._memberNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedMemberNamesAttributeKind + assignedMemberNamesAttributeKind, ); this._caseNamesStoreView = new TypeAttributeStoreView( this.typeGraph.attributeStore, - assignedCaseNamesAttributeKind + assignedCaseNamesAttributeKind, ); this._namesForTransformations = new Map(); @@ -209,33 +335,49 @@ export abstract class ConvenienceRenderer extends Renderer { this._unionMemberNamer = this.makeUnionMemberNamer(); this._enumCaseNamer = this.makeEnumCaseNamer(); - this._globalForbiddenNamespace = keywordNamespace("forbidden", this.forbiddenNamesForGlobalNamespace()); + this._globalForbiddenNamespace = keywordNamespace( + "forbidden", + this.forbiddenNamesForGlobalNamespace(), + ); this._otherForbiddenNamespaces = new Map(); - this._globalNamespace = new Namespace("global", undefined, [this._globalForbiddenNamespace], []); - const { objects, enums, unions } = this.typeGraph.allNamedTypesSeparated(); - const namedUnions = setFilter(unions, u => this.unionNeedsName(u)); + this._globalNamespace = new Namespace( + "global", + undefined, + [this._globalForbiddenNamespace], + [], + ); + const { objects, enums, unions } = + this.typeGraph.allNamedTypesSeparated(); + const namedUnions = setFilter(unions, (u) => this.unionNeedsName(u)); for (const [name, t] of this.topLevels) { - this.nameStoreView.setForTopLevel(name, this.addNameForTopLevel(t, name)); + this.nameStoreView.setForTopLevel( + name, + this.addNameForTopLevel(t, name), + ); } + for (const o of objects) { const name = this.addNameForNamedType(o); this.addPropertyNames(o, name); } + for (const e of enums) { const name = this.addNameForNamedType(e); this.addEnumCaseNames(e, name); } + for (const u of namedUnions) { const name = this.addNameForNamedType(u); this.addUnionMemberNames(u, name); } + for (const t of this.typeGraph.allTypesUnordered()) { this.addNameForTransformation(t); } return setUnion( [this._globalForbiddenNamespace, this._globalNamespace], - this._otherForbiddenNamespaces.values() + this._otherForbiddenNamespaces.values(), ); } @@ -246,8 +388,16 @@ export abstract class ConvenienceRenderer extends Renderer { } } - protected makeNameForTopLevel(_t: Type, givenName: string, _maybeNamedType: Type | undefined): Name { - return new SimpleName([givenName], defined(this._namedTypeNamer), topLevelNameOrder); + protected makeNameForTopLevel( + _t: Type, + givenName: string, + _maybeNamedType: Type | undefined, + ): Name { + return new SimpleName( + [givenName], + defined(this._namedTypeNamer), + topLevelNameOrder, + ); } private addNameForTopLevel(type: Type, givenName: string): Name { @@ -267,14 +417,24 @@ export abstract class ConvenienceRenderer extends Renderer { return name; } - private makeNameForType(t: Type, namer: Namer, givenOrder: number, inferredOrder: number): Name { + private makeNameForType( + t: Type, + namer: Namer, + givenOrder: number, + inferredOrder: number, + ): Name { const names = t.getNames(); const order = names.areInferred ? inferredOrder : givenOrder; return new SimpleName(names.proposedNames, namer, order); } protected makeNameForNamedType(t: Type): Name { - return this.makeNameForType(t, defined(this._namedTypeNamer), givenNameOrder, inferredNameOrder); + return this.makeNameForType( + t, + defined(this._namedTypeNamer), + givenNameOrder, + inferredNameOrder, + ); } private addNameForNamedType(type: Type): Name { @@ -301,6 +461,7 @@ export abstract class ConvenienceRenderer extends Renderer { if (name === undefined) { return panic("No name for transformation"); } + return name; } @@ -310,10 +471,13 @@ export abstract class ConvenienceRenderer extends Renderer { assert( defined(this._namesForTransformations).get(t) === undefined, - "Tried to give two names to the same transformation" + "Tried to give two names to the same transformation", ); - const name = this.makeNameForTransformation(xf, this.nameStoreView.tryGet(xf.targetType)); + const name = this.makeNameForTransformation( + xf, + this.nameStoreView.tryGet(xf.targetType), + ); if (name === undefined) return; this.globalNamespace.add(name); @@ -322,8 +486,11 @@ export abstract class ConvenienceRenderer extends Renderer { private processForbiddenWordsInfo( info: ForbiddenWordsInfo, - namespaceName: string - ): { forbiddenNames: ReadonlySet; forbiddenNamespaces: ReadonlySet } { + namespaceName: string, + ): { + forbiddenNames: ReadonlySet; + forbiddenNamespaces: ReadonlySet; + } { const forbiddenNames: Name[] = []; const forbiddenStrings: string[] = []; for (const nameOrString of info.names) { @@ -333,15 +500,24 @@ export abstract class ConvenienceRenderer extends Renderer { forbiddenNames.push(nameOrString); } } - let namespace = defined(this._otherForbiddenNamespaces).get(namespaceName); + + let namespace = defined(this._otherForbiddenNamespaces).get( + namespaceName, + ); if (forbiddenStrings.length > 0 && namespace === undefined) { namespace = keywordNamespace(namespaceName, forbiddenStrings); - this._otherForbiddenNamespaces = defined(this._otherForbiddenNamespaces).set(namespaceName, namespace); + this._otherForbiddenNamespaces = defined( + this._otherForbiddenNamespaces, + ).set(namespaceName, namespace); } + let forbiddenNamespaces = new Set(); if (info.includeGlobalForbidden) { - forbiddenNamespaces = forbiddenNamespaces.add(defined(this._globalForbiddenNamespace)); + forbiddenNamespaces = forbiddenNamespaces.add( + defined(this._globalForbiddenNamespace), + ); } + if (namespace !== undefined) { forbiddenNamespaces = forbiddenNamespaces.add(namespace); } @@ -354,7 +530,7 @@ export abstract class ConvenienceRenderer extends Renderer { _className: Name, p: ClassProperty, jsonName: string, - assignedName: string | undefined + assignedName: string | undefined, ): Name | undefined { const namer = this.namerForObjectProperty(o, p); if (namer === null) return undefined; @@ -368,8 +544,14 @@ export abstract class ConvenienceRenderer extends Renderer { // maybe we'll need global properties for some weird language at // some point. const alternative = `${o.getCombinedName()}_${jsonName}`; - const order = assignedName === undefined ? classPropertyNameOrder : assignedClassPropertyNameOrder; - const names = assignedName === undefined ? [jsonName, alternative] : [assignedName]; + const order = + assignedName === undefined + ? classPropertyNameOrder + : assignedClassPropertyNameOrder; + const names = + assignedName === undefined + ? [jsonName, alternative] + : [assignedName]; return new SimpleName(names, namer, order); } @@ -378,72 +560,121 @@ export abstract class ConvenienceRenderer extends Renderer { _className: Name, _p: ClassProperty, _jsonName: string, - _name: Name + _name: Name, ): Name[] { return []; } private addPropertyNames(o: ObjectType, className: Name): void { - const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( - this.forbiddenForObjectProperties(o, className), - "forbidden-for-properties" - ); + const { forbiddenNames, forbiddenNamespaces } = + this.processForbiddenWordsInfo( + this.forbiddenForObjectProperties(o, className), + "forbidden-for-properties", + ); let ns: Namespace | undefined; const accessorNames = objectPropertyNames(o, this.targetLanguage.name); const names = mapFilterMap(o.getSortedProperties(), (p, jsonName) => { - const [assignedName, isFixed] = getAccessorName(accessorNames, jsonName); + const [assignedName, isFixed] = getAccessorName( + accessorNames, + jsonName, + ); let name: Name | undefined; if (isFixed) { name = new FixedName(defined(assignedName)); } else { - name = this.makeNameForProperty(o, className, p, jsonName, assignedName); + name = this.makeNameForProperty( + o, + className, + p, + jsonName, + assignedName, + ); } + if (name === undefined) return undefined; if (ns === undefined) { - ns = new Namespace(o.getCombinedName(), this.globalNamespace, forbiddenNamespaces, forbiddenNames); + ns = new Namespace( + o.getCombinedName(), + this.globalNamespace, + forbiddenNamespaces, + forbiddenNames, + ); } + ns.add(name); - for (const depName of this.makePropertyDependencyNames(o, className, p, jsonName, name)) { + for (const depName of this.makePropertyDependencyNames( + o, + className, + p, + jsonName, + name, + )) { ns.add(depName); } + return name; }); defined(this._propertyNamesStoreView).set(o, names); } - protected makeNameForUnionMember(u: UnionType, unionName: Name, t: Type): Name { - const [assignedName, isFixed] = unionMemberName(u, t, this.targetLanguage.name); + protected makeNameForUnionMember( + u: UnionType, + unionName: Name, + t: Type, + ): Name { + const [assignedName, isFixed] = unionMemberName( + u, + t, + this.targetLanguage.name, + ); if (isFixed) { return new FixedName(defined(assignedName)); } - return new DependencyName(nonNull(this._unionMemberNamer), unionMemberNameOrder, lookup => { - if (assignedName !== undefined) return assignedName; - return this.proposeUnionMemberName(u, unionName, t, lookup); - }); + + return new DependencyName( + nonNull(this._unionMemberNamer), + unionMemberNameOrder, + (lookup) => { + if (assignedName !== undefined) return assignedName; + return this.proposeUnionMemberName(u, unionName, t, lookup); + }, + ); } private addUnionMemberNames(u: UnionType, unionName: Name): void { const memberNamer = this._unionMemberNamer; if (memberNamer === null) return; - const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( - this.forbiddenForUnionMembers(u, unionName), - "forbidden-for-union-members" - ); + const { forbiddenNames, forbiddenNamespaces } = + this.processForbiddenWordsInfo( + this.forbiddenForUnionMembers(u, unionName), + "forbidden-for-union-members", + ); let ns: Namespace; if (this.unionMembersInGlobalNamespace) { ns = this.globalNamespace; } else { - ns = new Namespace(u.getCombinedName(), this.globalNamespace, forbiddenNamespaces, forbiddenNames); + ns = new Namespace( + u.getCombinedName(), + this.globalNamespace, + forbiddenNamespaces, + forbiddenNames, + ); } - let names = new Map(); + + const names = new Map(); for (const t of u.members) { - const name = this.makeNameForUnionMember(u, unionName, followTargetType(t)); + const name = this.makeNameForUnionMember( + u, + unionName, + followTargetType(t), + ); names.set(t, ns.add(name)); } + defined(this._memberNamesStoreView).set(u, names); } @@ -451,13 +682,19 @@ export abstract class ConvenienceRenderer extends Renderer { e: EnumType, _enumName: Name, caseName: string, - assignedName: string | undefined + assignedName: string | undefined, ): Name { // FIXME: See the FIXME in `makeNameForProperty`. We do have global // enum cases, though (in Go), so this is actually useful already. const alternative = `${e.getCombinedName()}_${caseName}`; - const order = assignedName === undefined ? enumCaseNameOrder : assignedEnumCaseNameOrder; - const names = assignedName === undefined ? [caseName, alternative] : [assignedName]; + const order = + assignedName === undefined + ? enumCaseNameOrder + : assignedEnumCaseNameOrder; + const names = + assignedName === undefined + ? [caseName, alternative] + : [assignedName]; return new SimpleName(names, nonNull(this._enumCaseNamer), order); } @@ -465,29 +702,46 @@ export abstract class ConvenienceRenderer extends Renderer { private addEnumCaseNames(e: EnumType, enumName: Name): void { if (this._enumCaseNamer === null) return; - const { forbiddenNames, forbiddenNamespaces } = this.processForbiddenWordsInfo( - this.forbiddenForEnumCases(e, enumName), - "forbidden-for-enum-cases" - ); + const { forbiddenNames, forbiddenNamespaces } = + this.processForbiddenWordsInfo( + this.forbiddenForEnumCases(e, enumName), + "forbidden-for-enum-cases", + ); let ns: Namespace; if (this.enumCasesInGlobalNamespace) { ns = this.globalNamespace; } else { - ns = new Namespace(e.getCombinedName(), this.globalNamespace, forbiddenNamespaces, forbiddenNames); + ns = new Namespace( + e.getCombinedName(), + this.globalNamespace, + forbiddenNamespaces, + forbiddenNames, + ); } - let names = new Map(); + + const names = new Map(); const accessorNames = enumCaseNames(e, this.targetLanguage.name); for (const caseName of e.cases) { - const [assignedName, isFixed] = getAccessorName(accessorNames, caseName); + const [assignedName, isFixed] = getAccessorName( + accessorNames, + caseName, + ); let name: Name; if (isFixed) { name = new FixedName(defined(assignedName)); } else { - name = this.makeNameForEnumCase(e, enumName, caseName, assignedName); + name = this.makeNameForEnumCase( + e, + enumName, + caseName, + assignedName, + ); } + names.set(caseName, ns.add(name)); } + defined(this._caseNamesStoreView).set(e, names); } @@ -499,9 +753,12 @@ export abstract class ConvenienceRenderer extends Renderer { if (propertyNameds.get(n) === undefined) return undefined; return p.type; }); - const sortedMap = mapSortBy(filteredMap, (_, n) => defined(names.get(defined(propertyNameds.get(n))))); + const sortedMap = mapSortBy(filteredMap, (_, n) => + defined(names.get(defined(propertyNameds.get(n)))), + ); return new Set(sortedMap.values()); } + return t.getChildren(); } @@ -539,7 +796,9 @@ export abstract class ConvenienceRenderer extends Renderer { return this.enums.size > 0; } - protected proposedUnionMemberNameForTypeKind(_kind: TypeKind): string | null { + protected proposedUnionMemberNameForTypeKind( + _kind: TypeKind, + ): string | null { return null; } @@ -547,9 +806,11 @@ export abstract class ConvenienceRenderer extends Renderer { _u: UnionType, _unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { - const simpleName = this.proposedUnionMemberNameForTypeKind(fieldType.kind); + const simpleName = this.proposedUnionMemberNameForTypeKind( + fieldType.kind, + ); if (simpleName !== null) { return simpleName; } @@ -557,28 +818,29 @@ export abstract class ConvenienceRenderer extends Renderer { const typeNameForUnionMember = (t: Type): string => matchTypeExhaustive( t, - _noneType => { + (_noneType) => { return panic("none type should have been replaced"); }, - _anyType => "anything", - _nullType => "null", - _boolType => "bool", - _integerType => "integer", - _doubleType => "double", - _stringType => "string", - arrayType => typeNameForUnionMember(arrayType.items) + "_array", - classType => lookup(this.nameForNamedType(classType)), - mapType => typeNameForUnionMember(mapType.values) + "_map", - objectType => { + (_anyType) => "anything", + (_nullType) => "null", + (_boolType) => "bool", + (_integerType) => "integer", + (_doubleType) => "double", + (_stringType) => "string", + (arrayType) => + typeNameForUnionMember(arrayType.items) + "_array", + (classType) => lookup(this.nameForNamedType(classType)), + (mapType) => typeNameForUnionMember(mapType.values) + "_map", + (objectType) => { assert( this.targetLanguage.supportsFullObjectType, - "Object type should have been replaced in `replaceObjectType`" + "Object type should have been replaced in `replaceObjectType`", ); return lookup(this.nameForNamedType(objectType)); }, - _enumType => "enum", - _unionType => "union", - transformedType => transformedType.kind.replace("-", "_") + (_enumType) => "enum", + (_unionType) => "union", + (transformedType) => transformedType.kind.replace("-", "_"), ); return typeNameForUnionMember(fieldType); @@ -593,7 +855,9 @@ export abstract class ConvenienceRenderer extends Renderer { } protected isImplicitCycleBreaker(_t: Type): boolean { - return panic("A renderer that invokes isCycleBreakerType must implement isImplicitCycleBreaker"); + return panic( + "A renderer that invokes isCycleBreakerType must implement isImplicitCycleBreaker", + ); } protected canBreakCycles(_t: Type): boolean { @@ -604,17 +868,18 @@ export abstract class ConvenienceRenderer extends Renderer { if (this._cycleBreakerTypes === undefined) { this._cycleBreakerTypes = cycleBreakerTypesForGraph( this.typeGraph, - s => this.isImplicitCycleBreaker(s), - s => this.canBreakCycles(s) + (s) => this.isImplicitCycleBreaker(s), + (s) => this.canBreakCycles(s), ); } + return this._cycleBreakerTypes.has(t); } protected forEachTopLevel( blankLocations: BlankLineConfig, f: (t: Type, name: Name, position: ForEachPosition) => void, - predicate?: (t: Type) => boolean + predicate?: (t: Type) => boolean, ): boolean { let topLevels: ReadonlyMap; if (predicate !== undefined) { @@ -622,23 +887,27 @@ export abstract class ConvenienceRenderer extends Renderer { } else { topLevels = this.topLevels; } - return this.forEachWithBlankLines(topLevels, blankLocations, (t, name, pos) => - f(t, this.nameStoreView.getForTopLevel(name), pos) + + return this.forEachWithBlankLines( + topLevels, + blankLocations, + (t, name, pos) => + f(t, this.nameStoreView.getForTopLevel(name), pos), ); } protected forEachDeclaration( blankLocations: BlankLineConfig, - f: (decl: Declaration, position: ForEachPosition) => void - ) { + f: (decl: Declaration, position: ForEachPosition) => void, + ): void { this.forEachWithBlankLines( iterableEnumerate(defined(this._declarationIR).declarations), blankLocations, - (decl, _, pos) => f(decl, pos) + (decl, _, pos) => f(decl, pos), ); } - setAlphabetizeProperties(value: boolean): void { + public setAlphabetizeProperties(value: boolean): void { this._alphabetizeProperties = value; } @@ -654,29 +923,44 @@ export abstract class ConvenienceRenderer extends Renderer { protected sortClassProperties( properties: ReadonlyMap, - propertyNames: ReadonlyMap + propertyNames: ReadonlyMap, ): ReadonlyMap { if (this._alphabetizeProperties) { - return mapSortBy(properties, (_p: ClassProperty, jsonName: string) => { - const name = defined(propertyNames.get(jsonName)); - return defined(this.names.get(name)); - }); - } else { - return properties; + return mapSortBy( + properties, + (_p: ClassProperty, jsonName: string) => { + const name = defined(propertyNames.get(jsonName)); + return defined(this.names.get(name)); + }, + ); } + + return properties; } protected forEachClassProperty( o: ObjectType, blankLocations: BlankLineConfig, - f: (name: Name, jsonName: string, p: ClassProperty, position: ForEachPosition) => void + f: ( + name: Name, + jsonName: string, + p: ClassProperty, + position: ForEachPosition, + ) => void, ): void { const propertyNames = defined(this._propertyNamesStoreView).get(o); - const sortedProperties = this.sortClassProperties(o.getProperties(), propertyNames); - this.forEachWithBlankLines(sortedProperties, blankLocations, (p, jsonName, pos) => { - const name = defined(propertyNames.get(jsonName)); - f(name, jsonName, p, pos); - }); + const sortedProperties = this.sortClassProperties( + o.getProperties(), + propertyNames, + ); + this.forEachWithBlankLines( + sortedProperties, + blankLocations, + (p, jsonName, pos) => { + const name = defined(propertyNames.get(jsonName)); + f(name, jsonName, p, pos); + }, + ); } protected nameForUnionMember(u: UnionType, t: Type): Name { @@ -693,13 +977,17 @@ export abstract class ConvenienceRenderer extends Renderer { members: ReadonlySet | null, blankLocations: BlankLineConfig, sortOrder: ((n: Name, t: Type) => string) | null, - f: (name: Name, t: Type, position: ForEachPosition) => void + f: (name: Name, t: Type, position: ForEachPosition) => void, ): void { - const iterateMembers = members === null ? u.members : members; + const iterateMembers = members ?? u.members; if (sortOrder === null) { - sortOrder = n => defined(this.names.get(n)); + sortOrder = (n): string => defined(this.names.get(n)); } - const memberNames = mapFilter(defined(this._memberNamesStoreView).get(u), (_, t) => iterateMembers.has(t)); + + const memberNames = mapFilter( + defined(this._memberNamesStoreView).get(u), + (_, t) => iterateMembers.has(t), + ); const sortedMemberNames = mapSortBy(memberNames, sortOrder); this.forEachWithBlankLines(sortedMemberNames, blankLocations, f); } @@ -707,56 +995,80 @@ export abstract class ConvenienceRenderer extends Renderer { protected forEachEnumCase( e: EnumType, blankLocations: BlankLineConfig, - f: (name: Name, jsonName: string, position: ForEachPosition) => void + f: (name: Name, jsonName: string, position: ForEachPosition) => void, ): void { const caseNames = defined(this._caseNamesStoreView).get(e); - const sortedCaseNames = mapSortBy(caseNames, n => defined(this.names.get(n))); + const sortedCaseNames = mapSortBy(caseNames, (n) => + defined(this.names.get(n)), + ); this.forEachWithBlankLines(sortedCaseNames, blankLocations, f); } protected forEachTransformation( blankLocations: BlankLineConfig, - f: (n: Name, t: Type, position: ForEachPosition) => void + f: (n: Name, t: Type, position: ForEachPosition) => void, ): void { - this.forEachWithBlankLines(defined(this._namesForTransformations), blankLocations, f); + this.forEachWithBlankLines( + defined(this._namesForTransformations), + blankLocations, + f, + ); } protected forEachSpecificNamedType( blankLocations: BlankLineConfig, - types: Iterable<[any, T]>, - f: (t: T, name: Name, position: ForEachPosition) => void + types: Iterable<[T, T]>, + f: (t: T, name: Name, position: ForEachPosition) => void, ): void { - this.forEachWithBlankLines(types, blankLocations, (t, _, pos) => f(t, this.nameForNamedType(t), pos)); + this.forEachWithBlankLines(types, blankLocations, (t, _, pos) => + f(t, this.nameForNamedType(t), pos), + ); } protected forEachObject( blankLocations: BlankLineConfig, f: - | ((c: ClassType, className: Name, position: ForEachPosition) => void) - | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void) + | (( + c: ClassType, + className: Name, + position: ForEachPosition, + ) => void) + | (( + o: ObjectType, + objectName: Name, + position: ForEachPosition, + ) => void), ): void { // FIXME: This is ugly. - this.forEachSpecificNamedType(blankLocations, defined(this._namedObjects).entries(), f as any); + this.forEachSpecificNamedType( + blankLocations, + defined(this._namedObjects).entries(), + f, + ); } protected forEachEnum( blankLocations: BlankLineConfig, - f: (u: EnumType, enumName: Name, position: ForEachPosition) => void + f: (u: EnumType, enumName: Name, position: ForEachPosition) => void, ): void { this.forEachSpecificNamedType(blankLocations, this.enums.entries(), f); } protected forEachUnion( blankLocations: BlankLineConfig, - f: (u: UnionType, unionName: Name, position: ForEachPosition) => void + f: (u: UnionType, unionName: Name, position: ForEachPosition) => void, ): void { - this.forEachSpecificNamedType(blankLocations, this.namedUnions.entries(), f); + this.forEachSpecificNamedType( + blankLocations, + this.namedUnions.entries(), + f, + ); } protected forEachUniqueUnion( blankLocations: BlankLineConfig, uniqueValue: (u: UnionType) => T, - f: (firstUnion: UnionType, value: T, position: ForEachPosition) => void + f: (firstUnion: UnionType, value: T, position: ForEachPosition) => void, ): void { const firstUnionByValue = new Map(); for (const u of this.namedUnions) { @@ -765,71 +1077,117 @@ export abstract class ConvenienceRenderer extends Renderer { firstUnionByValue.set(v, u); } } + this.forEachWithBlankLines(firstUnionByValue, blankLocations, f); } protected forEachNamedType( blankLocations: BlankLineConfig, objectFunc: - | ((c: ClassType, className: Name, position: ForEachPosition) => void) - | ((o: ObjectType, objectName: Name, position: ForEachPosition) => void), - enumFunc: (e: EnumType, enumName: Name, position: ForEachPosition) => void, - unionFunc: (u: UnionType, unionName: Name, position: ForEachPosition) => void + | (( + c: ClassType, + className: Name, + position: ForEachPosition, + ) => void) + | (( + o: ObjectType, + objectName: Name, + position: ForEachPosition, + ) => void), + enumFunc: ( + e: EnumType, + enumName: Name, + position: ForEachPosition, + ) => void, + unionFunc: ( + u: UnionType, + unionName: Name, + position: ForEachPosition, + ) => void, ): void { - this.forEachWithBlankLines(defined(this._namedTypes).entries(), blankLocations, (t, _, pos) => { - const name = this.nameForNamedType(t); - if (t instanceof ObjectType) { - // FIXME: This is ugly. We can't runtime check that the function - // takes full object types if we have them. - (objectFunc as any)(t, name, pos); - } else if (t instanceof EnumType) { - enumFunc(t, name, pos); - } else if (t instanceof UnionType) { - unionFunc(t, name, pos); - } else { - return panic("Named type that's neither a class nor union"); - } - }); + this.forEachWithBlankLines( + defined(this._namedTypes).entries(), + blankLocations, + (t, _, pos) => { + const name = this.nameForNamedType(t); + if (t instanceof ObjectType) { + // FIXME: This is ugly. We can't runtime check that the function + // takes full object types if we have them. + objectFunc(t, name, pos); + } else if (t instanceof EnumType) { + enumFunc(t, name, pos); + } else if (t instanceof UnionType) { + unionFunc(t, name, pos); + } else { + return panic("Named type that's neither a class nor union"); + } + }, + ); } // You should never have to use this to produce parts of your generated // code. If you need to modify a Name, for example to change its casing, // use `modifySource`. protected sourcelikeToString(src: Sourcelike): string { - return serializeRenderResult(sourcelikeToSource(src), this.names, "").lines.join("\n"); + return serializeRenderResult( + sourcelikeToSource(src), + this.names, + "", + ).lines.join("\n"); } protected get commentLineStart(): string { return "// "; } + protected emitComments(comments: Comment[]): void { + comments.forEach((comment) => { + if (isStringComment(comment)) { + this.emitCommentLines([comment]); + } else if ("lines" in comment) { + this.emitCommentLines(comment.lines); + } else if ("descriptionBlock" in comment) { + this.emitDescriptionBlock(comment.descriptionBlock); + } else { + this.emitCommentLines(comment.customLines, comment); + } + + this.ensureBlankLine(); + }); + } + protected emitCommentLines( lines: Sourcelike[], - lineStart?: string, - beforeLine?: string, - afterLine?: string, - firstLineStart?: string + { + lineStart = this.commentLineStart, + firstLineStart = lineStart, + lineEnd, + beforeComment, + afterComment, + }: CommentOptions = {}, ): void { - if (lineStart === undefined) { - lineStart = this.commentLineStart; - } - if (firstLineStart === undefined) { - firstLineStart = lineStart; - } - if (beforeLine !== undefined) { - this.emitLine(beforeLine); + if (beforeComment !== undefined) { + this.emitLine(beforeComment); } + let first = true; for (const line of lines) { let start = first ? firstLineStart : lineStart; + first = false; + if (this.sourcelikeToString(line) === "") { start = trimEnd(start); } - this.emitLine(start, line); - first = false; + + if (lineEnd) { + this.emitLine(start, line, lineEnd); + } else { + this.emitLine(start, line); + } } - if (afterLine !== undefined) { - this.emitLine(afterLine); + + if (afterComment !== undefined) { + this.emitLine(afterComment); } } @@ -845,10 +1203,14 @@ export abstract class ConvenienceRenderer extends Renderer { protected emitPropertyTable( c: ClassType, - makePropertyRow: (name: Name, jsonName: string, p: ClassProperty) => Sourcelike[] + makePropertyRow: ( + name: Name, + jsonName: string, + p: ClassProperty, + ) => Sourcelike[], ): void { let table: Sourcelike[][] = []; - const emitTable = () => { + const emitTable = (): void => { if (table.length === 0) return; this.emitTable(table); table = []; @@ -860,6 +1222,7 @@ export abstract class ConvenienceRenderer extends Renderer { emitTable(); this.emitDescription(description); } + table.push(makePropertyRow(name, jsonName, p)); }); emitTable(); @@ -868,22 +1231,32 @@ export abstract class ConvenienceRenderer extends Renderer { private processGraph(): void { this._declarationIR = declarationsForGraph( this.typeGraph, - this.needsTypeDeclarationBeforeUse ? t => this.canBeForwardDeclared(t) : undefined, - t => this.childrenOfType(t), - t => { + this.needsTypeDeclarationBeforeUse + ? (t): boolean => this.canBeForwardDeclared(t) + : undefined, + (t) => this.childrenOfType(t), + (t) => { if (t instanceof UnionType) { return this.unionNeedsName(t); } + return isNamedType(t); - } + }, ); const types = this.typeGraph.allTypesUnordered(); - this._haveUnions = iterableSome(types, t => t instanceof UnionType); - this._haveMaps = iterableSome(types, t => t instanceof MapType); - const classTypes = setFilter(types, t => t instanceof ClassType) as Set; - this._haveOptionalProperties = iterableSome(classTypes, c => mapSome(c.getProperties(), p => p.isOptional)); - this._namedTypes = this._declarationIR.declarations.filter(d => d.kind === "define").map(d => d.type); + this._haveUnions = iterableSome(types, (t) => t instanceof UnionType); + this._haveMaps = iterableSome(types, (t) => t instanceof MapType); + const classTypes = setFilter( + types, + (t) => t instanceof ClassType, + ) as Set; + this._haveOptionalProperties = iterableSome(classTypes, (c) => + mapSome(c.getProperties(), (p) => p.isOptional), + ); + this._namedTypes = this._declarationIR.declarations + .filter((d) => d.kind === "define") + .map((d) => d.type); const { objects, enums, unions } = separateNamedTypes(this._namedTypes); this._namedObjects = new Set(objects); this._namedEnums = new Set(enums); @@ -895,16 +1268,19 @@ export abstract class ConvenienceRenderer extends Renderer { this.emitSourceStructure(givenOutputFilename); } - protected forEachType(process: (t: Type) => TResult): Set { + protected forEachType( + process: (t: Type) => TResult, + ): Set { const visitedTypes = new Set(); const processed = new Set(); const queue = Array.from(this.typeGraph.topLevels.values()); - function visit(t: Type) { + function visit(t: Type): void { if (visitedTypes.has(t)) return; for (const c of t.getChildren()) { queue.push(c); } + visitedTypes.add(t); processed.add(process(t)); } @@ -914,6 +1290,7 @@ export abstract class ConvenienceRenderer extends Renderer { if (maybeType === undefined) { break; } + visit(maybeType); } diff --git a/packages/quicktype-core/src/CycleBreaker.ts b/packages/quicktype-core/src/CycleBreaker.ts index d3eba6321..818b25c38 100644 --- a/packages/quicktype-core/src/CycleBreaker.ts +++ b/packages/quicktype-core/src/CycleBreaker.ts @@ -1,18 +1,22 @@ import { assert, panic } from "./support/Support"; -export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: number[]) => [number, T]): [number, T][] { +export function breakCycles( + outEdges: number[][], + chooseBreaker: (cycle: number[]) => [number, T], +): Array<[number, T]> { const numNodes = outEdges.length; const inEdges: number[][] = []; const inDegree: number[] = []; const outDegree: number[] = []; const done: boolean[] = []; - const results: [number, T][] = []; + const results: Array<[number, T]> = []; for (let i = 0; i < numNodes; i++) { inEdges.push([]); inDegree.push(0); outDegree.push(outEdges[i].length); done.push(false); } + for (let i = 0; i < numNodes; i++) { for (const n of outEdges[i]) { inEdges[n].push(i); @@ -54,7 +58,11 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb done[i] = true; continue; } - assert(inDegree[i] === 0 || outDegree[i] === 0, "Can't have nodes in the worklist with in and out edges"); + + assert( + inDegree[i] === 0 || outDegree[i] === 0, + "Can't have nodes in the worklist with in and out edges", + ); removeNode(i); continue; @@ -78,10 +86,11 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb // We could count the number of reachable nodes for all nodes in the graph, // and then pick one of the nodes with the lowest number, which would pick // the dependee cycle. - const maybeEdge = outEdges[n].find(x => !done[x]); + const maybeEdge = outEdges[n].find((x) => !done[x]); if (maybeEdge === undefined) { return panic("Presumed cycle is not a cycle"); } + const maybeFirst = path.indexOf(maybeEdge); if (maybeFirst === undefined) { // No cycle yet, continue @@ -93,11 +102,12 @@ export function breakCycles(outEdges: number[][], chooseBreaker: (cycle: numb // We found a cycle - break it const cycle = path.slice(maybeFirst); const [breakNode, info] = chooseBreaker(cycle); - assert(cycle.indexOf(breakNode) >= 0, "Breaker chose an invalid node"); + assert(cycle.includes(breakNode), "Breaker chose an invalid node"); removeNode(breakNode); results.push([breakNode, info]); break; } + continue; } diff --git a/packages/quicktype-core/src/DateTime.ts b/packages/quicktype-core/src/DateTime.ts index 20d0340b8..7c2f4b049 100644 --- a/packages/quicktype-core/src/DateTime.ts +++ b/packages/quicktype-core/src/DateTime.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ // https://github.com/epoberezkin/ajv/blob/4d76c6fb813b136b6ec4fe74990bc97233d75dea/lib/compile/formats.js /* @@ -29,9 +30,9 @@ const DAYS = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; const TIME = /^(\d\d):(\d\d):(\d\d)(\.\d+)?(z|[+-]\d\d:\d\d)?$/i; export interface DateTimeRecognizer { - isDate(s: string): boolean; - isTime(s: string): boolean; - isDateTime(s: string): boolean; + isDate: (s: string) => boolean; + isDateTime: (s: string) => boolean; + isTime: (s: string) => boolean; } const DATE_TIME_SEPARATOR = /t|\s/i; @@ -39,7 +40,7 @@ const DATE_TIME_SEPARATOR = /t|\s/i; export class DefaultDateTimeRecognizer implements DateTimeRecognizer { isDate(str: string) { // full-date from http://tools.ietf.org/html/rfc3339#section-5.6 - const matches = str.match(DATE); + const matches = DATE.exec(str); if (matches === null) return false; const month = +matches[2]; @@ -48,7 +49,7 @@ export class DefaultDateTimeRecognizer implements DateTimeRecognizer { } isTime(str: string): boolean { - const matches = str.match(TIME); + const matches = TIME.exec(str); if (matches === null) return false; const hour = +matches[1]; @@ -60,6 +61,10 @@ export class DefaultDateTimeRecognizer implements DateTimeRecognizer { isDateTime(str: string): boolean { // http://tools.ietf.org/html/rfc3339#section-5.6 const dateTime = str.split(DATE_TIME_SEPARATOR); - return dateTime.length === 2 && this.isDate(dateTime[0]) && this.isTime(dateTime[1]); + return ( + dateTime.length === 2 && + this.isDate(dateTime[0]) && + this.isTime(dateTime[1]) + ); } } diff --git a/packages/quicktype-core/src/DeclarationIR.ts b/packages/quicktype-core/src/DeclarationIR.ts index 8b36dbd51..8ee30c34f 100644 --- a/packages/quicktype-core/src/DeclarationIR.ts +++ b/packages/quicktype-core/src/DeclarationIR.ts @@ -1,10 +1,16 @@ -import { setUnionInto, setFilter, iterableFirst, setSubtract, setIntersect } from "collection-utils"; +import { + iterableFirst, + setFilter, + setIntersect, + setSubtract, + setUnionInto, +} from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Type } from "./Type"; -import { panic, defined, assert } from "./support/Support"; import { Graph } from "./Graph"; import { messageError } from "./Messages"; +import { assert, defined, panic } from "./support/Support"; +import type { Type } from "./Type/Type"; +import type { TypeGraph } from "./Type/TypeGraph"; export type DeclarationKind = "forward" | "define"; @@ -14,35 +20,40 @@ export interface Declaration { } export class DeclarationIR { - readonly declarations: ReadonlyArray; + public readonly declarations: readonly Declaration[]; - constructor(declarations: Iterable, readonly forwardedTypes: Set) { + public constructor( + declarations: Iterable, + public readonly forwardedTypes: Set, + ) { this.declarations = Array.from(declarations); } } function findBreaker( t: Type, - path: ReadonlyArray, - canBreak: ((t: Type) => boolean) | undefined + path: readonly Type[], + canBreak: ((t: Type) => boolean) | undefined, ): Type | undefined { const index = path.indexOf(t); if (index < 0) return undefined; if (canBreak === undefined) { return path[index]; } + const potentialBreakers = path.slice(0, index + 1).reverse(); const maybeBreaker = potentialBreakers.find(canBreak); if (maybeBreaker === undefined) { return panic("Found a cycle that cannot be broken"); } + return maybeBreaker; } export function cycleBreakerTypesForGraph( graph: TypeGraph, isImplicitCycleBreaker: (t: Type) => boolean, - canBreakCycles: (t: Type) => boolean + canBreakCycles: (t: Type) => boolean, ): Set { const visitedTypes = new Set(); const cycleBreakerTypes = new Set(); @@ -87,7 +98,7 @@ export function declarationsForGraph( typeGraph: TypeGraph, canBeForwardDeclared: ((t: Type) => boolean) | undefined, childrenOfType: (t: Type) => ReadonlySet, - needsDeclaration: (t: Type) => boolean + needsDeclaration: (t: Type) => boolean, ): DeclarationIR { /* function nodeTitle(t: Type): string { @@ -121,7 +132,10 @@ export function declarationsForGraph( // 1. Only one node in the cycle needs a declaration, in which // case it's the breaker, and no forward declaration is necessary. if (declarationNeeded.size === 1) { - declarations.push({ kind: "define", type: defined(iterableFirst(declarationNeeded)) }); + declarations.push({ + kind: "define", + type: defined(iterableFirst(declarationNeeded)), + }); return; } @@ -136,7 +150,10 @@ export function declarationsForGraph( // declaration, so we can pick any one. This is not a forward // declaration, either. if (declarationNeeded.size === 0) { - declarations.push({ kind: "define", type: defined(iterableFirst(component)) }); + declarations.push({ + kind: "define", + type: defined(iterableFirst(component)), + }); return; } @@ -147,6 +164,7 @@ export function declarationsForGraph( for (const t of declarationNeeded) { declarations.push({ kind: "define", type: t }); } + return; } @@ -156,20 +174,28 @@ export function declarationsForGraph( // there are none, we're stuck. If there are, we take them out of // the component and try the whole thing again recursively. Then // we declare the types we previously forward-declared. - const forwardDeclarable = setFilter(component, canBeForwardDeclared); + const forwardDeclarable = setFilter( + component, + canBeForwardDeclared, + ); if (forwardDeclarable.size === 0) { - return messageError("IRNoForwardDeclarableTypeInCycle", {}); + messageError("IRNoForwardDeclarableTypeInCycle", {}); } + for (const t of forwardDeclarable) { declarations.push({ kind: "forward", type: t }); } + setUnionInto(forwardedTypes, forwardDeclarable); const rest = setSubtract(component, forwardDeclarable); - const restGraph = new Graph(rest, true, t => setIntersect(childrenOfType(t), rest)); + const restGraph = new Graph(rest, true, (t) => + setIntersect(childrenOfType(t), rest), + ); processGraph(restGraph, false); for (const t of forwardDeclarable) { declarations.push({ kind: "define", type: t }); } + return; } diff --git a/packages/quicktype-core/src/GatherNames.ts b/packages/quicktype-core/src/GatherNames.ts index 40d1f4b05..c99da4bfb 100644 --- a/packages/quicktype-core/src/GatherNames.ts +++ b/packages/quicktype-core/src/GatherNames.ts @@ -1,38 +1,46 @@ +import { setMap, setSortBy, setUnion } from "collection-utils"; import * as pluralize from "pluralize"; -import { setUnion, setMap, setSortBy } from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Type, ObjectType } from "./Type"; -import { matchCompoundType, nullableFromUnion } from "./TypeUtils"; -import { TypeNames, namesTypeAttributeKind, TooManyTypeNames, tooManyNamesThreshold } from "./attributes/TypeNames"; -import { defined, panic, assert } from "./support/Support"; +import { + TooManyTypeNames, + TypeNames, + namesTypeAttributeKind, + tooManyNamesThreshold, +} from "./attributes/TypeNames"; +import { assert, defined, panic } from "./support/Support"; import { transformationForType } from "./Transformers"; +import { ObjectType, type Type } from "./Type/Type"; +import type { TypeGraph } from "./Type/TypeGraph"; +import { matchCompoundType, nullableFromUnion } from "./Type/TypeUtils"; class UniqueQueue { private readonly _present = new Set(); - private _queue: (T | undefined)[] = []; + + private _queue: Array = []; + private _front = 0; - get size(): number { + public get size(): number { return this._queue.length - this._front; } - get isEmpty(): boolean { + public get isEmpty(): boolean { return this.size <= 0; } - push(v: T): void { + public push(v: T): void { if (this._present.has(v)) return; this._queue.push(v); this._present.add(v); } - unshift(): T { + public unshift(): T { assert(!this.isEmpty, "Trying to unshift from an empty queue"); const v = this._queue[this._front]; if (v === undefined) { return panic("Value should have been present in queue"); } + this._queue[this._front] = undefined; this._front += 1; this._present.delete(v); @@ -82,7 +90,11 @@ class UniqueQueue { // step 1, and its alternatives to a union of its direct and ancestor // alternatives, gathered in steps 2 and 3. -export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: boolean): void { +export function gatherNames( + graph: TypeGraph, + destructive: boolean, + debugPrint: boolean, +): void { function setNames(t: Type, tn: TypeNames): void { graph.attributeStore.set(namesTypeAttributeKind, t, tn); } @@ -99,7 +111,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: // null means there are too many const namesForType = new Map | null>(); - function addNames(t: Type, names: ReadonlySet | null) { + function addNames(t: Type, names: ReadonlySet | null): void { // Always use the type's given names if it has some if (t.hasNames) { const originalNames = t.getNames(); @@ -123,6 +135,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (newNames !== null && newNames.size >= tooManyNamesThreshold) { newNames = null; } + namesForType.set(t, newNames); const transformation = transformationForType(t); @@ -157,23 +170,34 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: const values = t.getAdditionalProperties(); if (values !== undefined) { - addNames(values, names === null ? null : setMap(names, pluralize.singular)); + addNames( + values, + names === null ? null : setMap(names, pluralize.singular), + ); } } else { matchCompoundType( t, - arrayType => { - addNames(arrayType.items, names === null ? null : setMap(names, pluralize.singular)); + (arrayType) => { + addNames( + arrayType.items, + names === null + ? null + : setMap(names, pluralize.singular), + ); }, - _classType => panic("We handled this above"), - _mapType => panic("We handled this above"), - _objectType => panic("We handled this above"), - unionType => { - const members = setSortBy(unionType.members, member => member.kind); + (_classType) => panic("We handled this above"), + (_mapType) => panic("We handled this above"), + (_objectType) => panic("We handled this above"), + (unionType) => { + const members = setSortBy( + unionType.members, + (member) => member.kind, + ); for (const memberType of members) { addNames(memberType, names); } - } + }, ); } } @@ -184,18 +208,26 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (names === undefined) return; const index = t.index; - console.log(`${index}: ${names === null ? "*** too many ***" : Array.from(names).join(" ")}`); + console.log( + `${index}: ${names === null ? "*** too many ***" : Array.from(names).join(" ")}`, + ); } } // null means there are too many - const directAlternativesForType = new Map | null>(); - const ancestorAlternativesForType = new Map | null>(); + const directAlternativesForType = new Map< + Type, + ReadonlySet | null + >(); + const ancestorAlternativesForType = new Map< + Type, + ReadonlySet | null + >(); const pairsProcessed = new Map>(); function addAlternatives( existing: ReadonlySet | undefined, - alternatives: string[] + alternatives: string[], ): ReadonlySet | undefined | null { if (alternatives.length === 0) { return existing; @@ -204,14 +236,20 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (existing === undefined) { existing = new Set(); } + existing = setUnion(existing, alternatives); if (existing.size < tooManyNamesThreshold) { return existing; } + return null; } - function processType(ancestor: Type | undefined, t: Type, alternativeSuffix: string | undefined) { + function processType( + ancestor: Type | undefined, + t: Type, + alternativeSuffix: string | undefined, + ): void { const names = defined(namesForType.get(t)); let processedEntry = pairsProcessed.get(ancestor); @@ -238,31 +276,49 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: } else if (ancestorNames !== undefined) { const alternatives: string[] = []; for (const name of names) { - alternatives.push(...Array.from(ancestorNames).map(an => `${an}_${name}`)); + alternatives.push( + ...Array.from(ancestorNames).map( + (an) => `${an}_${name}`, + ), + ); // FIXME: add alternatives with the suffix here, too? - alternatives.push(...Array.from(ancestorNames).map(an => `${an}_${name}_${t.kind}`)); + alternatives.push( + ...Array.from(ancestorNames).map( + (an) => `${an}_${name}_${t.kind}`, + ), + ); // FIXME: add alternatives with the suffix here, too? } - ancestorAlternatives = addAlternatives(ancestorAlternatives, alternatives); + ancestorAlternatives = addAlternatives( + ancestorAlternatives, + alternatives, + ); } } - if (alternativeSuffix !== undefined && directAlternatives !== null) { + if ( + alternativeSuffix !== undefined && + directAlternatives !== null + ) { const alternatives: string[] = []; for (const name of names) { // FIXME: we should only add these for names we couldn't singularize alternatives.push(`${name}_${alternativeSuffix}`); } - directAlternatives = addAlternatives(directAlternatives, alternatives); + directAlternatives = addAlternatives( + directAlternatives, + alternatives, + ); } } if (ancestorAlternatives !== undefined) { ancestorAlternativesForType.set(t, ancestorAlternatives); } + if (directAlternatives !== undefined) { directAlternativesForType.set(t, directAlternatives); } @@ -275,26 +331,38 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: const values = t.getAdditionalProperties(); if (values !== undefined) { - processType(properties.size === 0 ? ancestor : t, values, "value"); + processType( + properties.size === 0 ? ancestor : t, + values, + "value", + ); } } else { matchCompoundType( t, - arrayType => { + (arrayType) => { processType(ancestor, arrayType.items, "element"); }, - _classType => panic("We handled this above"), - _mapType => panic("We handled this above"), - _objectType => panic("We handled this above"), - unionType => { - const members = setSortBy(unionType.members, member => member.kind); - const unionHasGivenName = unionType.hasNames && !unionType.getNames().areInferred; - const unionIsAncestor = unionHasGivenName || nullableFromUnion(unionType) === null; - const ancestorForMembers = unionIsAncestor ? unionType : ancestor; + (_classType) => panic("We handled this above"), + (_mapType) => panic("We handled this above"), + (_objectType) => panic("We handled this above"), + (unionType) => { + const members = setSortBy( + unionType.members, + (member) => member.kind, + ); + const unionHasGivenName = + unionType.hasNames && !unionType.getNames().areInferred; + const unionIsAncestor = + unionHasGivenName || + nullableFromUnion(unionType) === null; + const ancestorForMembers = unionIsAncestor + ? unionType + : ancestor; for (const memberType of members) { processType(ancestorForMembers, memberType, undefined); } - } + }, ); } } @@ -310,6 +378,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: directAlternativesForType.set(t, null); continue; } + let alternatives = directAlternativesForType.get(t); if (alternatives === null) continue; if (alternatives === undefined) { @@ -318,7 +387,7 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: alternatives = setUnion( alternatives, - setMap(names, name => `${name}_${t.kind}`) + setMap(names, (name) => `${name}_${t.kind}`), ); directAlternativesForType.set(t, alternatives); } @@ -338,17 +407,28 @@ export function gatherNames(graph: TypeGraph, destructive: boolean, debugPrint: if (ancestorAlternatives === null && directAlternatives === null) { alternatives = undefined; } else { - if (directAlternatives !== null && directAlternatives !== undefined) { + if ( + directAlternatives !== null && + directAlternatives !== undefined + ) { alternatives = directAlternatives; } else { alternatives = new Set(); } - if (ancestorAlternatives !== null && ancestorAlternatives !== undefined) { + + if ( + ancestorAlternatives !== null && + ancestorAlternatives !== undefined + ) { alternatives = setUnion(alternatives, ancestorAlternatives); } } - typeNames = TypeNames.makeWithDistance(names, alternatives, destructive ? 1 : 10); + typeNames = TypeNames.makeWithDistance( + names, + alternatives, + destructive ? 1 : 10, + ); } setNames(t, t.hasNames ? t.getNames().add([typeNames]) : typeNames); diff --git a/packages/quicktype-core/src/Graph.ts b/packages/quicktype-core/src/Graph.ts index fcff0a56a..16690398e 100644 --- a/packages/quicktype-core/src/Graph.ts +++ b/packages/quicktype-core/src/Graph.ts @@ -1,6 +1,6 @@ import { setMap } from "collection-utils"; -import { defined, repeated, assert, repeatedCall } from "./support/Support"; +import { assert, defined, repeated, repeatedCall } from "./support/Support"; function countComponentGraphNodes(components: number[][]): number { if (components.length === 0) return 0; @@ -64,6 +64,7 @@ function stronglyConnectedComponents(successors: number[][]): number[][] { onStack[w] = false; scc.push(w); } while (w !== v); + sccs.push(scc); } } @@ -74,28 +75,44 @@ function stronglyConnectedComponents(successors: number[][]): number[][] { } } - assert(countComponentGraphNodes(sccs) === numNodes, "We didn't put all the nodes into SCCs"); + assert( + countComponentGraphNodes(sccs) === numNodes, + "We didn't put all the nodes into SCCs", + ); return sccs; } -function buildComponentOfNodeMap(successors: number[][], components: number[][]): number[] { +function buildComponentOfNodeMap( + successors: number[][], + components: number[][], +): number[] { const numComponents = components.length; const numNodes = successors.length; - assert(numNodes === countComponentGraphNodes(components), "Components don't match up with graph"); + assert( + numNodes === countComponentGraphNodes(components), + "Components don't match up with graph", + ); const componentOfNode: number[] = repeated(numNodes, -1); for (let c = 0; c < numComponents; c++) { for (const n of components[c]) { - assert(componentOfNode[n] < 0, "We have a node that's in two components"); + assert( + componentOfNode[n] < 0, + "We have a node that's in two components", + ); componentOfNode[n] = c; } } + return componentOfNode; } -function buildMetaSuccessors(successors: number[][], components: number[][]): number[][] { +function buildMetaSuccessors( + successors: number[][], + components: number[][], +): number[][] { const numComponents = components.length; const componentOfNode = buildComponentOfNodeMap(successors, components); const componentAdded: boolean[] = repeated(numComponents, false); @@ -166,41 +183,58 @@ function findRoots(successors: number[][]): number[] { } export class Graph { - private readonly _nodes: ReadonlyArray; + private readonly _nodes: readonly T[]; + private readonly _indexByNode: ReadonlyMap; + private readonly _successors: number[][]; - constructor(nodes: Iterable, invertDirection: boolean, edges: number[][] | ((node: T) => ReadonlySet)) { + public constructor( + nodes: Iterable, + invertDirection: boolean, + edges: number[][] | ((node: T) => ReadonlySet), + ) { this._nodes = Array.from(nodes); - this._indexByNode = new Map(this._nodes.map((n, i): [T, number] => [n, i])); + this._indexByNode = new Map( + this._nodes.map((n, i): [T, number] => [n, i]), + ); let edgesArray: number[][]; if (Array.isArray(edges)) { edgesArray = edges; } else { - edgesArray = this._nodes.map(n => Array.from(edges(n)).map(s => defined(this._indexByNode.get(s)))); + edgesArray = this._nodes.map((n) => + Array.from(edges(n)).map((s) => + defined(this._indexByNode.get(s)), + ), + ); } if (invertDirection) { edgesArray = invertEdges(edgesArray); } + this._successors = edgesArray; } - get size(): number { + public get size(): number { return this._nodes.length; } - get nodes(): ReadonlyArray { + public get nodes(): readonly T[] { return this._nodes; } - findRoots(): ReadonlySet { + public findRoots(): ReadonlySet { const roots = findRoots(this._successors); - return new Set(roots.map(n => this._nodes[n])); + return new Set(roots.map((n) => this._nodes[n])); } // The subgraph starting at `root` must be acyclic. - dfsTraversal(root: T, preOrder: boolean, process: (node: T) => void): void { + public dfsTraversal( + root: T, + preOrder: boolean, + process: (node: T) => void, + ): void { const visited = repeated(this.size, false); const visit = (v: number): void => { @@ -223,17 +257,23 @@ export class Graph { visit(defined(this._indexByNode.get(root))); } - stronglyConnectedComponents(): Graph> { + public stronglyConnectedComponents(): Graph> { const components = stronglyConnectedComponents(this._successors); - const componentSuccessors = buildMetaSuccessors(this._successors, components); + const componentSuccessors = buildMetaSuccessors( + this._successors, + components, + ); return new Graph( - components.map(ns => setMap(ns, n => this._nodes[n])), + components.map((ns) => setMap(ns, (n) => this._nodes[n])), false, - componentSuccessors + componentSuccessors, ); } - makeDot(includeNode: (n: T) => boolean, nodeLabel: (n: T) => string): string { + public makeDot( + includeNode: (n: T) => boolean, + nodeLabel: (n: T) => string, + ): string { const lines: string[] = []; lines.push("digraph G {"); lines.push(" ordering = out;"); diff --git a/packages/quicktype-core/src/GraphRewriting.ts b/packages/quicktype-core/src/GraphRewriting.ts index b3610ad80..71cb44a8a 100644 --- a/packages/quicktype-core/src/GraphRewriting.ts +++ b/packages/quicktype-core/src/GraphRewriting.ts @@ -1,35 +1,53 @@ -import { mapMap, EqualityMap } from "collection-utils"; +import { EqualityMap, mapMap } from "collection-utils"; -import { PrimitiveTypeKind, Type, ClassProperty, MaybeTypeIdentity } from "./Type"; -import { combineTypeAttributesOfTypes } from "./TypeUtils"; import { - TypeGraph, - TypeRef, + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, +} from "./attributes/TypeAttributes"; +import { assert, indentationString, panic } from "./support/Support"; +import type { + ClassProperty, + MaybeTypeIdentity, + PrimitiveTypeKind, + Type, +} from "./Type"; +import { TypeBuilder } from "./Type/TypeBuilder"; +import type { StringTypeMapping } from "./Type/TypeBuilderUtils"; +import type { TypeGraph } from "./Type/TypeGraph"; +import { + type TypeRef, + assertTypeRefGraph, derefTypeRef, + isTypeRef, typeAndAttributesForTypeRef, - assertTypeRefGraph, typeRefIndex, - isTypeRef -} from "./TypeGraph"; -import { TypeAttributes, emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; -import { assert, panic, indentationString } from "./support/Support"; -import { TypeBuilder, StringTypeMapping } from "./TypeBuilder"; +} from "./Type/TypeRef"; +import { combineTypeAttributesOfTypes } from "./Type/TypeUtils"; export interface TypeLookerUp { - lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined; - reconstituteTypeRef(typeRef: TypeRef, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef; + lookupTypeRefs: ( + typeRefs: TypeRef[], + forwardingRef?: TypeRef, + ) => TypeRef | undefined; + reconstituteTypeRef: ( + typeRef: TypeRef, + attributes?: TypeAttributes, + forwardingRef?: TypeRef, + ) => TypeRef; } export class TypeReconstituter { private _wasUsed = false; + private _typeRef: TypeRef | undefined = undefined; - constructor( + public constructor( private readonly _typeBuilder: TBuilder, private readonly _makeClassUnique: boolean, private readonly _typeAttributes: TypeAttributes, private readonly _forwardingRef: TypeRef | undefined, - private readonly _register: (tref: TypeRef) => void + private readonly _register: (tref: TypeRef) => void, ) {} private builderForNewType(): TBuilder { @@ -39,14 +57,18 @@ export class TypeReconstituter { } private builderForSetting(): TBuilder { - assert(this._wasUsed && this._typeRef !== undefined, "Can't set type members before constructing a type"); + assert( + this._wasUsed && this._typeRef !== undefined, + "Can't set type members before constructing a type", + ); return this._typeBuilder; } - getResult(): TypeRef { + public getResult(): TypeRef { if (this._typeRef === undefined) { return panic("Type was not reconstituted"); } + return this._typeRef; } @@ -62,176 +84,282 @@ export class TypeReconstituter { this.register(tref); } - lookup(tref: TypeRef): TypeRef | undefined; - lookup(trefs: Iterable): ReadonlyArray | undefined; - lookup(trefs: TypeRef | Iterable): TypeRef | ReadonlyArray | undefined { - assert(!this._wasUsed, "Cannot lookup constituents after building type"); + public lookup(tref: TypeRef): TypeRef | undefined; + public lookup(trefs: Iterable): readonly TypeRef[] | undefined; + public lookup( + trefs: TypeRef | Iterable, + ): TypeRef | readonly TypeRef[] | undefined { + assert( + !this._wasUsed, + "Cannot lookup constituents after building type", + ); if (isTypeRef(trefs)) { return this._typeBuilder.lookupTypeRefs([trefs], undefined, false); - } else { - const maybeRefs = Array.from(trefs).map(tref => this._typeBuilder.lookupTypeRefs([tref], undefined, false)); - if (maybeRefs.some(tref => tref === undefined)) return undefined; - return maybeRefs as ReadonlyArray; } + + const maybeRefs = Array.from(trefs).map((tref) => + this._typeBuilder.lookupTypeRefs([tref], undefined, false), + ); + if (maybeRefs.some((tref) => tref === undefined)) { + return undefined; + } + + return maybeRefs as readonly TypeRef[]; } - lookupMap(trefs: ReadonlyMap): ReadonlyMap | undefined { + public lookupMap( + trefs: ReadonlyMap, + ): ReadonlyMap | undefined { const resultValues = this.lookup(trefs.values()); if (resultValues === undefined) return undefined; - assert(resultValues.length === trefs.size, "Didn't get back the correct number of types"); + assert( + resultValues.length === trefs.size, + "Didn't get back the correct number of types", + ); const result = new Map(); let i = 0; for (const k of trefs.keys()) { result.set(k, resultValues[i]); i += 1; } + return result; } - reconstitute(tref: TypeRef): TypeRef; - reconstitute(trefs: Iterable): ReadonlyArray; - reconstitute(trefs: TypeRef | Iterable): TypeRef | ReadonlyArray { - assert(this._wasUsed, "Cannot reconstitute constituents before building type"); + public reconstitute(tref: TypeRef): TypeRef; + public reconstitute(trefs: Iterable): readonly TypeRef[]; + public reconstitute( + trefs: TypeRef | Iterable, + ): TypeRef | readonly TypeRef[] { + assert( + this._wasUsed, + "Cannot reconstitute constituents before building type", + ); if (isTypeRef(trefs)) { return this._typeBuilder.reconstituteTypeRef(trefs); - } else { - return Array.from(trefs).map(tref => this._typeBuilder.reconstituteTypeRef(tref)); } + + return Array.from(trefs).map((tref) => + this._typeBuilder.reconstituteTypeRef(tref), + ); } - reconstituteMap(trefs: ReadonlyMap): ReadonlyMap { - return mapMap(trefs, tref => this._typeBuilder.reconstituteTypeRef(tref)); + public reconstituteMap( + trefs: ReadonlyMap, + ): ReadonlyMap { + return mapMap(trefs, (tref) => + this._typeBuilder.reconstituteTypeRef(tref), + ); } - getPrimitiveType(kind: PrimitiveTypeKind): void { - this.register(this.builderForNewType().getPrimitiveType(kind, this._typeAttributes, this._forwardingRef)); + public getPrimitiveType(kind: PrimitiveTypeKind): void { + this.register( + this.builderForNewType().getPrimitiveType( + kind, + this._typeAttributes, + this._forwardingRef, + ), + ); } - getEnumType(cases: ReadonlySet): void { - this.register(this.builderForNewType().getEnumType(this._typeAttributes, cases, this._forwardingRef)); + public getEnumType(cases: ReadonlySet): void { + this.register( + this.builderForNewType().getEnumType( + this._typeAttributes, + cases, + this._forwardingRef, + ), + ); } - getUniqueMapType(): void { - this.registerAndAddAttributes(this.builderForNewType().getUniqueMapType(this._forwardingRef)); + public getUniqueMapType(): void { + this.registerAndAddAttributes( + this.builderForNewType().getUniqueMapType(this._forwardingRef), + ); } - getMapType(values: TypeRef): void { - this.register(this.builderForNewType().getMapType(this._typeAttributes, values, this._forwardingRef)); + public getMapType(values: TypeRef): void { + this.register( + this.builderForNewType().getMapType( + this._typeAttributes, + values, + this._forwardingRef, + ), + ); } - getUniqueArrayType(): void { - this.registerAndAddAttributes(this.builderForNewType().getUniqueArrayType(this._forwardingRef)); + public getUniqueArrayType(): void { + this.registerAndAddAttributes( + this.builderForNewType().getUniqueArrayType(this._forwardingRef), + ); } - getArrayType(items: TypeRef): void { - this.register(this.builderForNewType().getArrayType(this._typeAttributes, items, this._forwardingRef)); + public getArrayType(items: TypeRef): void { + this.register( + this.builderForNewType().getArrayType( + this._typeAttributes, + items, + this._forwardingRef, + ), + ); } - setArrayItems(items: TypeRef): void { + public setArrayItems(items: TypeRef): void { this.builderForSetting().setArrayItems(this.getResult(), items); } - makeClassProperty(tref: TypeRef, isOptional: boolean): ClassProperty { + public makeClassProperty( + tref: TypeRef, + isOptional: boolean, + ): ClassProperty { return this._typeBuilder.makeClassProperty(tref, isOptional); } - getObjectType(properties: ReadonlyMap, additionalProperties: TypeRef | undefined): void { + public getObjectType( + properties: ReadonlyMap, + additionalProperties: TypeRef | undefined, + ): void { this.register( this.builderForNewType().getUniqueObjectType( this._typeAttributes, properties, additionalProperties, - this._forwardingRef - ) + this._forwardingRef, + ), ); } - getUniqueObjectType( + public getUniqueObjectType( properties: ReadonlyMap | undefined, - additionalProperties: TypeRef | undefined + additionalProperties: TypeRef | undefined, ): void { this.register( this.builderForNewType().getUniqueObjectType( this._typeAttributes, properties, additionalProperties, - this._forwardingRef - ) + this._forwardingRef, + ), ); } - getClassType(properties: ReadonlyMap): void { + public getClassType(properties: ReadonlyMap): void { if (this._makeClassUnique) { this.getUniqueClassType(false, properties); return; } - this.register(this.builderForNewType().getClassType(this._typeAttributes, properties, this._forwardingRef)); + + this.register( + this.builderForNewType().getClassType( + this._typeAttributes, + properties, + this._forwardingRef, + ), + ); } - getUniqueClassType(isFixed: boolean, properties: ReadonlyMap | undefined): void { + public getUniqueClassType( + isFixed: boolean, + properties: ReadonlyMap | undefined, + ): void { this.register( - this.builderForNewType().getUniqueClassType(this._typeAttributes, isFixed, properties, this._forwardingRef) + this.builderForNewType().getUniqueClassType( + this._typeAttributes, + isFixed, + properties, + this._forwardingRef, + ), ); } - setObjectProperties( + public setObjectProperties( properties: ReadonlyMap, - additionalProperties: TypeRef | undefined + additionalProperties: TypeRef | undefined, ): void { - this.builderForSetting().setObjectProperties(this.getResult(), properties, additionalProperties); + this.builderForSetting().setObjectProperties( + this.getResult(), + properties, + additionalProperties, + ); } - getUnionType(members: ReadonlySet): void { - this.register(this.builderForNewType().getUnionType(this._typeAttributes, members, this._forwardingRef)); + public getUnionType(members: ReadonlySet): void { + this.register( + this.builderForNewType().getUnionType( + this._typeAttributes, + members, + this._forwardingRef, + ), + ); } - getUniqueUnionType(): void { + public getUniqueUnionType(): void { this.register( - this.builderForNewType().getUniqueUnionType(this._typeAttributes, undefined, this._forwardingRef) + this.builderForNewType().getUniqueUnionType( + this._typeAttributes, + undefined, + this._forwardingRef, + ), ); } - getIntersectionType(members: ReadonlySet): void { - this.register(this.builderForNewType().getIntersectionType(this._typeAttributes, members, this._forwardingRef)); + public getIntersectionType(members: ReadonlySet): void { + this.register( + this.builderForNewType().getIntersectionType( + this._typeAttributes, + members, + this._forwardingRef, + ), + ); } - getUniqueIntersectionType(members?: ReadonlySet): void { + public getUniqueIntersectionType(members?: ReadonlySet): void { this.register( - this.builderForNewType().getUniqueIntersectionType(this._typeAttributes, members, this._forwardingRef) + this.builderForNewType().getUniqueIntersectionType( + this._typeAttributes, + members, + this._forwardingRef, + ), ); } - setSetOperationMembers(members: ReadonlySet): void { - this.builderForSetting().setSetOperationMembers(this.getResult(), members); + public setSetOperationMembers(members: ReadonlySet): void { + this.builderForSetting().setSetOperationMembers( + this.getResult(), + members, + ); } } -export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements TypeLookerUp { +export abstract class BaseGraphRewriteBuilder + extends TypeBuilder + implements TypeLookerUp +{ protected readonly reconstitutedTypes: Map = new Map(); private _lostTypeAttributes = false; + private _printIndent = 0; - constructor( - readonly originalGraph: TypeGraph, + public constructor( + public readonly originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, - protected readonly debugPrint: boolean + protected readonly debugPrint: boolean, ) { super( - originalGraph.serial + 1, stringTypeMapping, alphabetizeProperties, false, false, - graphHasProvenanceAttributes + graphHasProvenanceAttributes, ); } - withForwardingRef( + public withForwardingRef( maybeForwardingRef: TypeRef | undefined, - typeCreator: (forwardingRef: TypeRef) => TypeRef + typeCreator: (forwardingRef: TypeRef) => TypeRef, ): TypeRef { if (maybeForwardingRef !== undefined) { return typeCreator(maybeForwardingRef); @@ -239,41 +367,71 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ const forwardingRef = this.reserveTypeRef(); const actualRef = typeCreator(forwardingRef); - assert(actualRef === forwardingRef, "Type creator didn't return its forwarding ref"); + assert( + actualRef === forwardingRef, + "Type creator didn't return its forwarding ref", + ); return actualRef; } - reconstituteType(t: Type, attributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { + public reconstituteType( + t: Type, + attributes?: TypeAttributes, + forwardingRef?: TypeRef, + ): TypeRef { return this.reconstituteTypeRef(t.typeRef, attributes, forwardingRef); } - abstract lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet?: boolean): TypeRef | undefined; + public abstract lookupTypeRefs( + typeRefs: TypeRef[], + forwardingRef?: TypeRef, + replaceSet?: boolean, + ): TypeRef | undefined; protected abstract forceReconstituteTypeRef( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef; - reconstituteTypeRef(originalRef: TypeRef, attributes?: TypeAttributes, maybeForwardingRef?: TypeRef): TypeRef { + public reconstituteTypeRef( + originalRef: TypeRef, + attributes?: TypeAttributes, + maybeForwardingRef?: TypeRef, + ): TypeRef { const maybeRef = this.lookupTypeRefs([originalRef], maybeForwardingRef); if (maybeRef !== undefined) { if (attributes !== undefined) { this.addAttributes(maybeRef, attributes); } + return maybeRef; } - return this.forceReconstituteTypeRef(originalRef, attributes, maybeForwardingRef); + + return this.forceReconstituteTypeRef( + originalRef, + attributes, + maybeForwardingRef, + ); } - reconstituteTypeAttributes(attributes: TypeAttributes): TypeAttributes { + public reconstituteTypeAttributes( + attributes: TypeAttributes, + ): TypeAttributes { return mapMap(attributes, (v, a) => a.reconstitute(this, v)); } - protected assertTypeRefsToReconstitute(typeRefs: TypeRef[], forwardingRef?: TypeRef): void { - assert(typeRefs.length > 0, "Must have at least one type to reconstitute"); + protected assertTypeRefsToReconstitute( + typeRefs: TypeRef[], + forwardingRef?: TypeRef, + ): void { + assert( + typeRefs.length > 0, + "Must have at least one type to reconstitute", + ); for (const originalRef of typeRefs) { assertTypeRefGraph(originalRef, this.originalGraph); } + if (forwardingRef !== undefined) { assertTypeRefGraph(forwardingRef, this.typeGraph); } @@ -287,18 +445,19 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ return indentationString(this._printIndent); } - finish(): TypeGraph { + public finish(): TypeGraph { for (const [name, t] of this.originalGraph.topLevels) { this.addTopLevel(name, this.reconstituteType(t)); } + return super.finish(); } - setLostTypeAttributes(): void { + public setLostTypeAttributes(): void { this._lostTypeAttributes = true; } - get lostTypeAttributes(): boolean { + public get lostTypeAttributes(): boolean { return this._lostTypeAttributes; } } @@ -306,20 +465,20 @@ export abstract class BaseGraphRewriteBuilder extends TypeBuilder implements Typ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { private readonly _attributeSources: Map = new Map(); - constructor( + public constructor( originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, graphHasProvenanceAttributes: boolean, private readonly _map: ReadonlyMap, - debugPrintRemapping: boolean + debugPrintRemapping: boolean, ) { super( originalGraph, stringTypeMapping, alphabetizeProperties, graphHasProvenanceAttributes, - debugPrintRemapping + debugPrintRemapping, ); for (const [source, target] of _map) { @@ -328,6 +487,7 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { maybeSources = [target]; this._attributeSources.set(target, maybeSources); } + maybeSources.push(source); } } @@ -339,24 +499,42 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { private getMapTarget(tref: TypeRef): TypeRef { const maybeType = this._map.get(derefTypeRef(tref, this.originalGraph)); if (maybeType === undefined) return tref; - assert(this._map.get(maybeType) === undefined, "We have a type that's remapped to a remapped type"); + assert( + this._map.get(maybeType) === undefined, + "We have a type that's remapped to a remapped type", + ); return maybeType.typeRef; } - protected addForwardingIntersection(_forwardingRef: TypeRef, _tref: TypeRef): TypeRef { - return panic("We can't add forwarding intersections when we're removing forwarding intersections"); + protected addForwardingIntersection( + _forwardingRef: TypeRef, + _tref: TypeRef, + ): TypeRef { + return panic( + "We can't add forwarding intersections when we're removing forwarding intersections", + ); } - lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef): TypeRef | undefined { - assert(forwardingRef === undefined, "We can't have a forwarding ref when we remap"); + public lookupTypeRefs( + typeRefs: TypeRef[], + forwardingRef?: TypeRef, + ): TypeRef | undefined { + assert( + forwardingRef === undefined, + "We can't have a forwarding ref when we remap", + ); this.assertTypeRefsToReconstitute(typeRefs, forwardingRef); - const first = this.reconstitutedTypes.get(typeRefIndex(this.getMapTarget(typeRefs[0]))); + const first = this.reconstitutedTypes.get( + typeRefIndex(this.getMapTarget(typeRefs[0])), + ); if (first === undefined) return undefined; for (let i = 1; i < typeRefs.length; i++) { - const other = this.reconstitutedTypes.get(typeRefIndex(this.getMapTarget(typeRefs[i]))); + const other = this.reconstitutedTypes.get( + typeRefIndex(this.getMapTarget(typeRefs[i])), + ); if (first !== other) return undefined; } @@ -366,42 +544,55 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { protected forceReconstituteTypeRef( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef { originalRef = this.getMapTarget(originalRef); const index = typeRefIndex(originalRef); - assert(this.reconstitutedTypes.get(index) === undefined, "Type has already been reconstituted"); + assert( + this.reconstitutedTypes.get(index) === undefined, + "Type has already been reconstituted", + ); - assert(maybeForwardingRef === undefined, "We can't have a forwarding ref when we remap"); + assert( + maybeForwardingRef === undefined, + "We can't have a forwarding ref when we remap", + ); - return this.withForwardingRef(undefined, forwardingRef => { + return this.withForwardingRef(undefined, (forwardingRef) => { this.reconstitutedTypes.set(index, forwardingRef); if (this.debugPrint) { - console.log(`${this.debugPrintIndentation}reconstituting ${index} as ${typeRefIndex(forwardingRef)}`); + console.log( + `${this.debugPrintIndentation}reconstituting ${index} as ${typeRefIndex(forwardingRef)}`, + ); this.changeDebugPrintIndent(1); } - const [originalType, originalAttributes] = typeAndAttributesForTypeRef(originalRef, this.originalGraph); + const [originalType, originalAttributes] = + typeAndAttributesForTypeRef(originalRef, this.originalGraph); const attributeSources = this._attributeSources.get(originalType); if (attributes === undefined) { attributes = emptyTypeAttributes; } + if (attributeSources === undefined) { attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(originalAttributes) + this.reconstituteTypeAttributes(originalAttributes), ); } else { attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(combineTypeAttributesOfTypes("union", attributeSources)) + this.reconstituteTypeAttributes( + combineTypeAttributesOfTypes("union", attributeSources), + ), ); } + const newAttributes = attributes; const reconstituter = new TypeReconstituter( @@ -409,13 +600,18 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { this.canonicalOrder, newAttributes, forwardingRef, - tref => { - assert(tref === forwardingRef, "Reconstituted type as a different ref"); + (tref) => { + assert( + tref === forwardingRef, + "Reconstituted type as a different ref", + ); if (this.debugPrint) { this.changeDebugPrintIndent(-1); - console.log(`${this.debugPrintIndentation}reconstituted ${index} as ${typeRefIndex(tref)}`); + console.log( + `${this.debugPrintIndentation}reconstituted ${index} as ${typeRefIndex(tref)}`, + ); } - } + }, ); originalType.reconstitute(reconstituter, this.canonicalOrder); return reconstituter.getResult(); @@ -423,11 +619,15 @@ export class GraphRemapBuilder extends BaseGraphRewriteBuilder { } } -export class GraphRewriteBuilder extends BaseGraphRewriteBuilder { +export class GraphRewriteBuilder< + T extends Type, +> extends BaseGraphRewriteBuilder { private readonly _setsToReplaceByMember: Map>; - private readonly _reconstitutedUnions: EqualityMap, TypeRef> = new EqualityMap(); - constructor( + private readonly _reconstitutedUnions: EqualityMap, TypeRef> = + new EqualityMap(); + + public constructor( originalGraph: TypeGraph, stringTypeMapping: StringTypeMapping, alphabetizeProperties: boolean, @@ -437,15 +637,15 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder private readonly _replacer: ( typesToReplace: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef - ) => TypeRef + forwardingRef: TypeRef, + ) => TypeRef, ) { super( originalGraph, stringTypeMapping, alphabetizeProperties, graphHasProvenanceAttributes, - debugPrintReconstitution + debugPrintReconstitution, ); this._setsToReplaceByMember = new Map(); @@ -453,25 +653,36 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder const set = new Set(types); for (const t of set) { const index = t.index; - assert(!this._setsToReplaceByMember.has(index), "A type is member of more than one set to be replaced"); + assert( + !this._setsToReplaceByMember.has(index), + "A type is member of more than one set to be replaced", + ); this._setsToReplaceByMember.set(index, set); } } } - registerUnion(typeRefs: TypeRef[], reconstituted: TypeRef): void { + public registerUnion(typeRefs: TypeRef[], reconstituted: TypeRef): void { const set = new Set(typeRefs); - assert(!this._reconstitutedUnions.has(set), "Cannot register reconstituted set twice"); + assert( + !this._reconstitutedUnions.has(set), + "Cannot register reconstituted set twice", + ); this._reconstitutedUnions.set(set, reconstituted); } - private replaceSet(typesToReplace: ReadonlySet, maybeForwardingRef: TypeRef | undefined): TypeRef { - return this.withForwardingRef(maybeForwardingRef, forwardingRef => { + private replaceSet( + typesToReplace: ReadonlySet, + maybeForwardingRef: TypeRef | undefined, + ): TypeRef { + return this.withForwardingRef(maybeForwardingRef, (forwardingRef) => { if (this.debugPrint) { console.log( - `${this.debugPrintIndentation}replacing set ${Array.from(typesToReplace) - .map(t => t.index.toString()) - .join(",")} as ${typeRefIndex(forwardingRef)}` + `${this.debugPrintIndentation}replacing set ${Array.from( + typesToReplace, + ) + .map((t) => t.index.toString()) + .join(",")} as ${typeRefIndex(forwardingRef)}`, ); this.changeDebugPrintIndent(1); } @@ -482,15 +693,21 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder this.reconstitutedTypes.set(index, forwardingRef); this._setsToReplaceByMember.delete(index); } + const result = this._replacer(typesToReplace, this, forwardingRef); - assert(result === forwardingRef, "The forwarding ref got lost when replacing"); + assert( + result === forwardingRef, + "The forwarding ref got lost when replacing", + ); if (this.debugPrint) { this.changeDebugPrintIndent(-1); console.log( - `${this.debugPrintIndentation}replaced set ${Array.from(typesToReplace) - .map(t => t.index.toString()) - .join(",")} as ${typeRefIndex(forwardingRef)}` + `${this.debugPrintIndentation}replaced set ${Array.from( + typesToReplace, + ) + .map((t) => t.index.toString()) + .join(",")} as ${typeRefIndex(forwardingRef)}`, ); } @@ -501,9 +718,12 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder protected forceReconstituteTypeRef( originalRef: TypeRef, attributes?: TypeAttributes, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef { - const [originalType, originalAttributes] = typeAndAttributesForTypeRef(originalRef, this.originalGraph); + const [originalType, originalAttributes] = typeAndAttributesForTypeRef( + originalRef, + this.originalGraph, + ); const index = typeRefIndex(originalRef); if (this.debugPrint) { @@ -517,33 +737,48 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder attributes = combineTypeAttributes( "union", attributes, - this.reconstituteTypeAttributes(originalAttributes) + this.reconstituteTypeAttributes(originalAttributes), ); } - const reconstituter = new TypeReconstituter(this, this.canonicalOrder, attributes, maybeForwardingRef, tref => { - if (this.debugPrint) { - this.changeDebugPrintIndent(-1); - console.log(`${this.debugPrintIndentation}reconstituted ${index} as ${typeRefIndex(tref)}`); - } + const reconstituter = new TypeReconstituter( + this, + this.canonicalOrder, + attributes, + maybeForwardingRef, + (tref) => { + if (this.debugPrint) { + this.changeDebugPrintIndent(-1); + console.log( + `${this.debugPrintIndentation}reconstituted ${index} as ${typeRefIndex(tref)}`, + ); + } - if (maybeForwardingRef !== undefined) { - assert(tref === maybeForwardingRef, "We didn't pass the forwarding ref"); - } + if (maybeForwardingRef !== undefined) { + assert( + tref === maybeForwardingRef, + "We didn't pass the forwarding ref", + ); + } - const alreadyReconstitutedType = this.reconstitutedTypes.get(index); - if (alreadyReconstitutedType === undefined) { - this.reconstitutedTypes.set(index, tref); - } else { - assert(tref === alreadyReconstitutedType, "We reconstituted a type twice differently"); - } - }); + const alreadyReconstitutedType = + this.reconstitutedTypes.get(index); + if (alreadyReconstitutedType === undefined) { + this.reconstitutedTypes.set(index, tref); + } else { + assert( + tref === alreadyReconstitutedType, + "We reconstituted a type twice differently", + ); + } + }, + ); originalType.reconstitute(reconstituter, this.canonicalOrder); return reconstituter.getResult(); } /* - reconstituteTypeUnmodified(originalType: Type): TypeRef { + public reconstituteTypeUnmodified(originalType: Type): TypeRef { const reconstituter = new TypeReconstituter( this, this.alphabetizeProperties, @@ -558,7 +793,11 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder // If the union of these type refs have been, or are supposed to be, reconstituted to // one target type, return it. Otherwise return undefined. - lookupTypeRefs(typeRefs: TypeRef[], forwardingRef?: TypeRef, replaceSet = true): TypeRef | undefined { + public lookupTypeRefs( + typeRefs: TypeRef[], + forwardingRef?: TypeRef, + replaceSet = true, + ): TypeRef | undefined { this.assertTypeRefsToReconstitute(typeRefs, forwardingRef); // Check whether we have already reconstituted them. That means ensuring @@ -567,11 +806,15 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder if (maybeRef !== undefined && maybeRef !== forwardingRef) { let allEqual = true; for (let i = 1; i < typeRefs.length; i++) { - if (this.reconstitutedTypes.get(typeRefIndex(typeRefs[i])) !== maybeRef) { + if ( + this.reconstitutedTypes.get(typeRefIndex(typeRefs[i])) !== + maybeRef + ) { allEqual = false; break; } } + if (allEqual) { return this.forwardIfNecessary(forwardingRef, maybeRef); } @@ -584,15 +827,22 @@ export class GraphRewriteBuilder extends BaseGraphRewriteBuilder } // Is this set requested to be replaced? If not, we're out of options. - const maybeSet = this._setsToReplaceByMember.get(typeRefIndex(typeRefs[0])); + const maybeSet = this._setsToReplaceByMember.get( + typeRefIndex(typeRefs[0]), + ); if (maybeSet === undefined) { return undefined; } + for (let i = 1; i < typeRefs.length; i++) { - if (this._setsToReplaceByMember.get(typeRefIndex(typeRefs[i])) !== maybeSet) { + if ( + this._setsToReplaceByMember.get(typeRefIndex(typeRefs[i])) !== + maybeSet + ) { return undefined; } } + // Yes, this set is requested to be replaced, so do it. if (!replaceSet) return undefined; return this.replaceSet(maybeSet, forwardingRef); diff --git a/packages/quicktype-core/src/Inference.ts b/packages/quicktype-core/src/Inference.ts new file mode 100644 index 000000000..94bf2e829 --- /dev/null +++ b/packages/quicktype-core/src/Inference.ts @@ -0,0 +1,97 @@ +import type { TransformedStringTypeKind } from "./Type"; + +export interface InferenceFlag { + description: string; + explanation: string; + negationDescription: string; + order: number; + stringType?: TransformedStringTypeKind; +} + +export const inferenceFlagsObject = { + /** Whether to infer map types from JSON data */ + inferMaps: { + description: "Detect maps", + negationDescription: "Don't infer maps, always use classes", + explanation: "Infer maps when object keys look like map keys.", + order: 1, + }, + /** Whether to infer enum types from JSON data */ + inferEnums: { + description: "Detect enums", + negationDescription: "Don't infer enums, always use strings", + explanation: + "If string values occur within a relatively small domain,\ninfer them as enum values.", + order: 2, + }, + /** Whether to convert UUID strings to UUID objects */ + inferUuids: { + description: "Detect UUIDs", + negationDescription: "Don't convert UUIDs to UUID objects", + explanation: + "Detect UUIDs like '123e4567-e89b-12d3-a456-426655440000' (partial support).", + stringType: "uuid" as TransformedStringTypeKind, + order: 3, + }, + /** Whether to assume that JSON strings that look like dates are dates */ + inferDateTimes: { + description: "Detect dates & times", + negationDescription: "Don't infer dates or times", + explanation: "Infer dates from strings (partial support).", + stringType: "date-time" as TransformedStringTypeKind, + order: 4, + }, + /** Whether to convert stringified integers to integers */ + inferIntegerStrings: { + description: "Detect integers in strings", + negationDescription: "Don't convert stringified integers to integers", + explanation: + 'Automatically convert stringified integers to integers.\nFor example, "1" is converted to 1.', + stringType: "integer-string" as TransformedStringTypeKind, + order: 5, + }, + /** Whether to convert stringified booleans to boolean values */ + inferBooleanStrings: { + description: "Detect booleans in strings", + negationDescription: "Don't convert stringified booleans to booleans", + explanation: + 'Automatically convert stringified booleans to booleans.\nFor example, "true" is converted to true.', + stringType: "bool-string" as TransformedStringTypeKind, + order: 6, + }, + /** Combine similar classes. This doesn't apply to classes from a schema, only from inference. */ + combineClasses: { + description: "Merge similar classes", + negationDescription: "Don't combine similar classes", + explanation: + "Combine classes with significantly overlapping properties,\ntreating contingent properties as nullable.", + order: 7, + }, + /** Whether to treat $ref as references within JSON */ + ignoreJsonRefs: { + description: "Don't treat $ref as a reference in JSON", + negationDescription: "Treat $ref as a reference in JSON", + explanation: + "Like in JSON Schema, allow objects like\n'{ $ref: \"#/foo/bar\" }' to refer\nto another part of the input.", + order: 8, + }, +}; +export type InferenceFlagName = keyof typeof inferenceFlagsObject; +export const inferenceFlagNames = Object.getOwnPropertyNames( + inferenceFlagsObject, +) as InferenceFlagName[]; +export const inferenceFlags: { [F in InferenceFlagName]: InferenceFlag } = + inferenceFlagsObject; + +export type InferenceFlags = { [F in InferenceFlagName]: boolean }; + +function makeDefaultInferenceFlags(): InferenceFlags { + const flags = {} as InferenceFlags; + for (const flag of inferenceFlagNames) { + flags[flag] = true; + } + + return flags; +} + +export const defaultInferenceFlags = makeDefaultInferenceFlags(); diff --git a/packages/quicktype-core/src/MakeTransformations.ts b/packages/quicktype-core/src/MakeTransformations.ts index 4e44d89f5..9707357a3 100644 --- a/packages/quicktype-core/src/MakeTransformations.ts +++ b/packages/quicktype-core/src/MakeTransformations.ts @@ -1,54 +1,76 @@ -import { setFilter, iterableFirst, mapMapEntries, withDefault, iterableSome, arraySortByInto } from "collection-utils"; +import { + arraySortByInto, + iterableFirst, + iterableSome, + mapMapEntries, + setFilter, + withDefault, +} from "collection-utils"; -import { TypeGraph, TypeRef, typeRefIndex } from "./TypeGraph"; -import { TargetLanguage } from "./TargetLanguage"; import { - UnionType, - TypeKind, - EnumType, - Type, - ArrayType, - PrimitiveType, - isNumberTypeKind, - isPrimitiveStringTypeKind, - targetTypeKindForTransformedStringTypeKind, - PrimitiveStringTypeKind -} from "./Type"; -import { GraphRewriteBuilder } from "./GraphRewriting"; -import { defined, assert, panic } from "./support/Support"; + minMaxLengthForType, + minMaxValueForType, +} from "./attributes/Constraints"; +import { StringTypes } from "./attributes/StringTypes"; import { - UnionInstantiationTransformer, - DecodingChoiceTransformer, - Transformation, - transformationTypeAttributeKind, - StringMatchTransformer, - StringProducerTransformer, + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, +} from "./attributes/TypeAttributes"; +import type { GraphRewriteBuilder } from "./GraphRewriting"; +import type { RunContext } from "./Run"; +import { assert, defined, panic } from "./support/Support"; +import type { TargetLanguage } from "./TargetLanguage"; +import { + ArrayDecodingTransformer, ChoiceTransformer, - Transformer, + DecodingChoiceTransformer, DecodingTransformer, - ParseStringTransformer, - ArrayDecodingTransformer, MinMaxLengthCheckTransformer, - MinMaxValueTransformer + MinMaxValueTransformer, + ParseStringTransformer, + StringMatchTransformer, + StringProducerTransformer, + Transformation, + type Transformer, + UnionInstantiationTransformer, + transformationTypeAttributeKind, } from "./Transformers"; -import { TypeAttributes, emptyTypeAttributes, combineTypeAttributes } from "./attributes/TypeAttributes"; -import { StringTypes } from "./attributes/StringTypes"; -import { RunContext } from "./Run"; -import { minMaxLengthForType, minMaxValueForType } from "./attributes/Constraints"; +import { + ArrayType, + EnumType, + type PrimitiveStringTypeKind, + type PrimitiveType, + type Type, + type TypeKind, + UnionType, + isNumberTypeKind, + isPrimitiveStringTypeKind, + targetTypeKindForTransformedStringTypeKind, +} from "./Type"; +import type { TypeGraph } from "./Type/TypeGraph"; +import { type TypeRef, typeRefIndex } from "./Type/TypeRef"; function transformationAttributes( graph: TypeGraph, reconstitutedTargetType: TypeRef, transformer: Transformer, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeAttributes { - const transformation = new Transformation(graph, reconstitutedTargetType, transformer); + const transformation = new Transformation( + graph, + reconstitutedTargetType, + transformer, + ); if (debugPrintTransformations) { - console.log(`transformation for ${typeRefIndex(reconstitutedTargetType)}:`); + console.log( + `transformation for ${typeRefIndex(reconstitutedTargetType)}:`, + ); transformation.debugPrint(); - console.log(`reverse:`); + console.log("reverse:"); transformation.reverse.debugPrint(); } + return transformationTypeAttributeKind.makeAttributes(transformation); } @@ -56,17 +78,22 @@ function makeEnumTransformer( graph: TypeGraph, enumType: EnumType, stringType: TypeRef, - continuation?: Transformer + continuation?: Transformer, ): Transformer { const sortedCases = Array.from(enumType.cases).sort(); const caseTransformers = sortedCases.map( - c => + (c) => new StringMatchTransformer( graph, stringType, - new StringProducerTransformer(graph, stringType, continuation, c), - c - ) + new StringProducerTransformer( + graph, + stringType, + continuation, + c, + ), + c, + ), ); return new ChoiceTransformer(graph, stringType, caseTransformers); } @@ -76,7 +103,7 @@ function replaceUnion( builder: GraphRewriteBuilder, forwardingRef: TypeRef, transformedTypes: Set, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const graph = builder.typeGraph; @@ -90,20 +117,31 @@ function replaceUnion( // the union must be the target type, so if one already exists, use that // one, otherwise make a new one. if (isPrimitiveStringTypeKind(t.kind)) { - const targetTypeKind = targetTypeKindForTransformedStringTypeKind(t.kind); + const targetTypeKind = targetTypeKindForTransformedStringTypeKind( + t.kind, + ); if (targetTypeKind !== undefined) { const targetTypeMember = union.findMember(targetTypeKind); - additionalAttributes = combineTypeAttributes("union", additionalAttributes, t.getAttributes()); + additionalAttributes = combineTypeAttributes( + "union", + additionalAttributes, + t.getAttributes(), + ); if (targetTypeMember !== undefined) { return builder.reconstituteType(targetTypeMember); } + return builder.getPrimitiveType(targetTypeKind); } } + return builder.reconstituteType(t); } - const reconstitutedMembersByKind = mapMapEntries(union.members.entries(), m => [m.kind, reconstituteMember(m)]); + const reconstitutedMembersByKind = mapMapEntries( + union.members.entries(), + (m) => [m.kind, reconstituteMember(m)], + ); const reconstitutedMemberSet = new Set(reconstitutedMembersByKind.values()); const haveUnion = reconstitutedMemberSet.size > 1; @@ -115,7 +153,7 @@ function replaceUnion( ? builder.getUnionType(union.getAttributes(), reconstitutedMemberSet) : defined(iterableFirst(reconstitutedMemberSet)); - function memberForKind(kind: TypeKind) { + function memberForKind(kind: TypeKind): number { return defined(reconstitutedMembersByKind.get(kind)); } @@ -124,18 +162,28 @@ function replaceUnion( return new UnionInstantiationTransformer(graph, memberTypeRef); } - function transformerForKind(kind: TypeKind) { + function transformerForKind( + kind: TypeKind, + ): DecodingTransformer | undefined { const member = union.findMember(kind); if (member === undefined) return undefined; const memberTypeRef = memberForKind(kind); - return new DecodingTransformer(graph, memberTypeRef, consumer(memberTypeRef)); + return new DecodingTransformer( + graph, + memberTypeRef, + consumer(memberTypeRef), + ); } let maybeStringType: TypeRef | undefined = undefined; function getStringType(): TypeRef { if (maybeStringType === undefined) { - maybeStringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); + maybeStringType = builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ); } + return maybeStringType; } @@ -146,22 +194,46 @@ function replaceUnion( if (minMax === undefined) { return consumer(memberRef); } + const [min, max] = minMax; - return new MinMaxLengthCheckTransformer(graph, getStringType(), consumer(memberRef), min, max); - } else if (t instanceof EnumType && transformedTypes.has(t)) { - return makeEnumTransformer(graph, t, getStringType(), consumer(memberRef)); - } else { - return new ParseStringTransformer(graph, getStringType(), consumer(memberRef)); + return new MinMaxLengthCheckTransformer( + graph, + getStringType(), + consumer(memberRef), + min, + max, + ); + } + if (t instanceof EnumType && transformedTypes.has(t)) { + return makeEnumTransformer( + graph, + t, + getStringType(), + consumer(memberRef), + ); } + + return new ParseStringTransformer( + graph, + getStringType(), + consumer(memberRef), + ); } - const stringTypes = arraySortByInto(Array.from(union.stringTypeMembers), t => t.kind); + const stringTypes = arraySortByInto( + Array.from(union.stringTypeMembers), + (t) => t.kind, + ); let transformerForString: Transformer | undefined; if (stringTypes.length === 0) { transformerForString = undefined; } else if (stringTypes.length === 1) { const t = stringTypes[0]; - transformerForString = new DecodingTransformer(graph, getStringType(), transformerForStringType(t)); + transformerForString = new DecodingTransformer( + graph, + getStringType(), + transformerForStringType(t), + ); } else { transformerForString = new DecodingTransformer( graph, @@ -169,8 +241,8 @@ function replaceUnion( new ChoiceTransformer( graph, getStringType(), - stringTypes.map(t => defined(transformerForStringType(t))) - ) + stringTypes.map((t) => defined(transformerForStringType(t))), + ), ); } @@ -178,9 +250,9 @@ function replaceUnion( const transformerForMap = transformerForKind("map"); assert( transformerForClass === undefined || transformerForMap === undefined, - "Can't have both class and map in a transformed union" + "Can't have both class and map in a transformed union", ); - const transformerForObject = transformerForClass !== undefined ? transformerForClass : transformerForMap; + const transformerForObject = transformerForClass ?? transformerForMap; const transformer = new DecodingChoiceTransformer( graph, @@ -191,13 +263,18 @@ function replaceUnion( transformerForKind("bool"), transformerForString, transformerForKind("array"), - transformerForObject + transformerForObject, + ); + const attributes = transformationAttributes( + graph, + reconstitutedTargetType, + transformer, + debugPrintTransformations, ); - const attributes = transformationAttributes(graph, reconstitutedTargetType, transformer, debugPrintTransformations); return builder.getPrimitiveType( "any", combineTypeAttributes("union", attributes, additionalAttributes), - forwardingRef + forwardingRef, ); } @@ -205,7 +282,7 @@ function replaceArray( arrayType: ArrayType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const anyType = builder.getPrimitiveType("any"); const anyArrayType = builder.getArrayType(emptyTypeAttributes, anyType); @@ -215,19 +292,19 @@ function replaceArray( anyArrayType, undefined, reconstitutedItems, - new DecodingTransformer(builder.typeGraph, anyType, undefined) + new DecodingTransformer(builder.typeGraph, anyType, undefined), ); const reconstitutedArray = builder.getArrayType( builder.reconstituteTypeAttributes(arrayType.getAttributes()), - reconstitutedItems + reconstitutedItems, ); const attributes = transformationAttributes( builder.typeGraph, reconstitutedArray, transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getArrayType(attributes, anyType, forwardingRef); @@ -237,43 +314,64 @@ function replaceEnum( enumType: EnumType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { - const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); + const stringType = builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - makeEnumTransformer(builder.typeGraph, enumType, stringType) + makeEnumTransformer(builder.typeGraph, enumType, stringType), + ); + const reconstitutedEnum = builder.getEnumType( + enumType.getAttributes(), + enumType.cases, ); - const reconstitutedEnum = builder.getEnumType(enumType.getAttributes(), enumType.cases); const attributes = transformationAttributes( builder.typeGraph, reconstitutedEnum, transformer, - debugPrintTransformations + debugPrintTransformations, + ); + return builder.getStringType( + attributes, + StringTypes.unrestricted, + forwardingRef, ); - return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } function replaceNumber( t: PrimitiveType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { - const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); + const stringType = builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ); const [min, max] = defined(minMaxValueForType(t)); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new MinMaxValueTransformer(builder.typeGraph, stringType, undefined, min, max) + new MinMaxValueTransformer( + builder.typeGraph, + stringType, + undefined, + min, + max, + ), + ); + const reconstitutedAttributes = builder.reconstituteTypeAttributes( + t.getAttributes(), ); - const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); const attributes = transformationAttributes( builder.typeGraph, builder.getPrimitiveType("double", reconstitutedAttributes, undefined), transformer, - debugPrintTransformations + debugPrintTransformations, ); return builder.getPrimitiveType("double", attributes, forwardingRef); } @@ -282,23 +380,38 @@ function replaceString( t: PrimitiveType, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { const [min, max] = defined(minMaxLengthForType(t)); - const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); - const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); + const reconstitutedAttributes = builder.reconstituteTypeAttributes( + t.getAttributes(), + ); + const stringType = builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new MinMaxLengthCheckTransformer(builder.typeGraph, stringType, undefined, min, max) + new MinMaxLengthCheckTransformer( + builder.typeGraph, + stringType, + undefined, + min, + max, + ), ); const attributes = transformationAttributes( builder.typeGraph, builder.getStringType(reconstitutedAttributes, undefined), transformer, - debugPrintTransformations + debugPrintTransformations, + ); + return builder.getStringType( + attributes, + StringTypes.unrestricted, + forwardingRef, ); - return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } function replaceTransformedStringType( @@ -306,74 +419,124 @@ function replaceTransformedStringType( kind: PrimitiveStringTypeKind, builder: GraphRewriteBuilder, forwardingRef: TypeRef, - debugPrintTransformations: boolean + debugPrintTransformations: boolean, ): TypeRef { - const reconstitutedAttributes = builder.reconstituteTypeAttributes(t.getAttributes()); - const targetTypeKind = withDefault(targetTypeKindForTransformedStringTypeKind(kind), kind); - const stringType = builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); + const reconstitutedAttributes = builder.reconstituteTypeAttributes( + t.getAttributes(), + ); + const targetTypeKind = withDefault( + targetTypeKindForTransformedStringTypeKind(kind), + kind, + ); + const stringType = builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ); const transformer = new DecodingTransformer( builder.typeGraph, stringType, - new ParseStringTransformer(builder.typeGraph, stringType, undefined) + new ParseStringTransformer(builder.typeGraph, stringType, undefined), ); const attributes = transformationAttributes( builder.typeGraph, builder.getPrimitiveType(targetTypeKind, reconstitutedAttributes), transformer, - debugPrintTransformations + debugPrintTransformations, + ); + return builder.getStringType( + attributes, + StringTypes.unrestricted, + forwardingRef, ); - return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); } -export function makeTransformations(ctx: RunContext, graph: TypeGraph, targetLanguage: TargetLanguage): TypeGraph { - const transformedTypes = setFilter(graph.allTypesUnordered(), t => { +export function makeTransformations( + ctx: RunContext, + graph: TypeGraph, + targetLanguage: TargetLanguage, +): TypeGraph { + const transformedTypes = setFilter(graph.allTypesUnordered(), (t) => { if (targetLanguage.needsTransformerForType(t)) return true; if (!(t instanceof UnionType)) return false; const stringMembers = t.stringTypeMembers; if (stringMembers.size <= 1) return false; - return iterableSome(stringMembers, m => targetLanguage.needsTransformerForType(m)); + return iterableSome(stringMembers, (m) => + targetLanguage.needsTransformerForType(m), + ); }); function replace( setOfOneUnion: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { const t = defined(iterableFirst(setOfOneUnion)); if (t instanceof UnionType) { - return replaceUnion(t, builder, forwardingRef, transformedTypes, ctx.debugPrintTransformations); + return replaceUnion( + t, + builder, + forwardingRef, + transformedTypes, + ctx.debugPrintTransformations, + ); } + if (t instanceof ArrayType) { - return replaceArray(t, builder, forwardingRef, ctx.debugPrintTransformations); + return replaceArray( + t, + builder, + forwardingRef, + ctx.debugPrintTransformations, + ); } + if (t instanceof EnumType) { - return replaceEnum(t, builder, forwardingRef, ctx.debugPrintTransformations); + return replaceEnum( + t, + builder, + forwardingRef, + ctx.debugPrintTransformations, + ); } + if (t.kind === "string") { - return replaceString(t as PrimitiveType, builder, forwardingRef, ctx.debugPrintTransformations); + return replaceString( + t as PrimitiveType, + builder, + forwardingRef, + ctx.debugPrintTransformations, + ); } + if (isNumberTypeKind(t.kind)) { - return replaceNumber(t as PrimitiveType, builder, forwardingRef, ctx.debugPrintTransformations); + return replaceNumber( + t as PrimitiveType, + builder, + forwardingRef, + ctx.debugPrintTransformations, + ); } + if (isPrimitiveStringTypeKind(t.kind)) { return replaceTransformedStringType( t as PrimitiveType, t.kind, builder, forwardingRef, - ctx.debugPrintTransformations + ctx.debugPrintTransformations, ); } + return panic(`Cannot make transformation for type ${t.kind}`); } - const groups = Array.from(transformedTypes).map(t => [t]); + const groups = Array.from(transformedTypes).map((t) => [t]); return graph.rewrite( "make-transformations", ctx.stringTypeMapping, false, groups, ctx.debugPrintReconstitution, - replace + replace, ); } diff --git a/packages/quicktype-core/src/MarkovChain.ts b/packages/quicktype-core/src/MarkovChain.ts index 1c1b730a6..cd36d4b56 100644 --- a/packages/quicktype-core/src/MarkovChain.ts +++ b/packages/quicktype-core/src/MarkovChain.ts @@ -1,23 +1,24 @@ -import { panic, assert, inflateBase64 } from "./support/Support"; import { encodedMarkovChain } from "./EncodedMarkovChain"; +import { assert, inflateBase64, panic } from "./support/Support"; // This must be null, not undefined, because we read it from JSON. export type SubTrie = number | null | Trie; -export type Trie = { - count: number; +export interface Trie { arr: SubTrie[]; -}; + count: number; +} -export type MarkovChain = { - trie: Trie; +export interface MarkovChain { depth: number; -}; + trie: Trie; +} function makeTrie(): Trie { const arr: SubTrie[] = []; for (let i = 0; i < 128; i++) { arr.push(null); } + return { count: 0, arr }; } @@ -35,6 +36,7 @@ function lookup(t: Trie, seq: string, i: number): Trie | number | undefined { if (n === null) { return undefined; } + if (typeof n === "object") { return lookup(n, seq, i + 1); } else { @@ -52,12 +54,14 @@ function increment(t: Trie, seq: string, i: number): void { if (typeof t !== "object") { return panic("Malformed trie"); } + let n = t.arr[first]; if (n === null) { n = 0; } else if (typeof n === "object") { return panic("Malformed trie"); } + t.arr[first] = n + 1; t.count += 1; return; @@ -67,10 +71,12 @@ function increment(t: Trie, seq: string, i: number): void { if (st === null) { t.arr[first] = st = makeTrie(); } + if (typeof st !== "object") { return panic("Malformed trie"); } - return increment(st, seq, i + 1); + + increment(st, seq, i + 1); } export function train(lines: string[], depth: number): MarkovChain { @@ -88,11 +94,15 @@ export function load(): MarkovChain { return JSON.parse(inflateBase64(encodedMarkovChain)); } -export function evaluateFull(mc: MarkovChain, word: string): [number, number[]] { +export function evaluateFull( + mc: MarkovChain, + word: string, +): [number, number[]] { const { trie, depth } = mc; if (word.length < depth) { return [1, []]; } + let p = 1; const scores: number[] = []; for (let i = depth; i <= word.length; i++) { @@ -100,12 +110,15 @@ export function evaluateFull(mc: MarkovChain, word: string): [number, number[]] if (typeof cp === "object") { return panic("Did we mess up the depth?"); } + if (cp === undefined) { cp = 0.0001; } + scores.push(cp); p = p * cp; } + return [Math.pow(p, 1 / (word.length - depth + 1)), scores]; } @@ -113,25 +126,37 @@ export function evaluate(mc: MarkovChain, word: string): number { return evaluateFull(mc, word)[0]; } -function randomInt(lower: number, upper: number) { +function randomInt(lower: number, upper: number): number { const range = upper - lower; return lower + Math.floor(Math.random() * range); } -export function generate(mc: MarkovChain, state: string, unseenWeight: number): string { - assert(state.length === mc.depth - 1, "State and chain length don't match up"); +export function generate( + mc: MarkovChain, + state: string, + unseenWeight: number, +): string { + assert( + state.length === mc.depth - 1, + "State and chain length don't match up", + ); const t = lookup(mc.trie, state, 0); if (typeof t === "number") { return panic("Wrong depth?"); } + if (t === undefined) { return String.fromCharCode(randomInt(32, 127)); } - const counts = t.arr.map((x, i) => (x === null ? (i === 0 ? 0 : unseenWeight) : (x as number))); + + const counts = t.arr.map((x, i) => + x === null ? (i === 0 ? 0 : unseenWeight) : (x as number), + ); let n = 0; for (const c of counts) { n += c; } + const r = randomInt(0, n); let sum = 0; for (let i = 0; i < counts.length; i++) { @@ -140,6 +165,7 @@ export function generate(mc: MarkovChain, state: string, unseenWeight: number): return String.fromCharCode(i); } } + return panic("We screwed up bookkeeping, or randomInt"); } @@ -171,6 +197,6 @@ export function test(): void { testWord( mc, - "\ud83d\udebe \ud83c\udd92 \ud83c\udd93 \ud83c\udd95 \ud83c\udd96 \ud83c\udd97 \ud83c\udd99 \ud83c\udfe7" + "\ud83d\udebe \ud83c\udd92 \ud83c\udd93 \ud83c\udd95 \ud83c\udd96 \ud83c\udd97 \ud83c\udd99 \ud83c\udfe7", ); } diff --git a/packages/quicktype-core/src/Messages.ts b/packages/quicktype-core/src/Messages.ts index d740163ec..285207c76 100644 --- a/packages/quicktype-core/src/Messages.ts +++ b/packages/quicktype-core/src/Messages.ts @@ -1,5 +1,6 @@ -import { StringMap } from "./support/Support"; -import { Ref } from "./input/JSONSchemaInput"; +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { Ref } from "./input/JSONSchemaInput"; +import type { StringMap } from "./support/Support"; export type ErrorProperties = | { kind: "InternalError"; properties: { message: string } } @@ -7,41 +8,89 @@ export type ErrorProperties = // Misc | { kind: "MiscJSONParseError"; - properties: { description: string; address: string; message: string }; + properties: { address: string; description: string; message: string }; + } + | { + kind: "MiscReadError"; + properties: { fileOrURL: string; message: string }; } - | { kind: "MiscReadError"; properties: { fileOrURL: string; message: string } } | { kind: "MiscUnicodeHighSurrogateWithoutLowSurrogate"; properties: {} } - | { kind: "MiscInvalidMinMaxConstraint"; properties: { min: number; max: number } } + | { + kind: "MiscInvalidMinMaxConstraint"; + properties: { max: number; min: number }; + } // Inference - | { kind: "InferenceJSONReferenceNotRooted"; properties: { reference: string } } - | { kind: "InferenceJSONReferenceToUnion"; properties: { reference: string } } - | { kind: "InferenceJSONReferenceWrongProperty"; properties: { reference: string } } - | { kind: "InferenceJSONReferenceInvalidArrayIndex"; properties: { reference: string } } + | { + kind: "InferenceJSONReferenceNotRooted"; + properties: { reference: string }; + } + | { + kind: "InferenceJSONReferenceToUnion"; + properties: { reference: string }; + } + | { + kind: "InferenceJSONReferenceWrongProperty"; + properties: { reference: string }; + } + | { + kind: "InferenceJSONReferenceInvalidArrayIndex"; + properties: { reference: string }; + } // JSON Schema input | { kind: "SchemaArrayIsInvalidSchema"; properties: { ref: Ref } } | { kind: "SchemaNullIsInvalidSchema"; properties: { ref: Ref } } - | { kind: "SchemaRefMustBeString"; properties: { actual: string; ref: Ref } } + | { + kind: "SchemaRefMustBeString"; + properties: { actual: string; ref: Ref }; + } | { kind: "SchemaAdditionalTypesForbidRequired"; properties: { ref: Ref } } | { kind: "SchemaNoTypeSpecified"; properties: { ref: Ref } } - | { kind: "SchemaInvalidType"; properties: { type: string; ref: Ref } } + | { kind: "SchemaInvalidType"; properties: { ref: Ref; type: string } } | { kind: "SchemaFalseNotSupported"; properties: { ref: Ref } } - | { kind: "SchemaInvalidJSONSchemaType"; properties: { type: string; ref: Ref } } - | { kind: "SchemaRequiredMustBeStringOrStringArray"; properties: { actual: any; ref: Ref } } - | { kind: "SchemaRequiredElementMustBeString"; properties: { element: any; ref: Ref } } - | { kind: "SchemaTypeMustBeStringOrStringArray"; properties: { actual: any } } - | { kind: "SchemaTypeElementMustBeString"; properties: { element: any; ref: Ref } } - | { kind: "SchemaArrayItemsMustBeStringOrArray"; properties: { actual: any; ref: Ref } } + | { + kind: "SchemaInvalidJSONSchemaType"; + properties: { ref: Ref; type: string }; + } + | { + kind: "SchemaRequiredMustBeStringOrStringArray"; + properties: { actual: any; ref: Ref }; + } + | { + kind: "SchemaRequiredElementMustBeString"; + properties: { element: any; ref: Ref }; + } + | { + kind: "SchemaTypeMustBeStringOrStringArray"; + properties: { actual: any }; + } + | { + kind: "SchemaTypeElementMustBeString"; + properties: { element: any; ref: Ref }; + } + | { + kind: "SchemaArrayItemsMustBeStringOrArray"; + properties: { actual: any; ref: Ref }; + } | { kind: "SchemaIDMustHaveAddress"; properties: { id: string; ref: Ref } } - | { kind: "SchemaWrongAccessorEntryArrayLength"; properties: { operation: string; ref: Ref } } + | { + kind: "SchemaWrongAccessorEntryArrayLength"; + properties: { operation: string; ref: Ref }; + } | { kind: "SchemaSetOperationCasesIsNotArray"; - properties: { operation: string; cases: any; ref: Ref }; + properties: { cases: any; operation: string; ref: Ref }; + } + | { + kind: "SchemaMoreThanOneUnionMemberName"; + properties: { names: string[] }; } - | { kind: "SchemaMoreThanOneUnionMemberName"; properties: { names: string[] } } | { kind: "SchemaCannotGetTypesFromBoolean"; properties: { ref: string } } - | { kind: "SchemaCannotIndexArrayWithNonNumber"; properties: { actual: string; ref: Ref } } + | { + kind: "SchemaCannotIndexArrayWithNonNumber"; + properties: { actual: string; ref: Ref }; + } | { kind: "SchemaIndexNotInArray"; properties: { index: number; ref: Ref } } | { kind: "SchemaKeyNotInObject"; properties: { key: string; ref: Ref } } | { kind: "SchemaFetchError"; properties: { address: string; base: Ref } } @@ -58,11 +107,17 @@ export type ErrorProperties = | { kind: "DriverCannotInferNameForSchema"; properties: { uri: string } } | { kind: "DriverNoGraphQLQueryGiven"; properties: {} } | { kind: "DriverNoGraphQLSchemaInDir"; properties: { dir: string } } - | { kind: "DriverMoreThanOneGraphQLSchemaInDir"; properties: { dir: string } } + | { + kind: "DriverMoreThanOneGraphQLSchemaInDir"; + properties: { dir: string }; + } | { kind: "DriverSourceLangMustBeGraphQL"; properties: {} } | { kind: "DriverGraphQLSchemaNeeded"; properties: {} } | { kind: "DriverInputFileDoesNotExist"; properties: { filename: string } } - | { kind: "DriverCannotMixJSONWithOtherSamples"; properties: { dir: string } } + | { + kind: "DriverCannotMixJSONWithOtherSamples"; + properties: { dir: string }; + } | { kind: "DriverCannotMixNonJSONInputs"; properties: { dir: string } } | { kind: "DriverUnknownDebugOption"; properties: { option: string } } | { kind: "DriverNoLanguageOrExtension"; properties: {} } @@ -70,16 +125,22 @@ export type ErrorProperties = // IR | { kind: "IRNoForwardDeclarableTypeInCycle"; properties: {} } - | { kind: "IRTypeAttributesNotPropagated"; properties: { count: number; indexes: number[] } } + | { + kind: "IRTypeAttributesNotPropagated"; + properties: { count: number; indexes: number[] }; + } | { kind: "IRNoEmptyUnions"; properties: {} } // Rendering - | { kind: "RendererUnknownOptionValue"; properties: { value: string; name: string } } + | { + kind: "RendererUnknownOptionValue"; + properties: { name: string; value: string }; + } // TypeScript input | { kind: "TypeScriptCompilerError"; properties: { message: string } }; -export type ErrorKinds = ErrorProperties extends { kind: infer K } ? K : never; +export type ErrorKinds = ErrorProperties["kind"]; type ErrorMessages = { readonly [K in ErrorKinds]: string }; @@ -87,45 +148,62 @@ const errorMessages: ErrorMessages = { InternalError: "Internal error: ${message}", // Misc - MiscJSONParseError: "Syntax error in ${description} JSON ${address}: ${message}", + MiscJSONParseError: + "Syntax error in ${description} JSON ${address}: ${message}", MiscReadError: "Cannot read from file or URL ${fileOrURL}: ${message}", - MiscUnicodeHighSurrogateWithoutLowSurrogate: "Malformed unicode: High surrogate not followed by low surrogate", + MiscUnicodeHighSurrogateWithoutLowSurrogate: + "Malformed unicode: High surrogate not followed by low surrogate", MiscInvalidMinMaxConstraint: "Invalid min-max constraint: ${min}-${max}", // Inference - InferenceJSONReferenceNotRooted: "JSON reference doesn't start with '#/': ${reference}", - InferenceJSONReferenceToUnion: "JSON reference points to a union type: ${reference}", - InferenceJSONReferenceWrongProperty: "JSON reference points to a non-existant property: ${reference}", - InferenceJSONReferenceInvalidArrayIndex: "JSON reference uses invalid array index: ${reference}", + InferenceJSONReferenceNotRooted: + "JSON reference doesn't start with '#/': ${reference}", + InferenceJSONReferenceToUnion: + "JSON reference points to a union type: ${reference}", + InferenceJSONReferenceWrongProperty: + "JSON reference points to a non-existant property: ${reference}", + InferenceJSONReferenceInvalidArrayIndex: + "JSON reference uses invalid array index: ${reference}", // JSON Schema input SchemaArrayIsInvalidSchema: "An array is not a valid JSON Schema at ${ref}", SchemaNullIsInvalidSchema: "null is not a valid JSON Schema at ${ref}", - SchemaRefMustBeString: "$ref must be a string, but is an ${actual} at ${ref}", + SchemaRefMustBeString: + "$ref must be a string, but is an ${actual} at ${ref}", SchemaAdditionalTypesForbidRequired: "Can't have non-specified required properties but forbidden additionalTypes at ${ref}", - SchemaNoTypeSpecified: "JSON Schema must specify at least one type at ${ref}", + SchemaNoTypeSpecified: + "JSON Schema must specify at least one type at ${ref}", SchemaInvalidType: "Invalid type ${type} in JSON Schema at ${ref}", SchemaFalseNotSupported: 'Schema "false" is not supported at ${ref}', - SchemaInvalidJSONSchemaType: "Value of type ${type} is not valid JSON Schema at ${ref}", + SchemaInvalidJSONSchemaType: + "Value of type ${type} is not valid JSON Schema at ${ref}", SchemaRequiredMustBeStringOrStringArray: "`required` must be string or array of strings, but is ${actual} at ${ref}", - SchemaRequiredElementMustBeString: "`required` must contain only strings, but it has ${element}, at ${ref}", - SchemaTypeMustBeStringOrStringArray: "`type` must be string or array of strings, but is ${actual}", - SchemaTypeElementMustBeString: "`type` must contain only strings, but it has ${element}", - SchemaArrayItemsMustBeStringOrArray: "Array items must be an array or an object, but is ${actual}", + SchemaRequiredElementMustBeString: + "`required` must contain only strings, but it has ${element}, at ${ref}", + SchemaTypeMustBeStringOrStringArray: + "`type` must be string or array of strings, but is ${actual}", + SchemaTypeElementMustBeString: + "`type` must contain only strings, but it has ${element}", + SchemaArrayItemsMustBeStringOrArray: + "Array items must be an array or an object, but is ${actual}", SchemaIDMustHaveAddress: "$id ${id} doesn't have an address at ${ref}", SchemaWrongAccessorEntryArrayLength: "Accessor entry array must have the same number of entries as the ${operation} at ${ref}", - SchemaSetOperationCasesIsNotArray: "${operation} cases must be an array, but is ${cases}, at ${ref}", - SchemaMoreThanOneUnionMemberName: "More than one name given for union member: ${names}", + SchemaSetOperationCasesIsNotArray: + "${operation} cases must be an array, but is ${cases}, at ${ref}", + SchemaMoreThanOneUnionMemberName: + "More than one name given for union member: ${names}", SchemaCannotGetTypesFromBoolean: "Schema value to get top-level types from must be an object, but is boolean, at ${ref}", SchemaCannotIndexArrayWithNonNumber: "Trying to index array in schema with key that is not a number, but is ${actual} at ${ref}", - SchemaIndexNotInArray: "Index ${index} out of range of schema array at ${ref}", + SchemaIndexNotInArray: + "Index ${index} out of range of schema array at ${ref}", SchemaKeyNotInObject: "Key ${key} not in schema object at ${ref}", - SchemaFetchError: "Could not fetch schema ${address}, referred to from ${base}", + SchemaFetchError: + "Could not fetch schema ${address}, referred to from ${base}", SchemaFetchErrorTopLevel: "Could not fetch top-level schema ${address}", SchemaFetchErrorAdditional: "Could not fetch additional schema ${address}", @@ -135,19 +213,26 @@ const errorMessages: ErrorMessages = { // Driver DriverUnknownSourceLanguage: "Unknown source language ${lang}", DriverUnknownOutputLanguage: "Unknown output language ${lang}", - DriverMoreThanOneInputGiven: "More than one input given for top-level ${topLevel}", + DriverMoreThanOneInputGiven: + "More than one input given for top-level ${topLevel}", DriverCannotInferNameForSchema: "Cannot infer name for schema ${uri}", - DriverNoGraphQLQueryGiven: "Please specify at least one GraphQL query as input", + DriverNoGraphQLQueryGiven: + "Please specify at least one GraphQL query as input", DriverNoGraphQLSchemaInDir: "No GraphQL schema in ${dir}", - DriverMoreThanOneGraphQLSchemaInDir: "More than one GraphQL schema in ${dir}", - DriverSourceLangMustBeGraphQL: "If a GraphQL schema is specified, the source language must be GraphQL", - DriverGraphQLSchemaNeeded: "Please specify a GraphQL schema with --graphql-schema or --graphql-introspect", + DriverMoreThanOneGraphQLSchemaInDir: + "More than one GraphQL schema in ${dir}", + DriverSourceLangMustBeGraphQL: + "If a GraphQL schema is specified, the source language must be GraphQL", + DriverGraphQLSchemaNeeded: + "Please specify a GraphQL schema with --graphql-schema or --graphql-introspect", DriverInputFileDoesNotExist: "Input file ${filename} does not exist", DriverCannotMixJSONWithOtherSamples: "Cannot mix JSON samples with JSON Schems, GraphQL, or TypeScript in input subdirectory ${dir}", - DriverCannotMixNonJSONInputs: "Cannot mix JSON Schema, GraphQL, and TypeScript in an input subdirectory ${dir}", + DriverCannotMixNonJSONInputs: + "Cannot mix JSON Schema, GraphQL, and TypeScript in an input subdirectory ${dir}", DriverUnknownDebugOption: "Unknown debug option ${option}", - DriverNoLanguageOrExtension: "Please specify a language (--lang) or an output file extension", + DriverNoLanguageOrExtension: + "Please specify a language (--lang) or an output file extension", DriverCLIOptionParsingFailed: "Option parsing failed: ${message}", // IR @@ -155,54 +240,69 @@ const errorMessages: ErrorMessages = { "Cannot resolve cycle because it doesn't contain types that can be forward declared", IRTypeAttributesNotPropagated: "Type attributes for ${count} types were not carried over to the new graph: ${indexes}", - IRNoEmptyUnions: "Trying to make an empty union - do you have an impossible type in your schema?", + IRNoEmptyUnions: + "Trying to make an empty union - do you have an impossible type in your schema?", // Rendering RendererUnknownOptionValue: "Unknown value ${value} for option ${name}", // TypeScript input - TypeScriptCompilerError: "TypeScript error: ${message}" + TypeScriptCompilerError: "TypeScript error: ${message}", }; -export type ErrorPropertiesForName = Extract extends { properties: infer P } +export type ErrorPropertiesForKind = Extract< + ErrorProperties, + { kind: K } +> extends { properties: infer P } ? P : never; export class QuickTypeError extends Error { - constructor( - readonly errorMessage: string, - readonly messageName: string, - userMessage: string, - readonly properties: StringMap + public constructor( + public readonly errorMessage: string, + public readonly messageName: string, + public userMessage: string, + public readonly properties: StringMap, ) { super(userMessage); } } -export function messageError(kind: N, properties: ErrorPropertiesForName): never { +export function messageError( + kind: Kind, + properties: ErrorPropertiesForKind, +): never { const message = errorMessages[kind]; let userMessage: string = message; - const propertiesMap = properties as StringMap; - - for (const name of Object.getOwnPropertyNames(propertiesMap)) { - let value = propertiesMap[name]; - if (typeof value === "object" && typeof value.toString === "function") { - value = value.toString(); - } else if (typeof value.message === "string") { - value = value.message; + + for (const [name, value] of Object.entries(properties as StringMap)) { + let valueString = ""; + if ( + typeof value === "object" && + typeof value?.toString === "function" + ) { + valueString = value.toString(); + } else if (typeof value?.message === "string") { + valueString = value.message; } else if (typeof value !== "string") { - value = JSON.stringify(value); + valueString = JSON.stringify(value); } - userMessage = userMessage.replace("${" + name + "}", value); + + userMessage = userMessage.replace("${" + name + "}", valueString); } - throw new QuickTypeError(message, kind, userMessage, propertiesMap); + throw new QuickTypeError( + message, + kind, + userMessage, + properties as StringMap, + ); } -export function messageAssert( +export function messageAssert( assertion: boolean, - kind: N, - properties: ErrorPropertiesForName + kind: Kind, + properties: ErrorPropertiesForKind, ): void { if (assertion) return; return messageError(kind, properties); diff --git a/packages/quicktype-core/src/Naming.ts b/packages/quicktype-core/src/Naming.ts index a8508ca51..73df1ed72 100644 --- a/packages/quicktype-core/src/Naming.ts +++ b/packages/quicktype-core/src/Naming.ts @@ -1,31 +1,34 @@ import { - setUnion, - setUnionInto, - setMap, - setFilter, + iterableEvery, iterableFind, - iterableSome, + iterableFirst, iterableMinBy, - setGroupBy, + iterableSome, + mapMergeInto, + setFilter, setFilterMap, - iterableFirst, - iterableEvery, - mapMergeInto + setGroupBy, + setMap, + setUnion, + setUnionInto, } from "collection-utils"; -import { defined, assert, panic } from "./support/Support"; +import { assert, defined, panic } from "./support/Support"; export class Namespace { - readonly forbiddenNamespaces: ReadonlySet; - readonly additionalForbidden: ReadonlySet; + public readonly forbiddenNamespaces: ReadonlySet; + + public readonly additionalForbidden: ReadonlySet; + private readonly _children = new Set(); + private readonly _members = new Set(); - constructor( + public constructor( _name: string, parent: Namespace | undefined, forbiddenNamespaces: Iterable, - additionalForbidden: Iterable + additionalForbidden: Iterable, ) { this.forbiddenNamespaces = new Set(forbiddenNamespaces); this.additionalForbidden = new Set(additionalForbidden); @@ -38,20 +41,23 @@ export class Namespace { this._children.add(child); } - get children(): ReadonlySet { + public get children(): ReadonlySet { return this._children; } - get members(): ReadonlySet { + public get members(): ReadonlySet { return this._members; } - get forbiddenNameds(): ReadonlySet { + public get forbiddenNameds(): ReadonlySet { // FIXME: cache - return setUnion(this.additionalForbidden, ...Array.from(this.forbiddenNamespaces).map(ns => ns.members)); + return setUnion( + this.additionalForbidden, + ...Array.from(this.forbiddenNamespaces).map((ns) => ns.members), + ); } - add(named: TName): TName { + public add(named: TName): TName { this._members.add(named); return named; } @@ -77,25 +83,32 @@ export type NameStyle = (rawName: string) => string; export class Namer { private readonly _prefixes: ReadonlySet; - constructor(readonly name: string, readonly nameStyle: NameStyle, prefixes: string[]) { + public constructor( + public readonly name: string, + public readonly nameStyle: NameStyle, + public prefixes: string[], + ) { this._prefixes = new Set(prefixes); } // The namesIterable comes directly out of the context and will // be modified if we assign - assignNames( + public assignNames( names: ReadonlyMap, forbiddenNamesIterable: Iterable, - namesToAssignIterable: Iterable + namesToAssignIterable: Iterable, ): ReadonlyMap { const forbiddenNames = new Set(forbiddenNamesIterable); const namesToAssign = Array.from(namesToAssignIterable); - assert(namesToAssign.length > 0, "Number of names can't be less than 1"); + assert( + namesToAssign.length > 0, + "Number of names can't be less than 1", + ); const allAssignedNames = new Map(); - let namesToPrefix: Name[] = []; + const namesToPrefix: Name[] = []; for (const name of namesToAssign) { const proposedNames = name.proposeUnstyledNames(names); const namingFunction = name.namingFunction; @@ -103,13 +116,20 @@ export class Namer { // any of the other names and that isn't already forbidden. const maybeUniqueName = iterableFind( proposedNames, - proposed => + (proposed) => !forbiddenNames.has(namingFunction.nameStyle(proposed)) && - namesToAssign.every(n => n === name || !n.proposeUnstyledNames(names).has(proposed)) + namesToAssign.every( + (n) => + n === name || + !n.proposeUnstyledNames(names).has(proposed), + ), ); if (maybeUniqueName !== undefined) { const styledName = namingFunction.nameStyle(maybeUniqueName); - const assigned = name.nameAssignments(forbiddenNames, styledName); + const assigned = name.nameAssignments( + forbiddenNames, + styledName, + ); if (assigned !== null) { mapMergeInto(allAssignedNames, assigned); setUnionInto(forbiddenNames, assigned.values()); @@ -122,10 +142,12 @@ export class Namer { namesToPrefix.push(name); } - let prefixes = this._prefixes.values(); + const prefixes = this._prefixes.values(); let suffixNumber = 1; for (const name of namesToPrefix) { - const originalName: string = defined(iterableFirst(name.proposeUnstyledNames(names))); + const originalName: string = defined( + iterableFirst(name.proposeUnstyledNames(names)), + ); for (;;) { let nameToTry: string; const { done, value: prefix } = prefixes.next(); @@ -135,8 +157,12 @@ export class Namer { nameToTry = `${originalName}_${suffixNumber.toString()}`; suffixNumber++; } + const styledName = name.namingFunction.nameStyle(nameToTry); - const assigned = name.nameAssignments(forbiddenNames, styledName); + const assigned = name.nameAssignments( + forbiddenNames, + styledName, + ); if (assigned === null) continue; mapMergeInto(allAssignedNames, assigned); setUnionInto(forbiddenNames, assigned.values()); @@ -161,7 +187,7 @@ const funPrefixes = [ "Magenta", "Frisky", "Mischievous", - "Braggadocious" + "Braggadocious", ]; export function funPrefixNamer(name: string, nameStyle: NameStyle): Namer { @@ -177,30 +203,38 @@ export abstract class Name { private readonly _associates = new Set(); // If a Named is fixed, the namingFunction is undefined. - constructor(private readonly _namingFunction: Namer | undefined, readonly order: number) {} + public constructor( + private readonly _namingFunction: Namer | undefined, + public readonly order: number, + ) {} - addAssociate(associate: AssociatedName): void { + public addAssociate(associate: AssociatedName): void { this._associates.add(associate); } - abstract get dependencies(): ReadonlyArray; + public abstract get dependencies(): readonly Name[]; - isFixed(): this is FixedName { + public isFixed(): this is FixedName { return this instanceof FixedName; } - get namingFunction(): Namer { + public get namingFunction(): Namer { return defined(this._namingFunction); } // Must return at least one proposal. The proposals are considered in order. - abstract proposeUnstyledNames(names: ReadonlyMap): ReadonlySet; + public abstract proposeUnstyledNames( + names: ReadonlyMap, + ): ReadonlySet; - firstProposedName(names: ReadonlyMap): string { + public firstProposedName(names: ReadonlyMap): string { return defined(iterableFirst(this.proposeUnstyledNames(names))); } - nameAssignments(forbiddenNames: ReadonlySet, assignedName: string): ReadonlyMap | null { + public nameAssignments( + forbiddenNames: ReadonlySet, + assignedName: string, + ): ReadonlyMap | null { if (forbiddenNames.has(assignedName)) return null; const assignments = new Map([[this, assignedName]]); for (const an of this._associates) { @@ -208,31 +242,35 @@ export abstract class Name { if (forbiddenNames.has(associatedAssignedName)) { return null; } + assignments.set(an, associatedAssignedName); } + return assignments; } } // FIXME: FixedNameds should optionally be user-configurable export class FixedName extends Name { - constructor(private readonly _fixedName: string) { + public constructor(private readonly _fixedName: string) { super(undefined, 0); } - get dependencies(): ReadonlyArray { + public get dependencies(): readonly Name[] { return []; } - addAssociate(_: AssociatedName): never { + public addAssociate(_: AssociatedName): never { return panic("Cannot add associates to fixed names"); } - get fixedName(): string { + public get fixedName(): string { return this._fixedName; } - proposeUnstyledNames(_?: ReadonlyMap): ReadonlySet { + public proposeUnstyledNames( + _?: ReadonlyMap, + ): ReadonlySet { return panic("Only fixedName should be called on FixedName."); } } @@ -240,30 +278,40 @@ export class FixedName extends Name { export class SimpleName extends Name { private readonly _unstyledNames: ReadonlySet; - constructor(unstyledNames: Iterable, namingFunction: Namer, order: number) { + public constructor( + unstyledNames: Iterable, + namingFunction: Namer, + order: number, + ) { super(namingFunction, order); this._unstyledNames = new Set(unstyledNames); } - get dependencies(): ReadonlyArray { + public get dependencies(): readonly Name[] { return []; } - proposeUnstyledNames(_?: ReadonlyMap): ReadonlySet { + public proposeUnstyledNames( + _?: ReadonlyMap, + ): ReadonlySet { return this._unstyledNames; } } export class AssociatedName extends Name { - constructor(private readonly _sponsor: Name, order: number, readonly getName: (sponsorName: string) => string) { + public constructor( + private readonly _sponsor: Name, + order: number, + public readonly getName: (sponsorName: string) => string, + ) { super(undefined, order); } - get dependencies(): ReadonlyArray { + public get dependencies(): readonly Name[] { return [this._sponsor]; } - proposeUnstyledNames(_?: ReadonlyMap): never { + public proposeUnstyledNames(_?: ReadonlyMap): never { return panic("AssociatedName must be assigned via its sponsor"); } } @@ -271,96 +319,128 @@ export class AssociatedName extends Name { export class DependencyName extends Name { private readonly _dependencies: ReadonlySet; - constructor( + public constructor( namingFunction: Namer | undefined, order: number, - private readonly _proposeUnstyledName: (lookup: (n: Name) => string) => string + private readonly _proposeUnstyledName: ( + lookup: (n: Name) => string, + ) => string, ) { super(namingFunction, order); const dependencies: Name[] = []; - _proposeUnstyledName(n => { + _proposeUnstyledName((n) => { dependencies.push(n); return "0xDEADBEEF"; }); this._dependencies = new Set(dependencies); } - get dependencies(): ReadonlyArray { + public get dependencies(): readonly Name[] { return Array.from(this._dependencies); } - proposeUnstyledNames(names: ReadonlyMap): ReadonlySet { + public proposeUnstyledNames( + names: ReadonlyMap, + ): ReadonlySet { return new Set([ - this._proposeUnstyledName(n => { - assert(this._dependencies.has(n), "DependencyName proposer is not pure"); + this._proposeUnstyledName((n) => { + assert( + this._dependencies.has(n), + "DependencyName proposer is not pure", + ); return defined(names.get(n)); - }) + }), ]); } } -export function keywordNamespace(name: string, keywords: string[]) { +export function keywordNamespace( + name: string, + keywords: readonly string[], +): Namespace { const ns = new Namespace(name, undefined, [], []); for (const kw of keywords) { ns.add(new FixedName(kw)); } + return ns; } -function allNamespacesRecursively(namespaces: Iterable): ReadonlySet { - return setUnion(namespaces, ...Array.from(setMap(namespaces, ns => allNamespacesRecursively(ns.children)))); +function allNamespacesRecursively( + namespaces: Iterable, +): ReadonlySet { + return setUnion( + namespaces, + ...Array.from( + setMap(namespaces, (ns) => allNamespacesRecursively(ns.children)), + ), + ); } class NamingContext { private readonly _names: Map = new Map(); + private readonly _namedsForName: Map> = new Map(); - readonly namespaces: ReadonlySet; - constructor(rootNamespaces: Iterable) { + public readonly namespaces: ReadonlySet; + + public constructor(rootNamespaces: Iterable) { this.namespaces = allNamespacesRecursively(rootNamespaces); } - get names(): ReadonlyMap { + public get names(): ReadonlyMap { return this._names; } - isReadyToBeNamed = (named: Name): boolean => { + public isReadyToBeNamed(named: Name): boolean { if (this._names.has(named)) return false; return named.dependencies.every((n: Name) => this._names.has(n)); - }; + } - areForbiddensFullyNamed(namespace: Namespace): boolean { - return iterableEvery(namespace.forbiddenNameds, n => this._names.has(n)); + public areForbiddensFullyNamed(namespace: Namespace): boolean { + return iterableEvery(namespace.forbiddenNameds, (n) => + this._names.has(n), + ); } - isConflicting = (namedNamespace: Namespace, proposed: string): boolean => { + public isConflicting(namedNamespace: Namespace, proposed: string): boolean { const namedsForProposed = this._namedsForName.get(proposed); // If the name is not assigned at all, there is no conflict. if (namedsForProposed === undefined) return false; // The name is assigned, but it might still not be forbidden. for (const n of namedsForProposed) { - if (namedNamespace.members.has(n) || namedNamespace.forbiddenNameds.has(n)) { + if ( + namedNamespace.members.has(n) || + namedNamespace.forbiddenNameds.has(n) + ) { return true; } } + return false; - }; + } - assign = (named: Name, namedNamespace: Namespace, name: string): void => { + public assign(named: Name, namedNamespace: Namespace, name: string): void { assert(!this.names.has(named), `Name "${name}" assigned twice`); - assert(!this.isConflicting(namedNamespace, name), `Assigned name "${name}" conflicts`); + assert( + !this.isConflicting(namedNamespace, name), + `Assigned name "${name}" conflicts`, + ); this._names.set(named, name); let namedsForName = this._namedsForName.get(name); if (namedsForName === undefined) { namedsForName = new Set(); this._namedsForName.set(name, namedsForName); } + namedsForName.add(named); - }; + } } // Naming algorithm -export function assignNames(rootNamespaces: Iterable): ReadonlyMap { +export function assignNames( + rootNamespaces: Iterable, +): ReadonlyMap { const ctx = new NamingContext(rootNamespaces); // Assign all fixed names. @@ -377,42 +457,64 @@ export function assignNames(rootNamespaces: Iterable): ReadonlyMap ctx.areForbiddensFullyNamed(ns)); - const readyNamespace = iterableFind(unfinishedNamespaces, ns => iterableSome(ns.members, ctx.isReadyToBeNamed)); + const unfinishedNamespaces = setFilter(ctx.namespaces, (ns) => + ctx.areForbiddensFullyNamed(ns), + ); + const readyNamespace = iterableFind(unfinishedNamespaces, (ns) => + iterableSome(ns.members, (member) => ctx.isReadyToBeNamed(member)), + ); if (readyNamespace === undefined) { // FIXME: Check for cycles? return ctx.names; } - const allForbiddenNames = setUnion(readyNamespace.members, readyNamespace.forbiddenNameds); - let forbiddenNames = setFilterMap(allForbiddenNames, n => ctx.names.get(n)); + const allForbiddenNames = setUnion( + readyNamespace.members, + readyNamespace.forbiddenNameds, + ); + const forbiddenNames = setFilterMap(allForbiddenNames, (n) => + ctx.names.get(n), + ); // 2. From low order to high order, sort those names into sets where all // members of a set propose the same name and have the same naming // function. for (;;) { - const allReadyNames = setFilter(readyNamespace.members, ctx.isReadyToBeNamed); - const minOrderName = iterableMinBy(allReadyNames, n => n.order); + const allReadyNames = setFilter(readyNamespace.members, (member) => + ctx.isReadyToBeNamed(member), + ); + const minOrderName = iterableMinBy(allReadyNames, (n) => n.order); if (minOrderName === undefined) break; const minOrder = minOrderName.order; - const readyNames = setFilter(allReadyNames, n => n.order === minOrder); + const readyNames = setFilter( + allReadyNames, + (n) => n.order === minOrder, + ); // It would be nice if we had tuples, then we wouldn't have to do this in // two steps. - const byNamingFunction = setGroupBy(readyNames, n => n.namingFunction); + const byNamingFunction = setGroupBy( + readyNames, + (n) => n.namingFunction, + ); for (const [namer, namedsForNamingFunction] of byNamingFunction) { - const byProposed = setGroupBy(namedsForNamingFunction, n => - n.namingFunction.nameStyle(n.firstProposedName(ctx.names)) + const byProposed = setGroupBy(namedsForNamingFunction, (n) => + n.namingFunction.nameStyle(n.firstProposedName(ctx.names)), ); for (const [, nameds] of byProposed) { // 3. Use each set's naming function to name its members. - const names = namer.assignNames(ctx.names, forbiddenNames, nameds); + const names = namer.assignNames( + ctx.names, + forbiddenNames, + nameds, + ); for (const [name, assigned] of names) { ctx.assign(name, readyNamespace, assigned); } + setUnionInto(forbiddenNames, names.values()); } } diff --git a/packages/quicktype-core/src/Renderer.ts b/packages/quicktype-core/src/Renderer.ts index bd9badc6f..f151da0b5 100644 --- a/packages/quicktype-core/src/Renderer.ts +++ b/packages/quicktype-core/src/Renderer.ts @@ -1,28 +1,47 @@ import { iterableEnumerate } from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Name, Namespace, assignNames } from "./Naming"; -import { Source, Sourcelike, NewlineSource, annotated, sourcelikeToSource, newline } from "./Source"; -import { AnnotationData, IssueAnnotationData } from "./Annotation"; +import { type AnnotationData, IssueAnnotationData } from "./Annotation"; +import { type Name, type Namespace, assignNames } from "./Naming"; +import { + type NewlineSource, + type Source, + type Sourcelike, + annotated, + newline, + sourcelikeToSource, +} from "./Source"; +import type { Comment } from "./support/Comments"; import { assert, panic } from "./support/Support"; -import { TargetLanguage } from "./TargetLanguage"; +import type { TargetLanguage } from "./TargetLanguage"; +import type { TypeGraph } from "./Type/TypeGraph"; -export type RenderResult = { - sources: ReadonlyMap; +export interface RenderResult { names: ReadonlyMap; -}; + sources: ReadonlyMap; +} -export type BlankLinePosition = "none" | "interposing" | "leading" | "leading-and-interposing"; +export type BlankLinePosition = + | "none" + | "interposing" + | "leading" + | "leading-and-interposing"; export type BlankLineConfig = BlankLinePosition | [BlankLinePosition, number]; -function getBlankLineConfig(cfg: BlankLineConfig): { position: BlankLinePosition; count: number } { +function getBlankLineConfig(cfg: BlankLineConfig): { + count: number; + position: BlankLinePosition; +} { if (Array.isArray(cfg)) { return { position: cfg[0], count: cfg[1] }; } + return { position: cfg, count: 1 }; } -function lineIndentation(line: string): { indent: number; text: string | null } { +function lineIndentation(line: string): { + indent: number; + text: string | null; +} { const len = line.length; let indent = 0; for (let i = 0; i < len; i++) { @@ -35,100 +54,114 @@ function lineIndentation(line: string): { indent: number; text: string | null } return { indent, text: line.substring(i) }; } } + return { indent: 0, text: null }; } -export type RenderContext = { +export interface RenderContext { + leadingComments?: Comment[]; typeGraph: TypeGraph; - leadingComments: string[] | undefined; -}; +} export type ForEachPosition = "first" | "last" | "middle" | "only"; class EmitContext { private _lastNewline?: NewlineSource; - // @ts-ignore: Initialized in startEmit, which is called from the constructor - private _emitted: Sourcelike[]; - // @ts-ignore: Initialized in startEmit, which is called from the constructor - private _currentEmitTarget: Sourcelike[]; - // @ts-ignore: Initialized in startEmit, which is called from the constructor + + private readonly _emitted: Sourcelike[]; + + private readonly _currentEmitTarget: Sourcelike[]; + private _numBlankLinesNeeded: number; - // @ts-ignore: Initialized in startEmit, which is called from the constructor + private _preventBlankLine: boolean; - constructor() { + public constructor() { this._currentEmitTarget = this._emitted = []; this._numBlankLinesNeeded = 0; this._preventBlankLine = true; // no blank lines at start of file } - get isEmpty(): boolean { + public get isEmpty(): boolean { return this._emitted.length === 0; } - get isNested(): boolean { + public get isNested(): boolean { return this._emitted !== this._currentEmitTarget; } - get source(): Sourcelike[] { + public get source(): Sourcelike[] { return this._emitted; } - private pushItem(item: Sourcelike): void { + public pushItem(item: Sourcelike): void { this._currentEmitTarget.push(item); this._preventBlankLine = false; } - emitNewline(): void { + public emitNewline(): void { const nl = newline(); this.pushItem(nl); this._lastNewline = nl; } - emitItem(item: Sourcelike): void { + public emitItem(item: Sourcelike): void { if (!this.isEmpty) { for (let i = 0; i < this._numBlankLinesNeeded; i++) { this.emitNewline(); } } + this._numBlankLinesNeeded = 0; this.pushItem(item); } - containsItem(item: Sourcelike): boolean { - const existingItem = this._currentEmitTarget.find((value: Sourcelike) => item === value); + public containsItem(item: Sourcelike): boolean { + const existingItem = this._currentEmitTarget.find( + (value: Sourcelike) => item === value, + ); return existingItem !== undefined; } - ensureBlankLine(numBlankLines: number): void { + public ensureBlankLine(numBlankLines: number): void { if (this._preventBlankLine) return; - this._numBlankLinesNeeded = Math.max(this._numBlankLinesNeeded, numBlankLines); + this._numBlankLinesNeeded = Math.max( + this._numBlankLinesNeeded, + numBlankLines, + ); } - preventBlankLine(): void { + public preventBlankLine(): void { this._numBlankLinesNeeded = 0; this._preventBlankLine = true; } - changeIndent(offset: number): void { + public changeIndent(offset: number): void { if (this._lastNewline === undefined) { - return panic("Cannot change indent for the first line"); + panic("Cannot change indent for the first line"); } + this._lastNewline.indentationChange += offset; } } export abstract class Renderer { protected readonly typeGraph: TypeGraph; - protected readonly leadingComments: string[] | undefined; + + protected readonly leadingComments: Comment[] | undefined; private _names: ReadonlyMap | undefined; - private _finishedFiles: Map; - private _finishedEmitContexts: Map; + + private readonly _finishedFiles: Map; + + private readonly _finishedEmitContexts: Map; private _emitContext: EmitContext; - constructor(protected readonly targetLanguage: TargetLanguage, renderContext: RenderContext) { + public constructor( + protected readonly targetLanguage: TargetLanguage, + renderContext: RenderContext, + ) { this.typeGraph = renderContext.typeGraph; this.leadingComments = renderContext.leadingComments; @@ -137,19 +170,20 @@ export abstract class Renderer { this._emitContext = new EmitContext(); } - ensureBlankLine(numBlankLines = 1): void { + // FIXME: make protected once JavaDateTimeRenderer is refactored + public ensureBlankLine(numBlankLines = 1): void { this._emitContext.ensureBlankLine(numBlankLines); } - preventBlankLine(): void { + protected preventBlankLine(): void { this._emitContext.preventBlankLine(); } - emitItem(item: Sourcelike): void { + protected emitItem(item: Sourcelike): void { this._emitContext.emitItem(item); } - emitItemOnce(item: Sourcelike): boolean { + protected emitItemOnce(item: Sourcelike): boolean { if (this._emitContext.containsItem(item)) { return false; } @@ -158,7 +192,7 @@ export abstract class Renderer { return true; } - emitLineOnce(...lineParts: Sourcelike[]): void { + protected emitLineOnce(...lineParts: Sourcelike[]): void { let lineEmitted = true; if (lineParts.length === 1) { lineEmitted = this.emitItemOnce(lineParts[0]); @@ -171,16 +205,18 @@ export abstract class Renderer { } } - emitLine(...lineParts: Sourcelike[]): void { + // FIXME: make protected once JavaDateTimeRenderer is refactored + public emitLine(...lineParts: Sourcelike[]): void { if (lineParts.length === 1) { this._emitContext.emitItem(lineParts[0]); } else if (lineParts.length > 1) { this._emitContext.emitItem(lineParts); } + this._emitContext.emitNewline(); } - emitMultiline(linesString: string): void { + protected emitMultiline(linesString: string): void { const lines = linesString.split("\n"); const numLines = lines.length; if (numLines === 0) return; @@ -199,64 +235,82 @@ export abstract class Renderer { this._emitContext.emitNewline(); } } + if (currentIndent !== 0) { this.changeIndent(-currentIndent); } } - gatherSource(emitter: () => void): Sourcelike[] { + protected gatherSource(emitter: () => void): Sourcelike[] { const oldEmitContext = this._emitContext; this._emitContext = new EmitContext(); emitter(); - assert(!this._emitContext.isNested, "emit context not restored correctly"); + assert( + !this._emitContext.isNested, + "emit context not restored correctly", + ); const source = this._emitContext.source; this._emitContext = oldEmitContext; return source; } - emitGatheredSource(items: Sourcelike[]): void { + protected emitGatheredSource(items: Sourcelike[]): void { for (const item of items) { this._emitContext.emitItem(item); } } - emitAnnotated(annotation: AnnotationData, emitter: () => void): void { + protected emitAnnotated( + annotation: AnnotationData, + emitter: () => void, + ): void { const lines = this.gatherSource(emitter); const source = sourcelikeToSource(lines); this._emitContext.emitItem(annotated(annotation, source)); } - emitIssue(message: string, emitter: () => void): void { + protected emitIssue(message: string, emitter: () => void): void { this.emitAnnotated(new IssueAnnotationData(message), emitter); } protected emitTable = (tableArray: Sourcelike[][]): void => { if (tableArray.length === 0) return; - const table = tableArray.map(r => r.map(sl => sourcelikeToSource(sl))); + const table = tableArray.map((r) => + r.map((sl) => sourcelikeToSource(sl)), + ); this._emitContext.emitItem({ kind: "table", table }); this._emitContext.emitNewline(); }; - changeIndent(offset: number): void { + protected changeIndent(offset: number): void { this._emitContext.changeIndent(offset); } - iterableForEach(iterable: Iterable, emitter: (v: T, position: ForEachPosition) => void): void { + protected iterableForEach( + iterable: Iterable, + emitter: (v: T, position: ForEachPosition) => void, + ): void { const items = Array.from(iterable); let onFirst = true; for (const [i, v] of iterableEnumerate(items)) { const position = - items.length === 1 ? "only" : onFirst ? "first" : i === items.length - 1 ? "last" : "middle"; + items.length === 1 + ? "only" + : onFirst + ? "first" + : i === items.length - 1 + ? "last" + : "middle"; emitter(v, position); onFirst = false; } } - forEach( + protected forEach( iterable: Iterable<[K, V]>, interposedBlankLines: number, leadingBlankLines: number, - emitter: (v: V, k: K, position: ForEachPosition) => void + emitter: (v: V, k: K, position: ForEachPosition) => void, ): boolean { let didEmit = false; this.iterableForEach(iterable, ([k, v], position) => { @@ -265,24 +319,35 @@ export abstract class Renderer { } else { this.ensureBlankLine(interposedBlankLines); } + emitter(v, k, position); didEmit = true; }); return didEmit; } - forEachWithBlankLines( + protected forEachWithBlankLines( iterable: Iterable<[K, V]>, blankLineConfig: BlankLineConfig, - emitter: (v: V, k: K, position: ForEachPosition) => void + emitter: (v: V, k: K, position: ForEachPosition) => void, ): boolean { const { position, count } = getBlankLineConfig(blankLineConfig); - const interposing = ["interposing", "leading-and-interposing"].indexOf(position) >= 0; - const leading = ["leading", "leading-and-interposing"].indexOf(position) >= 0; - return this.forEach(iterable, interposing ? count : 0, leading ? count : 0, emitter); - } - - indent(fn: () => void): void { + const interposing = ["interposing", "leading-and-interposing"].includes( + position, + ); + const leading = ["leading", "leading-and-interposing"].includes( + position, + ); + return this.forEach( + iterable, + interposing ? count : 0, + leading ? count : 0, + emitter, + ); + } + + // FIXME: make protected once JavaDateTimeRenderer is refactored + public indent(fn: () => void): void { this.changeIndent(1); fn(); this.changeIndent(-1); @@ -291,13 +356,15 @@ export abstract class Renderer { protected abstract setUpNaming(): Iterable; protected abstract emitSource(givenOutputFilename: string): void; - private assignNames(): ReadonlyMap { + protected assignNames(): ReadonlyMap { return assignNames(this.setUpNaming()); } protected initializeEmitContextForFilename(filename: string): void { if (this._finishedEmitContexts.has(filename.toLowerCase())) { - const existingEmitContext = this._finishedEmitContexts.get(filename.toLowerCase()); + const existingEmitContext = this._finishedEmitContexts.get( + filename.toLowerCase(), + ); if (existingEmitContext !== undefined) { this._emitContext = existingEmitContext; } @@ -307,7 +374,7 @@ export abstract class Renderer { protected finishFile(filename: string): void { if (this._finishedFiles.has(filename)) { console.log( - `[WARNING] Tried to emit file ${filename} more than once. If performing multi-file output this warning can be safely ignored.` + `[WARNING] Tried to emit file ${filename} more than once. If performing multi-file output this warning can be safely ignored.`, ); } @@ -315,23 +382,28 @@ export abstract class Renderer { this._finishedFiles.set(filename, source); // [Michael Fey (@MrRooni), 2019-5-9] We save the current EmitContext for possible reuse later. We put it into the map with a lowercased version of the key so we can do a case-insensitive lookup later. The reason we lowercase it is because some schema (looking at you keyword-unions.schema) define objects of the same name with different casing. BOOL vs. bool, for example. - this._finishedEmitContexts.set(filename.toLowerCase(), this._emitContext); + this._finishedEmitContexts.set( + filename.toLowerCase(), + this._emitContext, + ); this._emitContext = new EmitContext(); } - render(givenOutputFilename: string): RenderResult { + public render(givenOutputFilename: string): RenderResult { this._names = this.assignNames(); this.emitSource(givenOutputFilename); if (!this._emitContext.isEmpty) { this.finishFile(givenOutputFilename); } + return { sources: this._finishedFiles, names: this._names }; } - get names(): ReadonlyMap { + public get names(): ReadonlyMap { if (this._names === undefined) { return panic("Names accessed before they were assigned"); } + return this._names; } } diff --git a/packages/quicktype-core/src/RendererOptions.ts b/packages/quicktype-core/src/RendererOptions.ts deleted file mode 100644 index 9ef964b42..000000000 --- a/packages/quicktype-core/src/RendererOptions.ts +++ /dev/null @@ -1,185 +0,0 @@ -import { assert } from "./support/Support"; -import { messageError } from "./Messages"; -import { hasOwnProperty } from "collection-utils"; - -/** - * Primary options show up in the web UI in the "Language" settings tab, - * secondary options in "Other". - */ -export type OptionKind = "primary" | "secondary"; - -export interface OptionDefinition { - name: string; - type: StringConstructor | BooleanConstructor; - kind?: OptionKind; - renderer?: boolean; - alias?: string; - multiple?: boolean; - defaultOption?: boolean; - defaultValue?: any; - typeLabel?: string; - description: string; - legalValues?: string[]; -} - -/** - * The superclass for target language options. You probably want to use one of its - * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. - */ -export abstract class Option { - readonly definition: OptionDefinition; - - constructor(definition: OptionDefinition) { - definition.renderer = true; - this.definition = definition; - assert(definition.kind !== undefined, "Renderer option kind must be defined"); - } - - getValue(values: { [name: string]: any }): T { - const value = values[this.definition.name]; - if (value === undefined) { - return this.definition.defaultValue; - } - return value; - } - - get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { - return { actual: [this.definition], display: [this.definition] }; - } -} - -export type OptionValueType = O extends Option ? T : never; -export type OptionValues = { [P in keyof T]: OptionValueType }; - -export function getOptionValues }>( - options: T, - untypedOptionValues: { [name: string]: any } -): OptionValues { - const optionValues: { [name: string]: any } = {}; - for (const name of Object.getOwnPropertyNames(options)) { - optionValues[name] = options[name].getValue(untypedOptionValues); - } - return optionValues as OptionValues; -} - -/** - * A target language option that allows setting a boolean flag. - */ -export class BooleanOption extends Option { - /** - * @param name The shorthand name. - * @param description Short-ish description of the option. - * @param defaultValue The default value. - * @param kind Whether it's a primary or secondary option. - */ - constructor(name: string, description: string, defaultValue: boolean, kind: OptionKind = "primary") { - super({ - name, - kind, - type: Boolean, - description, - defaultValue - }); - } - - get cliDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { - const negated = Object.assign({}, this.definition, { - name: `no-${this.definition.name}`, - defaultValue: !this.definition.defaultValue - }); - const display = Object.assign({}, this.definition, { - name: `[no-]${this.definition.name}`, - description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)` - }); - return { - display: [display], - actual: [this.definition, negated] - }; - } - - getValue(values: { [name: string]: any }): boolean { - let value = values[this.definition.name]; - if (value === undefined) { - value = this.definition.defaultValue; - } - - let negated = values[`no-${this.definition.name}`]; - if (negated === undefined) { - negated = !this.definition.defaultValue; - } - - if (value === "true") { - value = true; - } else if (value === "false") { - value = false; - } - - if (this.definition.defaultValue) { - return value && !negated; - } else { - return value || !negated; - } - } -} - -export class StringOption extends Option { - constructor( - name: string, - description: string, - typeLabel: string, - defaultValue: string, - kind: OptionKind = "primary" - ) { - const definition = { - name, - kind, - type: String, - description, - typeLabel, - defaultValue - }; - super(definition); - } -} - -export class EnumOption extends Option { - private readonly _values: { [name: string]: T }; - - constructor( - name: string, - description: string, - values: [string, T][], - defaultValue: string | undefined = undefined, - kind: OptionKind = "primary" - ) { - if (defaultValue === undefined) { - defaultValue = values[0][0]; - } - const definition = { - name, - kind, - type: String, - description, - typeLabel: values.map(([n, _]) => n).join("|"), - legalValues: values.map(([n, _]) => n), - defaultValue - }; - super(definition); - - this._values = {}; - for (const [n, v] of values) { - this._values[n] = v; - } - } - - getValue(values: { [name: string]: any }): T { - let name: string = values[this.definition.name]; - if (name === undefined) { - name = this.definition.defaultValue; - } - if (!hasOwnProperty(this._values, name)) { - return messageError("RendererUnknownOptionValue", { value: name, name: this.definition.name }); - } - return this._values[name]; - } -} diff --git a/packages/quicktype-core/src/RendererOptions/index.ts b/packages/quicktype-core/src/RendererOptions/index.ts new file mode 100644 index 000000000..72d9902fb --- /dev/null +++ b/packages/quicktype-core/src/RendererOptions/index.ts @@ -0,0 +1,193 @@ +import { messageError } from "../Messages"; +import { assert } from "../support/Support"; +import type { LanguageName, RendererOptions } from "../types"; + +import type { OptionDefinition, OptionKind, OptionValues } from "./types"; + +export * from "./types"; + +/** + * The superclass for target language options. You probably want to use one of its + * subclasses, `BooleanOption`, `EnumOption`, or `StringOption`. + */ +export abstract class Option { + public readonly definition: OptionDefinition; + + public constructor(definition: OptionDefinition) { + this.definition = definition; + assert( + definition.kind !== undefined, + "Renderer option kind must be defined", + ); + } + + public get name(): Name { + return this.definition.name; + } + + public getValue(values: Record): T { + return (values[this.name] ?? this.definition.defaultValue) as T; + } + + public get cliDefinitions(): { + actual: Array>; + display: Array>; + } { + return { actual: [this.definition], display: [this.definition] }; + } +} + +export function getOptionValues< + const Options extends Record>, + Lang extends LanguageName, +>( + options: Options, + untypedOptionValues: RendererOptions, +): OptionValues { + const optionValues: Record = {}; + + for (const [key, option] of Object.entries(options)) { + const value = option.getValue(untypedOptionValues); + if (option instanceof EnumOption) { + optionValues[key] = option.getEnumValue(value as string); + } else { + optionValues[key] = value; + } + } + + return optionValues as OptionValues; +} + +/** + * A target language option that allows setting a boolean flag. + */ +export class BooleanOption extends Option { + /** + * @param name The shorthand name. + * @param description Short-ish description of the option. + * @param defaultValue The default value. + * @param kind Whether it's a primary or secondary option. + */ + public constructor( + name: Name, + description: string, + defaultValue: boolean, + kind: OptionKind = "primary", + ) { + super({ + name, + kind, + optionType: "boolean", + description, + defaultValue, + }); + } + + public get cliDefinitions(): { + actual: Array>; + display: Array>; + } { + const negated = Object.assign({}, this.definition, { + name: `no-${this.name}`, + defaultValue: !this.definition.defaultValue, + }); + const display = Object.assign({}, this.definition, { + name: `[no-]${this.name}`, + description: `${this.definition.description} (${this.definition.defaultValue ? "on" : "off"} by default)`, + }); + return { + display: [display], + actual: [this.definition, negated], + }; + } + + public getValue(values: Record): boolean { + let value = values[this.name]; + if (value === undefined) { + value = this.definition.defaultValue; + } + + let negated = values[`no-${this.name}`]; + if (negated === undefined) { + negated = !this.definition.defaultValue; + } + + if (value === "true") { + value = true; + } else if (value === "false") { + value = false; + } + + if (this.definition.defaultValue) { + return (value && !negated) as boolean; + } + + return (value || !negated) as boolean; + } +} + +export class StringOption extends Option { + public constructor( + name: Name, + description: string, + typeLabel: string, + defaultValue: string, + kind: OptionKind = "primary", + ) { + super({ + name, + kind, + optionType: "string", + description, + typeLabel, + defaultValue, + }); + } +} + +export class EnumOption< + Name extends string, + const EnumMap extends Record, + EnumKey extends Extract = Extract< + keyof EnumMap, + string + >, +> extends Option { + private readonly _values: EnumMap; + + public constructor( + name: Name, + description: string, + values: EnumMap, + defaultValue: NoInfer, + kind: OptionKind = "primary", + ) { + super({ + name, + kind, + optionType: "enum", + description, + typeLabel: Object.keys(values).join("|"), + defaultValue, + values, + }); + + this._values = values; + } + + public getEnumValue(name: Key): EnumMap[Key] { + if (!name) { + const defaultKey = this.definition.defaultValue as NonNullable; + return this._values[defaultKey]; + } + + if (!(name in this._values)) { + return messageError("RendererUnknownOptionValue", { + value: name, + name: this.name, + }); + } + + return this._values[name]; + } +} diff --git a/packages/quicktype-core/src/RendererOptions/types.ts b/packages/quicktype-core/src/RendererOptions/types.ts new file mode 100644 index 000000000..f9f1be825 --- /dev/null +++ b/packages/quicktype-core/src/RendererOptions/types.ts @@ -0,0 +1,59 @@ +import type { EnumOption, Option } from "./index"; +import type { OptionDefinition as CommandLineArgsOptionDefinition } from "command-line-args"; + +/** + * Primary options show up in the web UI in the "Language" settings tab, + * Secondary options in "Other". + * CLI is only for cli + */ +export type OptionKind = "primary" | "secondary" | "cli"; +export type OptionType = "string" | "boolean" | "enum"; + +export interface OptionDefinition + extends CommandLineArgsOptionDefinition { + /** Option Name */ + name: Name; + /** Option Description */ + description: string; + /** Category of Option */ + optionType: OptionType; + /** Default Value for Option */ + defaultValue?: T; + /** Enum only, map of possible keys and values */ + values?: Record; + + /** Primary, Secondary, or CLI */ + kind?: OptionKind; + /** Whether multiple CLI inputs are allowed for this option */ + multiple?: boolean; + + // Unknown + typeLabel?: string; +} + +export type OptionName = O extends Option + ? Name + : never; +export type OptionValue = O extends EnumOption< + string, + infer EnumMap, + infer EnumKey +> + ? EnumMap[EnumKey] + : O extends Option + ? Value + : never; + +export type OptionKey = O extends EnumOption< + string, + Record, + infer EnumKey +> + ? EnumKey + : O; + +// FIXME: Merge these and use camelCase user-facing keys (v24) +export type OptionMap = { + [K in keyof T as OptionName]: OptionKey; +}; // user-facing, keys are `name` property of Option, values are the available input type +export type OptionValues = { [K in keyof T]: OptionValue }; // internal, keys are keys of `_Options` object in each language file diff --git a/packages/quicktype-core/src/Run.ts b/packages/quicktype-core/src/Run.ts index 57db411db..85a48c848 100644 --- a/packages/quicktype-core/src/Run.ts +++ b/packages/quicktype-core/src/Run.ts @@ -1,172 +1,117 @@ import { mapFirst } from "collection-utils"; +import { initTypeNames } from "./attributes/TypeNames"; +import { InputData } from "./input/Inputs"; import * as targetLanguages from "./language/All"; -import { TargetLanguage, MultiFileRenderResult } from "./TargetLanguage"; -import { SerializedRenderResult, Annotation, Location, Span } from "./Source"; -import { assert } from "./support/Support"; +import type { RendererOptions } from "./language/options.types"; +import type { LanguageName } from "./language/types"; import { combineClasses } from "./rewrites/CombineClasses"; -import { inferMaps } from "./rewrites/InferMaps"; -import { TypeBuilder, StringTypeMapping } from "./TypeBuilder"; -import { TypeGraph, noneToAny, optionalToNullable, removeIndirectionIntersections } from "./TypeGraph"; -import { initTypeNames } from "./attributes/TypeNames"; -import { gatherNames } from "./GatherNames"; import { expandStrings } from "./rewrites/ExpandStrings"; +import { flattenStrings } from "./rewrites/FlattenStrings"; import { flattenUnions } from "./rewrites/FlattenUnions"; -import { resolveIntersections } from "./rewrites/ResolveIntersections"; +import { inferMaps } from "./rewrites/InferMaps"; import { replaceObjectType } from "./rewrites/ReplaceObjectType"; -import { messageError } from "./Messages"; -import { InputData } from "./input/Inputs"; -import { flattenStrings } from "./rewrites/FlattenStrings"; -import { makeTransformations } from "./MakeTransformations"; -import { TransformedStringTypeKind } from "./Type"; +import { resolveIntersections } from "./rewrites/ResolveIntersections"; +import type { Comment } from "./support/Comments"; +import { assert } from "./support/Support"; -export function getTargetLanguage(nameOrInstance: string | TargetLanguage): TargetLanguage { +import { gatherNames } from "./GatherNames"; +import { + type InferenceFlags, + defaultInferenceFlags, + inferenceFlagNames, + inferenceFlags, +} from "./Inference"; +import { makeTransformations } from "./MakeTransformations"; +import { messageError } from "./Messages"; +import type { + Annotation, + Location, + SerializedRenderResult, + Span, +} from "./Source"; +import type { MultiFileRenderResult, TargetLanguage } from "./TargetLanguage"; +import { TypeBuilder } from "./Type/TypeBuilder"; +import type { StringTypeMapping } from "./Type/TypeBuilderUtils"; +import { TypeGraph } from "./Type/TypeGraph"; +import { + noneToAny, + optionalToNullable, + removeIndirectionIntersections, +} from "./Type/TypeGraphUtils"; + +export function getTargetLanguage( + nameOrInstance: LanguageName | TargetLanguage, +): TargetLanguage { if (typeof nameOrInstance === "object") { return nameOrInstance; } + const language = targetLanguages.languageNamed(nameOrInstance); if (language !== undefined) { return language; } - return messageError("DriverUnknownOutputLanguage", { lang: nameOrInstance }); -} -export type RendererOptions = { [name: string]: string | boolean }; - -export interface InferenceFlag { - description: string; - negationDescription: string; - explanation: string; - order: number; - stringType?: TransformedStringTypeKind; + return messageError("DriverUnknownOutputLanguage", { + lang: nameOrInstance, + }); } -export const inferenceFlagsObject = { - /** Whether to infer map types from JSON data */ - inferMaps: { - description: "Detect maps", - negationDescription: "Don't infer maps, always use classes", - explanation: "Infer maps when object keys look like map keys.", - order: 1 - }, - /** Whether to infer enum types from JSON data */ - inferEnums: { - description: "Detect enums", - negationDescription: "Don't infer enums, always use strings", - explanation: "If string values occur within a relatively small domain,\ninfer them as enum values.", - order: 2 - }, - /** Whether to convert UUID strings to UUID objects */ - inferUuids: { - description: "Detect UUIDs", - negationDescription: "Don't convert UUIDs to UUID objects", - explanation: "Detect UUIDs like '123e4567-e89b-12d3-a456-426655440000' (partial support).", - stringType: "uuid" as TransformedStringTypeKind, - order: 3 - }, - /** Whether to assume that JSON strings that look like dates are dates */ - inferDateTimes: { - description: "Detect dates & times", - negationDescription: "Don't infer dates or times", - explanation: "Infer dates from strings (partial support).", - stringType: "date-time" as TransformedStringTypeKind, - order: 4 - }, - /** Whether to convert stringified integers to integers */ - inferIntegerStrings: { - description: "Detect integers in strings", - negationDescription: "Don't convert stringified integers to integers", - explanation: 'Automatically convert stringified integers to integers.\nFor example, "1" is converted to 1.', - stringType: "integer-string" as TransformedStringTypeKind, - order: 5 - }, - /** Whether to convert stringified booleans to boolean values */ - inferBooleanStrings: { - description: "Detect booleans in strings", - negationDescription: "Don't convert stringified booleans to booleans", - explanation: - 'Automatically convert stringified booleans to booleans.\nFor example, "true" is converted to true.', - stringType: "bool-string" as TransformedStringTypeKind, - order: 6 - }, - /** Combine similar classes. This doesn't apply to classes from a schema, only from inference. */ - combineClasses: { - description: "Merge similar classes", - negationDescription: "Don't combine similar classes", - explanation: - "Combine classes with significantly overlapping properties,\ntreating contingent properties as nullable.", - order: 7 - }, - /** Whether to treat $ref as references within JSON */ - ignoreJsonRefs: { - description: "Don't treat $ref as a reference in JSON", - negationDescription: "Treat $ref as a reference in JSON", - explanation: - "Like in JSON Schema, allow objects like\n'{ $ref: \"#/foo/bar\" }' to refer\nto another part of the input.", - order: 8 - } -}; -export type InferenceFlagName = keyof typeof inferenceFlagsObject; -export const inferenceFlagNames = Object.getOwnPropertyNames(inferenceFlagsObject) as InferenceFlagName[]; -export const inferenceFlags: { [F in InferenceFlagName]: InferenceFlag } = inferenceFlagsObject; - -export type InferenceFlags = { [F in InferenceFlagName]: boolean }; - /** * The options type for the main quicktype entry points, * `quicktypeMultiFile` and `quicktype`. */ -export type NonInferenceOptions = { - /** - * The target language for which to produce code. This can be either an instance of `TargetLanguage`, - * or a string specifying one of the names for quicktype's built-in target languages. For example, - * both `cs` and `csharp` will generate C#. - */ - lang: string | TargetLanguage; - /** The input data from which to produce types */ - inputData: InputData; - /** Put class properties in alphabetical order, instead of in the order found in the JSON */ - alphabetizeProperties: boolean; +export interface NonInferenceOptions { /** Make all class property optional */ allPropertiesOptional: boolean; + /** Put class properties in alphabetical order, instead of in the order found in the JSON */ + alphabetizeProperties: boolean; + /** Check that we're propagating all type attributes (unless we actually can't) */ + checkProvenance: boolean; /** - * Make top-levels classes from JSON fixed. That means even if two top-level classes are exactly - * the same, quicktype will still generate two separate types for them. - */ - fixedTopLevels: boolean; - /** Don't render output. This is mainly useful for benchmarking. */ - noRender: boolean; - /** If given, output these comments at the beginning of the main output file */ - leadingComments: string[] | undefined; - /** Options for the target language's renderer */ - rendererOptions: RendererOptions; - /** String to use for one indentation level. If not given, use the target language's default. */ - indentation: string | undefined; - /** Name of the output file. Note that quicktype will not write that file, but you'll get its name - * back as a key in the resulting `Map`. + * Print name gathering debug information to the console. This might help to figure out why + * your types get weird names, but the output is quite arcane. */ - outputFilename: string; + debugPrintGatherNames: boolean; /** Print the type graph to the console at every processing step */ debugPrintGraph: boolean; - /** Check that we're propagating all type attributes (unless we actually can't) */ - checkProvenance: boolean; /** * Print type reconstitution debug information to the console. You'll only ever need this if * you're working deep inside quicktype-core. */ debugPrintReconstitution: boolean; - /** - * Print name gathering debug information to the console. This might help to figure out why - * your types get weird names, but the output is quite arcane. - */ - debugPrintGatherNames: boolean; - /** Print all transformations to the console prior to generating code */ - debugPrintTransformations: boolean; - /** Print the time it took for each pass to run */ - debugPrintTimes: boolean; /** Print schema resolving steps */ debugPrintSchemaResolving: boolean; -}; + /** Print the time it took for each pass to run */ + debugPrintTimes: boolean; + /** Print all transformations to the console prior to generating code */ + debugPrintTransformations: boolean; + /** + * Make top-levels classes from JSON fixed. That means even if two top-level classes are exactly + * the same, quicktype will still generate two separate types for them. + */ + fixedTopLevels: boolean; + /** String to use for one indentation level. If not given, use the target language's default. */ + indentation: string | undefined; + /** The input data from which to produce types */ + inputData: InputData; + /** + * The target language for which to produce code. This can be either an instance of `TargetLanguage`, + * or a string specifying one of the names for quicktype's built-in target languages. For example, + * both `cs` and `csharp` will generate C#. + */ + lang: Lang | TargetLanguage; + /** If given, output these comments at the beginning of the main output file */ + leadingComments?: Comment[]; + /** Don't render output. This is mainly useful for benchmarking. */ + noRender: boolean; + /** Name of the output file. Note that quicktype will not write that file, but you'll get its name + * back as a key in the resulting `Map`. + */ + outputFilename: string; + /** Options for the target language's renderer */ + rendererOptions: RendererOptions; +} export type Options = NonInferenceOptions & InferenceFlags; @@ -187,52 +132,40 @@ const defaultOptions: NonInferenceOptions = { debugPrintGatherNames: false, debugPrintTransformations: false, debugPrintTimes: false, - debugPrintSchemaResolving: false + debugPrintSchemaResolving: false, }; export interface RunContext { - stringTypeMapping: StringTypeMapping; debugPrintReconstitution: boolean; - debugPrintTransformations: boolean; debugPrintSchemaResolving: boolean; + debugPrintTransformations: boolean; + stringTypeMapping: StringTypeMapping; - timeSync(name: string, f: () => Promise): Promise; - time(name: string, f: () => T): T; + time: (name: string, f: () => T) => T; + timeSync: (name: string, f: () => Promise) => Promise; } interface GraphInputs { - targetLanguage: TargetLanguage; - stringTypeMapping: StringTypeMapping; conflateNumbers: boolean; + stringTypeMapping: StringTypeMapping; + targetLanguage: TargetLanguage; typeBuilder: TypeBuilder; } -function makeDefaultInferenceFlags(): InferenceFlags { - const flags = {} as InferenceFlags; - for (const flag of inferenceFlagNames) { - flags[flag] = true; - } - return flags; -} - -export const defaultInferenceFlags = makeDefaultInferenceFlags(); - class Run implements RunContext { private readonly _options: Options; - constructor(options: Partial) { + public constructor(options: Partial) { // We must not overwrite defaults with undefined values, which // we sometimes get. - this._options = Object.assign({}, defaultOptions, defaultInferenceFlags); - for (const k of Object.getOwnPropertyNames(options)) { - const v = (options as any)[k]; - if (v !== undefined) { - (this._options as any)[k] = v; - } - } + this._options = Object.fromEntries( + Object.entries( + Object.assign({}, defaultOptions, defaultInferenceFlags), + ).map(([k, v]) => [k, options[k as keyof typeof options] ?? v]), + ) as Required; } - get stringTypeMapping(): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { const targetLanguage = getTargetLanguage(this._options.lang); const mapping = new Map(targetLanguage.stringTypeMapping); for (const flag of inferenceFlagNames) { @@ -241,55 +174,68 @@ class Run implements RunContext { mapping.set(stringType, "string"); } } + return mapping; } - get debugPrintReconstitution(): boolean { + public get debugPrintReconstitution(): boolean { return this._options.debugPrintReconstitution === true; } - get debugPrintTransformations(): boolean { + public get debugPrintTransformations(): boolean { return this._options.debugPrintTransformations; } - get debugPrintSchemaResolving(): boolean { + public get debugPrintSchemaResolving(): boolean { return this._options.debugPrintSchemaResolving; } - async timeSync(name: string, f: () => Promise): Promise { + public async timeSync(name: string, f: () => Promise): Promise { const start = Date.now(); const result = await f(); const end = Date.now(); if (this._options.debugPrintTimes) { console.log(`${name} took ${end - start}ms`); } + return result; } - time(name: string, f: () => T): T { + public time(name: string, f: () => T): T { const start = Date.now(); const result = f(); const end = Date.now(); if (this._options.debugPrintTimes) { console.log(`${name} took ${end - start}ms`); } + return result; } private makeGraphInputs(): GraphInputs { const targetLanguage = getTargetLanguage(this._options.lang); const stringTypeMapping = this.stringTypeMapping; - const conflateNumbers = !targetLanguage.supportsUnionsWithBothNumberTypes; + const conflateNumbers = + !targetLanguage.supportsUnionsWithBothNumberTypes; const typeBuilder = new TypeBuilder( - 0, stringTypeMapping, this._options.alphabetizeProperties, this._options.allPropertiesOptional, this._options.checkProvenance, - false + false, + ); + typeBuilder.typeGraph = new TypeGraph( + typeBuilder, + 0, + this._options.checkProvenance, ); - return { targetLanguage, stringTypeMapping, conflateNumbers, typeBuilder }; + return { + targetLanguage, + stringTypeMapping, + conflateNumbers, + typeBuilder, + }; } private async makeGraph(allInputs: InputData): Promise { @@ -303,8 +249,8 @@ class Run implements RunContext { graphInputs.typeBuilder, this._options.inferMaps, this._options.inferEnums, - this._options.fixedTopLevels - ) + this._options.fixedTopLevels, + ), ); return this.processGraph(allInputs, graphInputs); @@ -319,15 +265,23 @@ class Run implements RunContext { graphInputs.typeBuilder, this._options.inferMaps, this._options.inferEnums, - this._options.fixedTopLevels - ) + this._options.fixedTopLevels, + ), ); return this.processGraph(allInputs, graphInputs); } - private processGraph(allInputs: InputData, graphInputs: GraphInputs): TypeGraph { - const { targetLanguage, stringTypeMapping, conflateNumbers, typeBuilder } = graphInputs; + private processGraph( + allInputs: InputData, + graphInputs: GraphInputs, + ): TypeGraph { + const { + targetLanguage, + stringTypeMapping, + conflateNumbers, + typeBuilder, + } = graphInputs; let graph = typeBuilder.finish(); if (this._options.debugPrintGraph) { @@ -337,11 +291,17 @@ class Run implements RunContext { const debugPrintReconstitution = this.debugPrintReconstitution; - if (typeBuilder.didAddForwardingIntersection || !this._options.ignoreJsonRefs) { - this.time( - "remove indirection intersections", - () => (graph = removeIndirectionIntersections(graph, stringTypeMapping, debugPrintReconstitution)) - ); + if ( + typeBuilder.didAddForwardingIntersection || + !this._options.ignoreJsonRefs + ) { + this.time("remove indirection intersections", () => { + graph = removeIndirectionIntersections( + graph, + stringTypeMapping, + debugPrintReconstitution, + ); + }); } let unionsDone = false; @@ -350,141 +310,172 @@ class Run implements RunContext { do { const graphBeforeRewrites = graph; if (!intersectionsDone) { - this.time( - "resolve intersections", - () => - ([graph, intersectionsDone] = resolveIntersections( - graph, - stringTypeMapping, - debugPrintReconstitution - )) - ); + this.time("resolve intersections", () => { + [graph, intersectionsDone] = resolveIntersections( + graph, + stringTypeMapping, + debugPrintReconstitution, + ); + }); } + if (!unionsDone) { - this.time( - "flatten unions", - () => - ([graph, unionsDone] = flattenUnions( - graph, - stringTypeMapping, - conflateNumbers, - true, - debugPrintReconstitution - )) - ); + this.time("flatten unions", () => { + [graph, unionsDone] = flattenUnions( + graph, + stringTypeMapping, + conflateNumbers, + true, + debugPrintReconstitution, + ); + }); } if (graph === graphBeforeRewrites) { - assert(intersectionsDone && unionsDone, "Graph didn't change but we're not done"); + assert( + intersectionsDone && unionsDone, + "Graph didn't change but we're not done", + ); } } while (!intersectionsDone || !unionsDone); } - this.time( - "replace object type", - () => - (graph = replaceObjectType( + this.time("replace object type", () => { + graph = replaceObjectType( + graph, + stringTypeMapping, + conflateNumbers, + targetLanguage.supportsFullObjectType, + debugPrintReconstitution, + ); + }); + do { + this.time("flatten unions", () => { + [graph, unionsDone] = flattenUnions( graph, stringTypeMapping, conflateNumbers, - targetLanguage.supportsFullObjectType, - debugPrintReconstitution - )) - ); - do { - this.time( - "flatten unions", - () => - ([graph, unionsDone] = flattenUnions( - graph, - stringTypeMapping, - conflateNumbers, - false, - debugPrintReconstitution - )) - ); + false, + debugPrintReconstitution, + ); + }); } while (!unionsDone); if (this._options.combineClasses) { const combinedGraph = this.time("combine classes", () => - combineClasses(this, graph, this._options.alphabetizeProperties, true, false, debugPrintReconstitution) + combineClasses( + this, + graph, + this._options.alphabetizeProperties, + true, + false, + debugPrintReconstitution, + ), ); if (combinedGraph === graph) { graph = combinedGraph; } else { - this.time( - "combine classes cleanup", - () => - (graph = combineClasses( - this, - combinedGraph, - this._options.alphabetizeProperties, - false, - true, - debugPrintReconstitution - )) - ); + this.time("combine classes cleanup", () => { + graph = combineClasses( + this, + combinedGraph, + this._options.alphabetizeProperties, + false, + true, + debugPrintReconstitution, + ); + }); } } if (this._options.inferMaps) { for (;;) { const newGraph = this.time("infer maps", () => - inferMaps(graph, stringTypeMapping, true, debugPrintReconstitution) + inferMaps( + graph, + stringTypeMapping, + true, + debugPrintReconstitution, + ), ); if (newGraph === graph) { break; } + graph = newGraph; } } - const enumInference = allInputs.needSchemaProcessing ? "all" : this._options.inferEnums ? "infer" : "none"; - this.time("expand strings", () => (graph = expandStrings(this, graph, enumInference))); - this.time( - "flatten unions", - () => - ([graph, unionsDone] = flattenUnions( - graph, - stringTypeMapping, - conflateNumbers, - false, - debugPrintReconstitution - )) + const enumInference = allInputs.needSchemaProcessing + ? "all" + : this._options.inferEnums + ? "infer" + : "none"; + this.time("expand strings", () => { + graph = expandStrings(this, graph, enumInference); + }); + this.time("flatten unions", () => { + [graph, unionsDone] = flattenUnions( + graph, + stringTypeMapping, + conflateNumbers, + false, + debugPrintReconstitution, + ); + }); + assert( + unionsDone, + "We should only have to flatten unions once after expanding strings", ); - assert(unionsDone, "We should only have to flatten unions once after expanding strings"); if (allInputs.needSchemaProcessing) { - this.time( - "flatten strings", - () => (graph = flattenStrings(graph, stringTypeMapping, debugPrintReconstitution)) - ); + this.time("flatten strings", () => { + graph = flattenStrings( + graph, + stringTypeMapping, + debugPrintReconstitution, + ); + }); } - this.time("none to any", () => (graph = noneToAny(graph, stringTypeMapping, debugPrintReconstitution))); - if (!targetLanguage.supportsOptionalClassProperties) { - this.time( - "optional to nullable", - () => (graph = optionalToNullable(graph, stringTypeMapping, debugPrintReconstitution)) + this.time("none to any", () => { + graph = noneToAny( + graph, + stringTypeMapping, + debugPrintReconstitution, ); - } - - this.time("fixed point", () => (graph = graph.rewriteFixedPoint(false, debugPrintReconstitution))); - - this.time("make transformations", () => (graph = makeTransformations(this, graph, targetLanguage))); - - this.time( - "flatten unions", - () => - ([graph, unionsDone] = flattenUnions( + }); + if (!targetLanguage.supportsOptionalClassProperties) { + this.time("optional to nullable", () => { + graph = optionalToNullable( graph, stringTypeMapping, - conflateNumbers, - false, - debugPrintReconstitution - )) + debugPrintReconstitution, + ); + }); + } + + this.time("fixed point", () => { + graph = graph.rewriteFixedPoint(false, debugPrintReconstitution); + }); + + this.time("make transformations", () => { + graph = makeTransformations(this, graph, targetLanguage); + }); + + this.time("flatten unions", () => { + [graph, unionsDone] = flattenUnions( + graph, + stringTypeMapping, + conflateNumbers, + false, + debugPrintReconstitution, + ); + }); + assert( + unionsDone, + "We should only have to flatten unions once after making transformations", ); - assert(unionsDone, "We should only have to flatten unions once after making transformations"); // Sometimes we combine classes in ways that will the order come out // differently compared to what it would be from the equivalent schema, @@ -493,16 +484,23 @@ class Run implements RunContext { // FIXME: We don't actually have to do this if any of the above graph // rewrites did anything. We could just check whether the current graph // is different from the one we started out with. - this.time( - "GC", - () => (graph = graph.garbageCollect(this._options.alphabetizeProperties, debugPrintReconstitution)) - ); + this.time("GC", () => { + graph = graph.garbageCollect( + this._options.alphabetizeProperties, + debugPrintReconstitution, + ); + }); if (this._options.debugPrintGraph) { console.log("\n# gather names"); } + this.time("gather names", () => - gatherNames(graph, !allInputs.needSchemaProcessing, this._options.debugPrintGatherNames) + gatherNames( + graph, + !allInputs.needSchemaProcessing, + this._options.debugPrintGatherNames, + ), ); if (this._options.debugPrintGraph) { graph.printGraph(); @@ -512,10 +510,9 @@ class Run implements RunContext { } private makeSimpleTextResult(lines: string[]): MultiFileRenderResult { - return new Map([[this._options.outputFilename, { lines, annotations: [] }]] as [ - string, - SerializedRenderResult - ][]); + return new Map([ + [this._options.outputFilename, { lines, annotations: [] }], + ] as Array<[string, SerializedRenderResult]>); } private preRun(): MultiFileRenderResult | [InputData, TargetLanguage] { @@ -524,20 +521,32 @@ class Run implements RunContext { const targetLanguage = getTargetLanguage(this._options.lang); const inputData = this._options.inputData; - const needIR = inputData.needIR || targetLanguage.names.indexOf("schema") < 0; + const needIR = + inputData.needIR || !targetLanguage.names.includes("schema"); - const schemaString = needIR ? undefined : inputData.singleStringSchemaSource(); + const schemaString = needIR + ? undefined + : inputData.singleStringSchemaSource(); if (schemaString !== undefined) { - const lines = JSON.stringify(JSON.parse(schemaString), undefined, 4).split("\n"); + const lines = JSON.stringify( + JSON.parse(schemaString), + undefined, + 4, + ).split("\n"); lines.push(""); const srr = { lines, annotations: [] }; - return new Map([[this._options.outputFilename, srr] as [string, SerializedRenderResult]]); + return new Map([ + [this._options.outputFilename, srr] as [ + string, + SerializedRenderResult, + ], + ]); } return [inputData, targetLanguage]; } - async run(): Promise { + public async run(): Promise { const preRunResult = this.preRun(); if (!Array.isArray(preRunResult)) { return preRunResult; @@ -550,7 +559,7 @@ class Run implements RunContext { return this.renderGraph(targetLanguage, graph); } - runSync(): MultiFileRenderResult { + public runSync(): MultiFileRenderResult { const preRunResult = this.preRun(); if (!Array.isArray(preRunResult)) { return preRunResult; @@ -563,7 +572,10 @@ class Run implements RunContext { return this.renderGraph(targetLanguage, graph); } - private renderGraph(targetLanguage: TargetLanguage, graph: TypeGraph): MultiFileRenderResult { + private renderGraph( + targetLanguage: TargetLanguage, + graph: TypeGraph, + ): MultiFileRenderResult { if (this._options.noRender) { return this.makeSimpleTextResult(["Done.", ""]); } @@ -574,7 +586,7 @@ class Run implements RunContext { this._options.alphabetizeProperties, this._options.leadingComments, this._options.rendererOptions, - this._options.indentation + this._options.indentation, ); } } @@ -585,11 +597,15 @@ class Run implements RunContext { * @param options Partial options. For options that are not defined, the * defaults will be used. */ -export async function quicktypeMultiFile(options: Partial): Promise { +export async function quicktypeMultiFile( + options: Partial, +): Promise { return await new Run(options).run(); } -export function quicktypeMultiFileSync(options: Partial): MultiFileRenderResult { +export function quicktypeMultiFileSync( + options: Partial, +): MultiFileRenderResult { return new Run(options).runSync(); } @@ -598,7 +614,10 @@ function offsetLocation(loc: Location, lineOffset: number): Location { } function offsetSpan(span: Span, lineOffset: number): Span { - return { start: offsetLocation(span.start, lineOffset), end: offsetLocation(span.end, lineOffset) }; + return { + start: offsetLocation(span.start, lineOffset), + end: offsetLocation(span.end, lineOffset), + }; } /** @@ -606,23 +625,31 @@ function offsetSpan(span: Span, lineOffset: number): Span { * are concatenated and prefixed with a `//`-style comment giving the * filename. */ -export function combineRenderResults(result: MultiFileRenderResult): SerializedRenderResult { +export function combineRenderResults( + result: MultiFileRenderResult, +): SerializedRenderResult { if (result.size <= 1) { const first = mapFirst(result); if (first === undefined) { return { lines: [], annotations: [] }; } + return first; } + let lines: string[] = []; let annotations: Annotation[] = []; for (const [filename, srr] of result) { const offset = lines.length + 2; lines = lines.concat([`// ${filename}`, ""], srr.lines); annotations = annotations.concat( - srr.annotations.map(ann => ({ annotation: ann.annotation, span: offsetSpan(ann.span, offset) })) + srr.annotations.map((ann) => ({ + annotation: ann.annotation, + span: offsetSpan(ann.span, offset), + })), ); } + return { lines, annotations }; } @@ -634,7 +661,9 @@ export function combineRenderResults(result: MultiFileRenderResult): SerializedR * @param options Partial options. For options that are not defined, the * defaults will be used. */ -export async function quicktype(options: Partial): Promise { +export async function quicktype( + options: Partial, +): Promise { const result = await quicktypeMultiFile(options); return combineRenderResults(result); } diff --git a/packages/quicktype-core/src/Source.ts b/packages/quicktype-core/src/Source.ts index 6898480af..5286d8ab2 100644 --- a/packages/quicktype-core/src/Source.ts +++ b/packages/quicktype-core/src/Source.ts @@ -1,9 +1,9 @@ import { arrayIntercalate, iterableMax, withDefault } from "collection-utils"; -import { AnnotationData } from "./Annotation"; +import type { AnnotationData } from "./Annotation"; import { Name } from "./Naming"; -import { defined, assertNever, panic, assert } from "./support/Support"; import { repeatString } from "./support/Strings"; +import { assert, assertNever, defined, panic } from "./support/Support"; export type Source = | TextSource @@ -20,28 +20,28 @@ export interface TextSource { } export interface NewlineSource { - kind: "newline"; // Number of indentation levels (not spaces!) to change // the rest of the source by. Positive numbers mean // indent more, negative mean indent less. The most // common value will be zero, for no change in // indentation. indentationChange: number; + kind: "newline"; } export interface SequenceSource { kind: "sequence"; - sequence: ReadonlyArray; + sequence: readonly Source[]; } export interface TableSource { kind: "table"; - table: ReadonlyArray>; + table: ReadonlyArray; } export interface AnnotatedSource { - kind: "annotated"; annotation: AnnotationData; + kind: "annotated"; source: Source; } @@ -63,31 +63,35 @@ export function newline(): NewlineSource { } export type Sourcelike = Source | string | Name | SourcelikeArray; -export interface SourcelikeArray extends Array {} +export type SourcelikeArray = Sourcelike[]; export function sourcelikeToSource(sl: Sourcelike): Source { if (sl instanceof Array) { return { kind: "sequence", - sequence: sl.map(sourcelikeToSource) + sequence: sl.map(sourcelikeToSource), }; } + if (typeof sl === "string") { const lines = sl.split("\n"); if (lines.length === 1) { return { kind: "text", text: sl }; } + return { kind: "sequence", sequence: arrayIntercalate( newline(), - lines.map((l: string) => ({ kind: "text", text: l } as Source)) - ) + lines.map((l: string) => ({ kind: "text", text: l }) as Source), + ), }; } + if (sl instanceof Name) { return { kind: "name", named: sl }; } + return sl; } @@ -95,34 +99,42 @@ export function annotated(annotation: AnnotationData, sl: Sourcelike): Source { return { kind: "annotated", annotation, - source: sourcelikeToSource(sl) + source: sourcelikeToSource(sl), }; } -export function maybeAnnotated(doAnnotate: boolean, annotation: AnnotationData, sl: Sourcelike): Sourcelike { +export function maybeAnnotated( + doAnnotate: boolean, + annotation: AnnotationData, + sl: Sourcelike, +): Sourcelike { if (!doAnnotate) { return sl; } + return annotated(annotation, sl); } -export function modifySource(modifier: (serialized: string) => string, sl: Sourcelike): Sourcelike { +export function modifySource( + modifier: (serialized: string) => string, + sl: Sourcelike, +): Sourcelike { return { kind: "modified", modifier, - source: sourcelikeToSource(sl) + source: sourcelikeToSource(sl), }; } export interface Location { + column: number; // Both of these are zero-based. line: number; - column: number; } export interface Span { - start: Location; end: Location; + start: Location; } export interface Annotation { @@ -131,11 +143,14 @@ export interface Annotation { } export interface SerializedRenderResult { + annotations: readonly Annotation[]; lines: string[]; - annotations: ReadonlyArray; } -function sourceLineLength(source: Source, names: ReadonlyMap): number { +function sourceLineLength( + source: Source, + names: ReadonlyMap, +): number { switch (source.kind) { case "text": return source.text.length; @@ -152,7 +167,8 @@ function sourceLineLength(source: Source, names: ReadonlyMap): num case "name": return defined(names.get(source.named)).length; case "modified": - return serializeRenderResult(source, names, "").lines.join("\n").length; + return serializeRenderResult(source, names, "").lines.join("\n") + .length; default: return assertNever(source); } @@ -161,7 +177,7 @@ function sourceLineLength(source: Source, names: ReadonlyMap): num export function serializeRenderResult( rootSource: Source, names: ReadonlyMap, - indentation: string + indentation: string, ): SerializedRenderResult { let indent = 0; let indentNeeded = 0; @@ -206,42 +222,62 @@ export function serializeRenderResult( for (const s of source.sequence) { serializeToStringArray(s); } + break; case "table": const t = source.table; const numRows = t.length; if (numRows === 0) break; - const widths = t.map(l => l.map(s => sourceLineLength(s, names))); - const numColumns = defined(iterableMax(t.map(l => l.length))); + const widths = t.map((l) => + l.map((s) => sourceLineLength(s, names)), + ); + const numColumns = defined(iterableMax(t.map((l) => l.length))); if (numColumns === 0) break; const columnWidths: number[] = []; for (let i = 0; i < numColumns; i++) { - columnWidths.push(defined(iterableMax(widths.map(l => withDefault(l[i], 0))))); + columnWidths.push( + defined( + iterableMax( + widths.map((l) => withDefault(l[i], 0)), + ), + ), + ); } + for (let y = 0; y < numRows; y++) { indentIfNeeded(); const row = defined(t[y]); const rowWidths = defined(widths[y]); for (let x = 0; x < numColumns; x++) { const colWidth = columnWidths[x]; - const src = withDefault(row[x], { kind: "text", text: "" }); + const src = withDefault(row[x], { + kind: "text", + text: "", + }); const srcWidth = withDefault(rowWidths[x], 0); serializeToStringArray(src); if (x < numColumns - 1 && srcWidth < colWidth) { - currentLine.push(repeatString(" ", colWidth - srcWidth)); + currentLine.push( + repeatString(" ", colWidth - srcWidth), + ); } } + if (y < numRows - 1) { finishLine(); indentNeeded = indent; } } + break; case "annotated": const start = currentLocation(); serializeToStringArray(source.source); const end = currentLocation(); - annotations.push({ annotation: source.annotation, span: { start, end } }); + annotations.push({ + annotation: source.annotation, + span: { start, end }, + }); break; case "name": assert(names.has(source.named), "No name for Named"); @@ -250,8 +286,15 @@ export function serializeRenderResult( break; case "modified": indentIfNeeded(); - const serialized = serializeRenderResult(source.source, names, indentation).lines; - assert(serialized.length === 1, "Cannot modify more than one line."); + const serialized = serializeRenderResult( + source.source, + names, + indentation, + ).lines; + assert( + serialized.length === 1, + "Cannot modify more than one line.", + ); currentLine.push(source.modifier(serialized[0])); break; default: @@ -264,25 +307,30 @@ export function serializeRenderResult( return { lines, annotations: annotations }; } -export type MultiWord = { - source: Sourcelike; +export interface MultiWord { needsParens: boolean; -}; + source: Sourcelike; +} export function singleWord(...source: Sourcelike[]): MultiWord { return { source, needsParens: false }; } -export function multiWord(separator: Sourcelike, ...words: Sourcelike[]): MultiWord { +export function multiWord( + separator: Sourcelike, + ...words: Sourcelike[] +): MultiWord { assert(words.length > 0, "Zero words is not multiple"); if (words.length === 1) { return singleWord(words[0]); } + const items: Sourcelike[] = []; for (let i = 0; i < words.length; i++) { if (i > 0) items.push(separator); items.push(words[i]); } + return { source: items, needsParens: true }; } @@ -290,5 +338,6 @@ export function parenIfNeeded({ source, needsParens }: MultiWord): Sourcelike { if (needsParens) { return ["(", source, ")"]; } + return source; } diff --git a/packages/quicktype-core/src/TargetLanguage.ts b/packages/quicktype-core/src/TargetLanguage.ts index 4b8203026..84fce85cd 100644 --- a/packages/quicktype-core/src/TargetLanguage.ts +++ b/packages/quicktype-core/src/TargetLanguage.ts @@ -1,87 +1,118 @@ import { mapMap } from "collection-utils"; -import { TypeGraph } from "./TypeGraph"; -import { Renderer, RenderContext } from "./Renderer"; -import { OptionDefinition, Option } from "./RendererOptions"; -import { serializeRenderResult, SerializedRenderResult } from "./Source"; -import { StringTypeMapping } from "./TypeBuilder"; -import { defined } from "./support/Support"; import { ConvenienceRenderer } from "./ConvenienceRenderer"; -import { Type } from "./Type"; -import { DateTimeRecognizer, DefaultDateTimeRecognizer } from "./DateTime"; +import { type DateTimeRecognizer, DefaultDateTimeRecognizer } from "./DateTime"; +import type { RenderContext, Renderer } from "./Renderer"; +import type { Option, OptionDefinition } from "./RendererOptions"; +import { type SerializedRenderResult, serializeRenderResult } from "./Source"; +import type { Comment } from "./support/Comments"; +import { defined } from "./support/Support"; +import type { Type } from "./Type/Type"; +import type { StringTypeMapping } from "./Type/TypeBuilderUtils"; +import type { TypeGraph } from "./Type/TypeGraph"; +import type { LanguageName, RendererOptions } from "./types"; export type MultiFileRenderResult = ReadonlyMap; -export abstract class TargetLanguage { - constructor(readonly displayName: string, readonly names: string[], readonly extension: string) {} +export interface LanguageConfig { + readonly displayName: string; + readonly extension: string; + readonly names: readonly string[]; +} + +export abstract class TargetLanguage< + Config extends LanguageConfig = LanguageConfig, +> { + public readonly displayName: Config["displayName"]; + + public readonly names: Config["names"]; - protected abstract getOptions(): Option[]; + public readonly extension: Config["extension"]; - get optionDefinitions(): OptionDefinition[] { - return this.getOptions().map(o => o.definition); + public constructor({ displayName, names, extension }: Config) { + this.displayName = displayName; + this.names = names; + this.extension = extension; } - get cliOptionDefinitions(): { display: OptionDefinition[]; actual: OptionDefinition[] } { - let actual: OptionDefinition[] = []; - let display: OptionDefinition[] = []; - for (const { cliDefinitions } of this.getOptions()) { + protected abstract getOptions(): Record>; + + public get optionDefinitions(): Array> { + return Object.values(this.getOptions()).map((o) => o.definition); + } + + public get cliOptionDefinitions(): { + actual: Array>; + display: Array>; + } { + let actual: Array> = []; + let display: Array> = []; + for (const { cliDefinitions } of Object.values(this.getOptions())) { actual = actual.concat(cliDefinitions.actual); display = display.concat(cliDefinitions.display); } + return { actual, display }; } - get name(): string { + public get name(): (typeof this.names)[0] { return defined(this.names[0]); } - protected abstract makeRenderer(renderContext: RenderContext, optionValues: { [name: string]: any }): Renderer; + protected abstract makeRenderer( + renderContext: RenderContext, + optionValues: RendererOptions, + ): Renderer; - renderGraphAndSerialize( + public renderGraphAndSerialize( typeGraph: TypeGraph, givenOutputFilename: string, alphabetizeProperties: boolean, - leadingComments: string[] | undefined, - rendererOptions: { [name: string]: any }, - indentation?: string + leadingComments: Comment[] | undefined, + rendererOptions: RendererOptions, + indentation?: string, ): MultiFileRenderResult { if (indentation === undefined) { indentation = this.defaultIndentation; } + const renderContext = { typeGraph, leadingComments }; const renderer = this.makeRenderer(renderContext, rendererOptions); - if ((renderer as any).setAlphabetizeProperties !== undefined) { - (renderer as ConvenienceRenderer).setAlphabetizeProperties(alphabetizeProperties); + if (renderer instanceof ConvenienceRenderer) { + renderer.setAlphabetizeProperties(alphabetizeProperties); } + const renderResult = renderer.render(givenOutputFilename); - return mapMap(renderResult.sources, s => serializeRenderResult(s, renderResult.names, defined(indentation))); + return mapMap(renderResult.sources, (s) => + serializeRenderResult(s, renderResult.names, defined(indentation)), + ); } protected get defaultIndentation(): string { return " "; } - get stringTypeMapping(): StringTypeMapping { + public get stringTypeMapping(): StringTypeMapping { return new Map(); } - get supportsOptionalClassProperties(): boolean { + public get supportsOptionalClassProperties(): boolean { return false; } - get supportsUnionsWithBothNumberTypes(): boolean { + public get supportsUnionsWithBothNumberTypes(): boolean { return false; } - get supportsFullObjectType(): boolean { + public get supportsFullObjectType(): boolean { return false; } - needsTransformerForType(_t: Type): boolean { + public needsTransformerForType(_t: Type): boolean { return false; } - get dateTimeRecognizer(): DateTimeRecognizer { + public get dateTimeRecognizer(): DateTimeRecognizer { return new DefaultDateTimeRecognizer(); } } diff --git a/packages/quicktype-core/src/Transformers.ts b/packages/quicktype-core/src/Transformers.ts index e64752358..3827c92c1 100644 --- a/packages/quicktype-core/src/Transformers.ts +++ b/packages/quicktype-core/src/Transformers.ts @@ -1,60 +1,76 @@ import { - setUnionInto, + addHashCode, areEqual, - hashCodeOf, + arraySortByInto, definedMap, - addHashCode, definedMapWithDefault, - arraySortByInto, - hashString + hashCodeOf, + hashString, + setUnionInto, } from "collection-utils"; -import { UnionType, Type, EnumType, PrimitiveType, TypeKind } from "./Type"; import { TypeAttributeKind } from "./attributes/TypeAttributes"; -import { panic, assert, indentationString } from "./support/Support"; -import { BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { TypeRef, derefTypeRef, TypeGraph } from "./TypeGraph"; +import type { BaseGraphRewriteBuilder } from "./GraphRewriting"; +import { assert, indentationString, panic } from "./support/Support"; +import { + EnumType, + PrimitiveType, + type Type, + type TypeKind, + UnionType, +} from "./Type"; +import type { TypeGraph } from "./Type/TypeGraph"; +import { type TypeRef, derefTypeRef } from "./Type/TypeRef"; function debugStringForType(t: Type): string { const target = followTargetType(t); if (t === target) { return t.kind; } + return `${t.kind} (${target.kind})`; } function getNumberOfNodes(xfer: Transformer | undefined): number { - return definedMapWithDefault(xfer, 0, x => x.getNumberOfNodes()); + return definedMapWithDefault(xfer, 0, (x) => x.getNumberOfNodes()); } export abstract class Transformer { - constructor(readonly kind: string, protected readonly graph: TypeGraph, readonly sourceTypeRef: TypeRef) {} + public constructor( + public readonly kind: string, + protected readonly graph: TypeGraph, + public readonly sourceTypeRef: TypeRef, + ) {} - get sourceType(): Type { + public get sourceType(): Type { return derefTypeRef(this.sourceTypeRef, this.graph); } /** This must return a newly constructed set. */ - getChildren(): Set { + public getChildren(): Set { return new Set([this.sourceType]); } - getNumberOfNodes(): number { + public getNumberOfNodes(): number { return 1; } - abstract get canFail(): boolean; + public abstract get canFail(): boolean; - abstract reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer; + public abstract reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer; - abstract reconstitute(builder: TBuilder): Transformer; + public abstract reconstitute( + builder: TBuilder, + ): Transformer; - equals(other: any): boolean { - if (!(other instanceof Transformer)) return false; + public equals(other: T): boolean { return this.sourceTypeRef === other.sourceTypeRef; } - hashCode(): number { + public hashCode(): number { return hashCodeOf(this.sourceTypeRef); } @@ -66,34 +82,39 @@ export abstract class Transformer { return; } - debugPrint(indent: number): void { + public debugPrint(indent: number): void { console.log(indentationString(indent) + this.debugDescription()); this.debugPrintContinuations(indent + 1); } } export abstract class ProducerTransformer extends Transformer { - constructor(kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly consumer: Transformer | undefined) { + public constructor( + kind: string, + graph: TypeGraph, + sourceTypeRef: TypeRef, + public readonly consumer: Transformer | undefined, + ) { super(kind, graph, sourceTypeRef); } - getChildren(): Set { + public getChildren(): Set { const children = super.getChildren(); if (this.consumer === undefined) return children; return setUnionInto(children, this.consumer.getChildren()); } - getNumberOfNodes(): number { + public getNumberOfNodes(): number { return super.getNumberOfNodes() + getNumberOfNodes(this.consumer); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ProducerTransformer)) return false; return areEqual(this.consumer, other.consumer); } - hashCode(): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.consumer)); } @@ -105,25 +126,33 @@ export abstract class ProducerTransformer extends Transformer { } export abstract class MatchTransformer extends Transformer { - constructor(kind: string, graph: TypeGraph, sourceTypeRef: TypeRef, readonly transformer: Transformer) { + public constructor( + kind: string, + graph: TypeGraph, + sourceTypeRef: TypeRef, + public readonly transformer: Transformer, + ) { super(kind, graph, sourceTypeRef); } - getChildren(): Set { - return setUnionInto(super.getChildren(), this.transformer.getChildren()); + public getChildren(): Set { + return setUnionInto( + super.getChildren(), + this.transformer.getChildren(), + ); } - getNumberOfNodes(): number { + public getNumberOfNodes(): number { return super.getNumberOfNodes() + this.transformer.getNumberOfNodes(); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof MatchTransformer)) return false; return this.transformer.equals(other.transformer); } - hashCode(): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, this.transformer.hashCode()); } @@ -134,61 +163,80 @@ export abstract class MatchTransformer extends Transformer { } export class DecodingTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + consumer: Transformer | undefined, + ) { super("decode", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (continuationTransformer !== undefined) { - return panic("Reversing a decoding transformer cannot have a continuation"); + return panic( + "Reversing a decoding transformer cannot have a continuation", + ); } if (this.consumer === undefined) { return new EncodingTransformer(this.graph, targetTypeRef); - } else { - return this.consumer.reverse( - targetTypeRef, - new EncodingTransformer(this.graph, this.consumer.sourceTypeRef) - ); } + + return this.consumer.reverse( + targetTypeRef, + new EncodingTransformer(this.graph, this.consumer.sourceTypeRef), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new DecodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)) + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof DecodingTransformer; } } export class EncodingTransformer extends Transformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { super("encode", graph, sourceTypeRef); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + public reverse( + _targetTypeRef: TypeRef, + _continuationTransformer: Transformer | undefined, + ): Transformer { return panic("Can't reverse encoding transformer"); } - reconstitute(builder: TBuilder): Transformer { - return new EncodingTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); + public reconstitute( + builder: TBuilder, + ): Transformer { + return new EncodingTransformer( + builder.typeGraph, + builder.reconstituteTypeRef(this.sourceTypeRef), + ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof EncodingTransformer)) return false; return true; @@ -196,82 +244,95 @@ export class EncodingTransformer extends Transformer { } export class ArrayDecodingTransformer extends ProducerTransformer { - constructor( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, private readonly _itemTargetTypeRef: TypeRef, - readonly itemTransformer: Transformer + public readonly itemTransformer: Transformer, ) { super("decode-array", graph, sourceTypeRef, consumer); } - getChildren(): Set { + public getChildren(): Set { const children = super.getChildren(); children.add(this.itemTargetType); return setUnionInto(children, this.itemTransformer.getChildren()); } - getNumberOfNodes(): number { - return super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes(); + public getNumberOfNodes(): number { + return ( + super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes() + ); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - get itemTargetType(): Type { + public get itemTargetType(): Type { return derefTypeRef(this._itemTargetTypeRef, this.graph); } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (continuationTransformer !== undefined) { - return panic("Reversing a decoding transformer cannot have a continuation"); + return panic( + "Reversing a decoding transformer cannot have a continuation", + ); } - const itemTransformer = this.itemTransformer.reverse(this._itemTargetTypeRef, undefined); + const itemTransformer = this.itemTransformer.reverse( + this._itemTargetTypeRef, + undefined, + ); if (this.consumer === undefined) { return new ArrayEncodingTransformer( this.graph, targetTypeRef, this.itemTransformer.sourceTypeRef, - itemTransformer - ); - } else { - return this.consumer.reverse( - targetTypeRef, - new ArrayEncodingTransformer( - this.graph, - this.consumer.sourceTypeRef, - this.itemTransformer.sourceTypeRef, - itemTransformer - ) + itemTransformer, ); } + + return this.consumer.reverse( + targetTypeRef, + new ArrayEncodingTransformer( + this.graph, + this.consumer.sourceTypeRef, + this.itemTransformer.sourceTypeRef, + itemTransformer, + ), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new ArrayDecodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), builder.reconstituteTypeRef(this._itemTargetTypeRef), - this.itemTransformer.reconstitute(builder) + this.itemTransformer.reconstitute(builder), ); } - hashCode(): number { + public hashCode(): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this._itemTargetTypeRef)); h = addHashCode(h, this.itemTransformer.hashCode()); return h; } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayDecodingTransformer)) return false; - if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; + if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) + return false; return this.itemTransformer.equals(other.itemTransformer); } @@ -282,56 +343,64 @@ export class ArrayDecodingTransformer extends ProducerTransformer { } export class ArrayEncodingTransformer extends Transformer { - constructor( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, private readonly _itemTargetTypeRef: TypeRef, - readonly itemTransformer: Transformer + public readonly itemTransformer: Transformer, ) { super("encode-array", graph, sourceTypeRef); } - getChildren(): Set { + public getChildren(): Set { const children = super.getChildren(); children.add(this.itemTargetType); return setUnionInto(children, this.itemTransformer.getChildren()); } - getNumberOfNodes(): number { - return super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes(); + public getNumberOfNodes(): number { + return ( + super.getNumberOfNodes() + this.itemTransformer.getNumberOfNodes() + ); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - get itemTargetType(): Type { + public get itemTargetType(): Type { return derefTypeRef(this._itemTargetTypeRef, this.graph); } - reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + public reverse( + _targetTypeRef: TypeRef, + _continuationTransformer: Transformer | undefined, + ): Transformer { return panic("Can't reverse array encoding transformer"); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new ArrayEncodingTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), builder.reconstituteTypeRef(this._itemTargetTypeRef), - this.itemTransformer.reconstitute(builder) + this.itemTransformer.reconstitute(builder), ); } - hashCode(): number { + public hashCode(): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this._itemTargetTypeRef)); return addHashCode(h, this.itemTransformer.hashCode()); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ArrayEncodingTransformer)) return false; - if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) return false; + if (!areEqual(this._itemTargetTypeRef, other._itemTargetTypeRef)) + return false; return this.itemTransformer.equals(other.itemTransformer); } @@ -342,64 +411,96 @@ export class ArrayEncodingTransformer extends Transformer { } export class ChoiceTransformer extends Transformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, public readonly transformers: ReadonlyArray) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + public readonly transformers: readonly Transformer[], + ) { super("choice", graph, sourceTypeRef); - assert(transformers.length > 0, "Choice must have at least one transformer"); + assert( + transformers.length > 0, + "Choice must have at least one transformer", + ); } - getChildren(): Set { - let children = super.getChildren(); + public getChildren(): Set { + const children = super.getChildren(); for (const xfer of this.transformers) { setUnionInto(children, xfer.getChildren()); } + return children; } - getNumberOfNodes(): number { + public getNumberOfNodes(): number { let n = 0; for (const xfer of this.transformers) { n += xfer.getNumberOfNodes(); } + return super.getNumberOfNodes() + n; } - get canFail(): boolean { - return this.transformers.some(xfer => xfer.canFail); + public get canFail(): boolean { + return this.transformers.some((xfer) => xfer.canFail); } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { - const transformers = this.transformers.map(xfer => xfer.reverse(targetTypeRef, continuationTransformer)); - if (transformers.every(xfer => xfer instanceof UnionMemberMatchTransformer)) { - const memberMatchers = transformers as UnionMemberMatchTransformer[]; + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { + const transformers = this.transformers.map((xfer) => + xfer.reverse(targetTypeRef, continuationTransformer), + ); + if ( + transformers.every( + (xfer) => xfer instanceof UnionMemberMatchTransformer, + ) + ) { + const memberMatchers = + transformers as UnionMemberMatchTransformer[]; const first = memberMatchers[0]; - if (memberMatchers.every(xfer => first.memberType.equals(xfer.memberType))) { - const subTransformers = memberMatchers.map(xfer => xfer.transformer); + if ( + memberMatchers.every((xfer) => + first.memberType.equals(xfer.memberType), + ) + ) { + const subTransformers = memberMatchers.map( + (xfer) => xfer.transformer, + ); return new UnionMemberMatchTransformer( this.graph, targetTypeRef, - new ChoiceTransformer(this.graph, subTransformers[0].sourceTypeRef, subTransformers), - first.memberTypeRef + new ChoiceTransformer( + this.graph, + subTransformers[0].sourceTypeRef, + subTransformers, + ), + first.memberTypeRef, ); } } + return new ChoiceTransformer(this.graph, targetTypeRef, transformers); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new ChoiceTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - this.transformers.map(xfer => xfer.reconstitute(builder)) + this.transformers.map((xfer) => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof ChoiceTransformer)) return false; return areEqual(this.transformers, other.transformers); } - hashCode(): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.transformers)); } @@ -412,23 +513,23 @@ export class ChoiceTransformer extends Transformer { } export class DecodingChoiceTransformer extends Transformer { - constructor( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, - readonly nullTransformer: Transformer | undefined, - readonly integerTransformer: Transformer | undefined, - readonly doubleTransformer: Transformer | undefined, - readonly boolTransformer: Transformer | undefined, - readonly stringTransformer: Transformer | undefined, - readonly arrayTransformer: Transformer | undefined, - readonly objectTransformer: Transformer | undefined + public readonly nullTransformer: Transformer | undefined, + public readonly integerTransformer: Transformer | undefined, + public readonly doubleTransformer: Transformer | undefined, + public readonly boolTransformer: Transformer | undefined, + public readonly stringTransformer: Transformer | undefined, + public readonly arrayTransformer: Transformer | undefined, + public readonly objectTransformer: Transformer | undefined, ) { super("decoding-choice", graph, sourceTypeRef); } - get transformers(): ReadonlyArray { + public get transformers(): readonly Transformer[] { const transformers: Transformer[] = []; - function add(xfer: Transformer | undefined) { + function add(xfer: Transformer | undefined): void { if (xfer === undefined) return; transformers.push(xfer); } @@ -444,36 +545,41 @@ export class DecodingChoiceTransformer extends Transformer { return transformers; } - getChildren(): Set { - let children = super.getChildren(); + public getChildren(): Set { + const children = super.getChildren(); for (const xfer of this.transformers) { setUnionInto(children, xfer.getChildren()); } + return children; } - getNumberOfNodes(): number { + public getNumberOfNodes(): number { let n = super.getNumberOfNodes(); for (const xfer of this.transformers) { n += getNumberOfNodes(xfer); } + return n; } - get canFail(): boolean { + public get canFail(): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { assert( continuationTransformer === undefined, - "Reversing a decoding transformer can't have a target transformer" + "Reversing a decoding transformer can't have a target transformer", ); - let transformers = new Map(); - let memberMatchTransformers = new Map(); + const transformers = new Map(); + const memberMatchTransformers = new Map(); - function addCase(reversed: Transformer) { + function addCase(reversed: Transformer): void { if (reversed instanceof UnionMemberMatchTransformer) { const memberType = reversed.memberType; let arr = memberMatchTransformers.get(memberType); @@ -481,6 +587,7 @@ export class DecodingChoiceTransformer extends Transformer { arr = []; memberMatchTransformers.set(memberType, arr); } + arr.push(reversed); } else { const kind = reversed.sourceType.kind; @@ -489,19 +596,21 @@ export class DecodingChoiceTransformer extends Transformer { arr = []; transformers.set(kind, arr); } + arr.push(reversed); } } - function reverseAndAdd(transformer: Transformer) { + function reverseAndAdd(transformer: Transformer): void { const reversed = transformer.reverse(targetTypeRef, undefined); - let cases: ReadonlyArray = []; + let cases: readonly Transformer[] = []; // Flatten nested ChoiceTransformers if (reversed instanceof ChoiceTransformer) { cases = reversed.transformers; } else { cases = [reversed]; } + for (const xfer of cases) { addCase(xfer); } @@ -517,7 +626,7 @@ export class DecodingChoiceTransformer extends Transformer { function filter(xfers: Transformer[]): Transformer[] { assert(xfers.length > 0, "Must have at least one transformer"); - const nonfailing = xfers.filter(xfer => { + const nonfailing = xfers.filter((xfer) => { // For member match transformers we're deciding between // multiple that match against the same member, so the fact // that the match can fail is not important, since if it fails @@ -525,34 +634,48 @@ export class DecodingChoiceTransformer extends Transformer { // its continuation can fail. if (xfer instanceof UnionMemberMatchTransformer) { return !xfer.transformer.canFail; - } else { - return !xfer.canFail; } + + return !xfer.canFail; }); if (nonfailing.length === 0) return xfers; const smallest = arraySortByInto( - nonfailing.map(x => [x.getNumberOfNodes(), x] as [number, Transformer]), - ([c, _]) => c + nonfailing.map( + (x) => [x.getNumberOfNodes(), x] as [number, Transformer], + ), + ([c, _]) => c, )[0][1]; return [smallest]; } this.transformers.forEach(reverseAndAdd); - const allTransformers = Array.from(transformers.values()).concat(Array.from(memberMatchTransformers.values())); - const resultingTransformers = ([] as Transformer[]).concat(...allTransformers.map(filter)); + const allTransformers = Array.from(transformers.values()).concat( + Array.from(memberMatchTransformers.values()), + ); + const resultingTransformers = ([] as Transformer[]).concat( + ...allTransformers.map(filter), + ); // No choice needed if there's only one if (resultingTransformers.length === 1) { return resultingTransformers[0]; } - return new ChoiceTransformer(this.graph, targetTypeRef, resultingTransformers); + return new ChoiceTransformer( + this.graph, + targetTypeRef, + resultingTransformers, + ); } - reconstitute(builder: TBuilder): Transformer { - function reconstitute(xf: Transformer | undefined) { + public reconstitute( + builder: TBuilder, + ): Transformer { + function reconstitute( + xf: Transformer | undefined, + ): Transformer | undefined { if (xf === undefined) return undefined; return xf.reconstitute(builder); } @@ -566,24 +689,31 @@ export class DecodingChoiceTransformer extends Transformer { reconstitute(this.boolTransformer), reconstitute(this.stringTransformer), reconstitute(this.arrayTransformer), - reconstitute(this.objectTransformer) + reconstitute(this.objectTransformer), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof DecodingChoiceTransformer)) return false; - if (!areEqual(this.nullTransformer, other.nullTransformer)) return false; - if (!areEqual(this.integerTransformer, other.integerTransformer)) return false; - if (!areEqual(this.doubleTransformer, other.doubleTransformer)) return false; - if (!areEqual(this.boolTransformer, other.boolTransformer)) return false; - if (!areEqual(this.stringTransformer, other.stringTransformer)) return false; - if (!areEqual(this.arrayTransformer, other.arrayTransformer)) return false; - if (!areEqual(this.objectTransformer, other.objectTransformer)) return false; + if (!areEqual(this.nullTransformer, other.nullTransformer)) + return false; + if (!areEqual(this.integerTransformer, other.integerTransformer)) + return false; + if (!areEqual(this.doubleTransformer, other.doubleTransformer)) + return false; + if (!areEqual(this.boolTransformer, other.boolTransformer)) + return false; + if (!areEqual(this.stringTransformer, other.stringTransformer)) + return false; + if (!areEqual(this.arrayTransformer, other.arrayTransformer)) + return false; + if (!areEqual(this.objectTransformer, other.objectTransformer)) + return false; return true; } - hashCode(): number { + public hashCode(): number { let h = super.hashCode(); h = addHashCode(h, hashCodeOf(this.nullTransformer)); h = addHashCode(h, hashCodeOf(this.integerTransformer)); @@ -603,50 +733,63 @@ export class DecodingChoiceTransformer extends Transformer { } export class UnionMemberMatchTransformer extends MatchTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly memberTypeRef: TypeRef) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + transformer: Transformer, + public readonly memberTypeRef: TypeRef, + ) { super("union-member-match", graph, sourceTypeRef, transformer); } - get sourceType(): UnionType { + public get sourceType(): UnionType { const t = derefTypeRef(this.sourceTypeRef, this.graph); if (!(t instanceof UnionType)) { - return panic("The source of a union member match transformer must be a union type"); + return panic( + "The source of a union member match transformer must be a union type", + ); } + return t; } - get canFail(): boolean { + public get canFail(): boolean { return true; } - get memberType(): Type { + public get memberType(): Type { return derefTypeRef(this.memberTypeRef, this.graph); } - getChildren(): Set { + public getChildren(): Set { return super.getChildren().add(this.memberType); } - reverse(_targetTypeRef: TypeRef, _continuationTransformer: Transformer | undefined): Transformer { + public reverse( + _targetTypeRef: TypeRef, + _continuationTransformer: Transformer | undefined, + ): Transformer { return panic("Can't reverse union member match transformer"); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new UnionMemberMatchTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), this.transformer.reconstitute(builder), - builder.reconstituteTypeRef(this.memberTypeRef) + builder.reconstituteTypeRef(this.memberTypeRef), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof UnionMemberMatchTransformer)) return false; return this.memberTypeRef === other.memberTypeRef; } - hashCode(): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.memberTypeRef)); } @@ -660,50 +803,66 @@ export class UnionMemberMatchTransformer extends MatchTransformer { * This matches strings and enum cases. */ export class StringMatchTransformer extends MatchTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, transformer: Transformer, readonly stringCase: string) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + transformer: Transformer, + public readonly stringCase: string, + ) { super("string-match", graph, sourceTypeRef, transformer); } - get sourceType(): EnumType | PrimitiveType { + public get sourceType(): EnumType | PrimitiveType { const t = derefTypeRef(this.sourceTypeRef, this.graph); - if (!(t instanceof EnumType) && !(t instanceof PrimitiveType && t.kind === "string")) { - return panic("The source of a string match transformer must be an enum or string type"); + if ( + !(t instanceof EnumType) && + !(t instanceof PrimitiveType && t.kind === "string") + ) { + return panic( + "The source of a string match transformer must be an enum or string type", + ); } + return t; } - get canFail(): boolean { + public get canFail(): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { return this.transformer.reverse( targetTypeRef, new StringProducerTransformer( this.graph, this.transformer.sourceTypeRef, continuationTransformer, - this.stringCase - ) + this.stringCase, + ), ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new StringMatchTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), this.transformer.reconstitute(builder), - this.stringCase + this.stringCase, ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringMatchTransformer)) return false; return this.stringCase !== other.stringCase; } - hashCode(): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashString(this.stringCase)); } @@ -714,27 +873,42 @@ export class StringMatchTransformer extends MatchTransformer { } export class UnionInstantiationTransformer extends Transformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { + public constructor(graph: TypeGraph, sourceTypeRef: TypeRef) { super("union-instantiation", graph, sourceTypeRef); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (continuationTransformer === undefined) { - return panic("Union instantiation transformer reverse must have a continuation"); + return panic( + "Union instantiation transformer reverse must have a continuation", + ); } - return new UnionMemberMatchTransformer(this.graph, targetTypeRef, continuationTransformer, this.sourceTypeRef); + return new UnionMemberMatchTransformer( + this.graph, + targetTypeRef, + continuationTransformer, + this.sourceTypeRef, + ); } - reconstitute(builder: TBuilder): Transformer { - return new UnionInstantiationTransformer(builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef)); + public reconstitute( + builder: TBuilder, + ): Transformer { + return new UnionInstantiationTransformer( + builder.typeGraph, + builder.reconstituteTypeRef(this.sourceTypeRef), + ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof UnionInstantiationTransformer; } @@ -744,50 +918,67 @@ export class UnionInstantiationTransformer extends Transformer { * Produces a string or an enum case. */ export class StringProducerTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, readonly result: string) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + consumer: Transformer | undefined, + public readonly result: string, + ) { super("string-producer", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (continuationTransformer === undefined) { - return panic("Reversing a string producer transformer must have a continuation"); + return panic( + "Reversing a string producer transformer must have a continuation", + ); } if (this.consumer === undefined) { - return new StringMatchTransformer(this.graph, targetTypeRef, continuationTransformer, this.result); - } else { - return this.consumer.reverse( + return new StringMatchTransformer( + this.graph, targetTypeRef, - new StringMatchTransformer( - this.graph, - this.consumer.sourceTypeRef, - continuationTransformer, - this.result - ) + continuationTransformer, + this.result, ); } + + return this.consumer.reverse( + targetTypeRef, + new StringMatchTransformer( + this.graph, + this.consumer.sourceTypeRef, + continuationTransformer, + this.result, + ), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new StringProducerTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), - this.result + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), + this.result, ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; if (!(other instanceof StringProducerTransformer)) return false; return this.result === other.result; } - hashCode(): number { + public hashCode(): number { const h = super.hashCode(); return addHashCode(h, hashCodeOf(this.consumer)); } @@ -798,122 +989,161 @@ export class StringProducerTransformer extends ProducerTransformer { } export class ParseStringTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + consumer: Transformer | undefined, + ) { super("parse-string", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + public get canFail(): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (this.consumer === undefined) { - return new StringifyTransformer(this.graph, targetTypeRef, continuationTransformer); - } else { - return this.consumer.reverse( + return new StringifyTransformer( + this.graph, targetTypeRef, - new StringifyTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer) + continuationTransformer, ); } + + return this.consumer.reverse( + targetTypeRef, + new StringifyTransformer( + this.graph, + this.consumer.sourceTypeRef, + continuationTransformer, + ), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new ParseStringTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)) + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof ParseStringTransformer; } } export class StringifyTransformer extends ProducerTransformer { - constructor(graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined) { + public constructor( + graph: TypeGraph, + sourceTypeRef: TypeRef, + consumer: Transformer | undefined, + ) { super("stringify", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + public get canFail(): boolean { return false; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (this.consumer === undefined) { - return new ParseStringTransformer(this.graph, targetTypeRef, continuationTransformer); - } else { - return this.consumer.reverse( + return new ParseStringTransformer( + this.graph, targetTypeRef, - new ParseStringTransformer(this.graph, this.consumer.sourceTypeRef, continuationTransformer) + continuationTransformer, ); } + + return this.consumer.reverse( + targetTypeRef, + new ParseStringTransformer( + this.graph, + this.consumer.sourceTypeRef, + continuationTransformer, + ), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new StringifyTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)) + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return other instanceof StringifyTransformer; } } export class MinMaxLengthCheckTransformer extends ProducerTransformer { - constructor( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, - readonly minLength: number | undefined, - readonly maxLength: number | undefined + public readonly minLength: number | undefined, + public readonly maxLength: number | undefined, ) { super("min-max-length-check", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + public get canFail(): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (this.consumer === undefined) { return new MinMaxLengthCheckTransformer( this.graph, targetTypeRef, continuationTransformer, this.minLength, - this.maxLength - ); - } else { - return this.consumer.reverse( - targetTypeRef, - new MinMaxLengthCheckTransformer( - this.graph, - this.consumer.sourceTypeRef, - continuationTransformer, - this.minLength, - this.maxLength - ) + this.maxLength, ); } + + return this.consumer.reverse( + targetTypeRef, + new MinMaxLengthCheckTransformer( + this.graph, + this.consumer.sourceTypeRef, + continuationTransformer, + this.minLength, + this.maxLength, + ), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new MinMaxLengthCheckTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), this.minLength, - this.maxLength + this.maxLength, ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return ( other instanceof MinMaxLengthCheckTransformer && @@ -924,149 +1154,170 @@ export class MinMaxLengthCheckTransformer extends ProducerTransformer { } export class MinMaxValueTransformer extends ProducerTransformer { - constructor( + public constructor( graph: TypeGraph, sourceTypeRef: TypeRef, consumer: Transformer | undefined, - readonly minimum: number | undefined, - readonly maximum: number | undefined + public readonly minimum: number | undefined, + public readonly maximum: number | undefined, ) { super("min-max-value-check", graph, sourceTypeRef, consumer); } - get canFail(): boolean { + public get canFail(): boolean { return true; } - reverse(targetTypeRef: TypeRef, continuationTransformer: Transformer | undefined): Transformer { + public reverse( + targetTypeRef: TypeRef, + continuationTransformer: Transformer | undefined, + ): Transformer { if (this.consumer === undefined) { return new MinMaxValueTransformer( this.graph, targetTypeRef, continuationTransformer, this.minimum, - this.maximum - ); - } else { - return this.consumer.reverse( - targetTypeRef, - new MinMaxValueTransformer( - this.graph, - this.consumer.sourceTypeRef, - continuationTransformer, - this.minimum, - this.maximum - ) + this.maximum, ); } + + return this.consumer.reverse( + targetTypeRef, + new MinMaxValueTransformer( + this.graph, + this.consumer.sourceTypeRef, + continuationTransformer, + this.minimum, + this.maximum, + ), + ); } - reconstitute(builder: TBuilder): Transformer { + public reconstitute( + builder: TBuilder, + ): Transformer { return new MinMaxValueTransformer( builder.typeGraph, builder.reconstituteTypeRef(this.sourceTypeRef), - definedMap(this.consumer, xfer => xfer.reconstitute(builder)), + definedMap(this.consumer, (xfer) => xfer.reconstitute(builder)), this.minimum, - this.maximum + this.maximum, ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!super.equals(other)) return false; return ( - other instanceof MinMaxValueTransformer && this.minimum === other.minimum && this.maximum === other.maximum + other instanceof MinMaxValueTransformer && + this.minimum === other.minimum && + this.maximum === other.maximum ); } } export class Transformation { - constructor( + public constructor( private readonly _graph: TypeGraph, private readonly _targetTypeRef: TypeRef, - readonly transformer: Transformer + public readonly transformer: Transformer, ) {} - get sourceType(): Type { + public get sourceType(): Type { return this.transformer.sourceType; } - get targetType(): Type { + public get targetType(): Type { return derefTypeRef(this._targetTypeRef, this._graph); } - get reverse(): Transformation { + public get reverse(): Transformation { return new Transformation( this._graph, this.transformer.sourceTypeRef, - this.transformer.reverse(this._targetTypeRef, undefined) + this.transformer.reverse(this._targetTypeRef, undefined), ); } - getChildren(): Set { + public getChildren(): Set { return this.transformer.getChildren().add(this.targetType); } - reconstitute(builder: TBuilder): Transformation { + public reconstitute( + builder: TBuilder, + ): Transformation { return new Transformation( builder.typeGraph, builder.reconstituteTypeRef(this._targetTypeRef), - this.transformer.reconstitute(builder) + this.transformer.reconstitute(builder), ); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof Transformation)) return false; - return this._targetTypeRef === other._targetTypeRef && this.transformer.equals(other.transformer); + return ( + this._targetTypeRef === other._targetTypeRef && + this.transformer.equals(other.transformer) + ); } - hashCode(): number { + public hashCode(): number { let h = hashCodeOf(this._targetTypeRef); h = addHashCode(h, this.transformer.hashCode()); return h; } - debugPrint(): void { + public debugPrint(): void { this.transformer.debugPrint(0); console.log(`-> ${debugStringForType(this.targetType)}`); } } class TransformationTypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("transformation"); } - appliesToTypeKind(_kind: TypeKind): boolean { + public appliesToTypeKind(_kind: TypeKind): boolean { return true; } - get inIdentity(): boolean { + public get inIdentity(): boolean { return true; } - children(xf: Transformation): Set { + public children(xf: Transformation): Set { return xf.getChildren(); } - reconstitute(builder: TBuilder, xf: Transformation): Transformation { + public reconstitute( + builder: TBuilder, + xf: Transformation, + ): Transformation { return xf.reconstitute(builder); } - stringify(_: Transformation): string { + public stringify(_: Transformation): string { return "transformation"; } } -export const transformationTypeAttributeKind: TypeAttributeKind = new TransformationTypeAttributeKind(); +export const transformationTypeAttributeKind: TypeAttributeKind = + new TransformationTypeAttributeKind(); export function transformationForType(t: Type): Transformation | undefined { - return transformationTypeAttributeKind.tryGetInAttributes(t.getAttributes()); + return transformationTypeAttributeKind.tryGetInAttributes( + t.getAttributes(), + ); } export function followTargetType(t: Type): Type { for (;;) { const xf = transformationForType(t); - if (xf === undefined) return t; + if (xf === undefined) { + return t; + } + t = xf.targetType; } } diff --git a/packages/quicktype-core/src/Type/ProvenanceTypeAttributeKind.ts b/packages/quicktype-core/src/Type/ProvenanceTypeAttributeKind.ts new file mode 100644 index 000000000..2b4ece435 --- /dev/null +++ b/packages/quicktype-core/src/Type/ProvenanceTypeAttributeKind.ts @@ -0,0 +1,35 @@ +import { setUnionManyInto } from "collection-utils"; + +import { TypeAttributeKind } from "../attributes/TypeAttributes"; + +import type { TypeKind } from "./TransformedStringType"; + +// FIXME: Don't infer provenance. All original types should be present in +// non-inferred form in the final graph. +class ProvenanceTypeAttributeKind extends TypeAttributeKind> { + public constructor() { + super("provenance"); + } + + public appliesToTypeKind(_kind: TypeKind): boolean { + return true; + } + + public combine(arr: Array>): Set { + return setUnionManyInto(new Set(), arr); + } + + public makeInferred(p: Set): Set { + return p; + } + + public stringify(p: Set): string { + return Array.from(p) + .sort() + .map((i) => i.toString()) + .join(","); + } +} + +export const provenanceTypeAttributeKind: TypeAttributeKind> = + new ProvenanceTypeAttributeKind(); diff --git a/packages/quicktype-core/src/Type/TransformedStringType.ts b/packages/quicktype-core/src/Type/TransformedStringType.ts new file mode 100644 index 000000000..6a230611c --- /dev/null +++ b/packages/quicktype-core/src/Type/TransformedStringType.ts @@ -0,0 +1,118 @@ +import { + // eslint-disable-next-line @typescript-eslint/no-redeclare + hasOwnProperty, + mapFromObject, +} from "collection-utils"; + +import type { TypeAttributes } from "../attributes/TypeAttributes"; +import { uriInferenceAttributesProducer } from "../attributes/URIAttributes"; + +import type { Type } from "./Type"; + +/** + * `jsonSchema` is the `format` to be used to represent this string type in + * JSON Schema. It's ok to "invent" a new one if the JSON Schema standard doesn't + * have that particular type yet. + * + * For transformed type kinds that map to an existing primitive type, `primitive` + * must specify that type kind. + */ +export interface TransformedStringTypeTargets { + attributesProducer?: (s: string) => TypeAttributes; + jsonSchema: string; + primitive: PrimitiveNonStringTypeKind | undefined; +} + +/** + * All the transformed string type kinds and the JSON Schema formats and + * primitive type kinds they map to. Not all transformed string types map to + * primitive types. Date-time types, for example, stand on their own, but + * stringified integers map to integers. + */ +const transformedStringTypeTargetTypeKinds = { + date: { jsonSchema: "date", primitive: undefined }, + time: { jsonSchema: "time", primitive: undefined }, + "date-time": { jsonSchema: "date-time", primitive: undefined }, + uuid: { jsonSchema: "uuid", primitive: undefined }, + uri: { + jsonSchema: "uri", + primitive: undefined, + attributesProducer: uriInferenceAttributesProducer, + }, + "integer-string": { + jsonSchema: "integer", + primitive: "integer", + } as TransformedStringTypeTargets, + "bool-string": { + jsonSchema: "boolean", + primitive: "bool", + } as TransformedStringTypeTargets, +}; + +export const transformedStringTypeTargetTypeKindsMap = mapFromObject( + transformedStringTypeTargetTypeKinds as { + [kind: string]: TransformedStringTypeTargets; + }, +); + +export type TransformedStringTypeKind = + keyof typeof transformedStringTypeTargetTypeKinds; +export type PrimitiveStringTypeKind = "string" | TransformedStringTypeKind; +export type PrimitiveNonStringTypeKind = + | "none" + | "any" + | "null" + | "bool" + | "integer" + | "double"; +export type PrimitiveTypeKind = + | PrimitiveNonStringTypeKind + | PrimitiveStringTypeKind; +export type NamedTypeKind = "class" | "enum" | "union"; +export type TypeKind = + | PrimitiveTypeKind + | NamedTypeKind + | "array" + | "object" + | "map" + | "intersection"; +export type ObjectTypeKind = "object" | "map" | "class"; + +export const transformedStringTypeKinds = new Set( + Object.getOwnPropertyNames(transformedStringTypeTargetTypeKinds), +) as ReadonlySet; + +export function isPrimitiveStringTypeKind( + kind: string, +): kind is PrimitiveStringTypeKind { + return ( + kind === "string" || + hasOwnProperty(transformedStringTypeTargetTypeKinds, kind) + ); +} + +export function targetTypeKindForTransformedStringTypeKind( + kind: PrimitiveStringTypeKind, +): PrimitiveNonStringTypeKind | undefined { + const target = transformedStringTypeTargetTypeKindsMap.get(kind); + if (target === undefined) return undefined; + return target.primitive; +} + +export function isNumberTypeKind(kind: TypeKind): kind is "integer" | "double" { + return kind === "integer" || kind === "double"; +} + +export function isPrimitiveTypeKind(kind: TypeKind): kind is PrimitiveTypeKind { + if (isPrimitiveStringTypeKind(kind)) return true; + if (isNumberTypeKind(kind)) return true; + return ( + kind === "none" || kind === "any" || kind === "null" || kind === "bool" + ); +} + +export function triviallyStructurallyCompatible(x: Type, y: Type): boolean { + if (x.index === y.index) return true; + if (x.kind === "none" || y.kind === "none") return true; + return false; +} diff --git a/packages/quicktype-core/src/Type.ts b/packages/quicktype-core/src/Type/Type.ts similarity index 56% rename from packages/quicktype-core/src/Type.ts rename to packages/quicktype-core/src/Type/Type.ts index 7a16f06d3..f7bb83721 100644 --- a/packages/quicktype-core/src/Type.ts +++ b/packages/quicktype-core/src/Type/Type.ts @@ -1,134 +1,85 @@ import { + addHashCode, + areEqual, + definedMap, + hashCodeInit, + hashCodeOf, iterableEvery, iterableFind, iterableSome, - toReadonlySet, - hashCodeOf, - areEqual, + mapFilter, mapMap, - setMap, - mapSortByKey, mapSome, - mapFilter, - setSortBy, + mapSortByKey, + mapSortToArray, setFilter, + setMap, + setSortBy, setUnionInto, - mapSortToArray, - definedMap, - hashCodeInit, - addHashCode, - hasOwnProperty, - mapFromObject + toReadonlySet, } from "collection-utils"; -import { defined, panic, assert } from "./support/Support"; -import { TypeReconstituter, BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; -import { TypeAttributes } from "./attributes/TypeAttributes"; -import { messageAssert } from "./Messages"; -import { TypeRef, attributesForTypeRef, derefTypeRef, TypeGraph, typeRefIndex } from "./TypeGraph"; -import { uriInferenceAttributesProducer } from "./attributes/URIAttributes"; - -/** - * `jsonSchema` is the `format` to be used to represent this string type in - * JSON Schema. It's ok to "invent" a new one if the JSON Schema standard doesn't - * have that particular type yet. - * - * For transformed type kinds that map to an existing primitive type, `primitive` - * must specify that type kind. - */ -export type TransformedStringTypeTargets = { - jsonSchema: string; - primitive: PrimitiveNonStringTypeKind | undefined; - attributesProducer?: (s: string) => TypeAttributes; -}; - -/** - * All the transformed string type kinds and the JSON Schema formats and - * primitive type kinds they map to. Not all transformed string types map to - * primitive types. Date-time types, for example, stand on their own, but - * stringified integers map to integers. - */ -const transformedStringTypeTargetTypeKinds = { - date: { jsonSchema: "date", primitive: undefined }, - time: { jsonSchema: "time", primitive: undefined }, - "date-time": { jsonSchema: "date-time", primitive: undefined }, - uuid: { jsonSchema: "uuid", primitive: undefined }, - uri: { jsonSchema: "uri", primitive: undefined, attributesProducer: uriInferenceAttributesProducer }, - "integer-string": { jsonSchema: "integer", primitive: "integer" } as TransformedStringTypeTargets, - "bool-string": { jsonSchema: "boolean", primitive: "bool" } as TransformedStringTypeTargets -}; - -export const transformedStringTypeTargetTypeKindsMap = mapFromObject( - transformedStringTypeTargetTypeKinds as { - [kind: string]: TransformedStringTypeTargets; - } -); - -export type TransformedStringTypeKind = keyof typeof transformedStringTypeTargetTypeKinds; -export type PrimitiveStringTypeKind = "string" | TransformedStringTypeKind; -export type PrimitiveNonStringTypeKind = "none" | "any" | "null" | "bool" | "integer" | "double"; -export type PrimitiveTypeKind = PrimitiveNonStringTypeKind | PrimitiveStringTypeKind; -export type NamedTypeKind = "class" | "enum" | "union"; -export type TypeKind = PrimitiveTypeKind | NamedTypeKind | "array" | "object" | "map" | "intersection"; -export type ObjectTypeKind = "object" | "map" | "class"; - -export const transformedStringTypeKinds = new Set( - Object.getOwnPropertyNames(transformedStringTypeTargetTypeKinds) -) as ReadonlySet; - -export function isPrimitiveStringTypeKind(kind: string): kind is PrimitiveStringTypeKind { - return kind === "string" || hasOwnProperty(transformedStringTypeTargetTypeKinds, kind); -} - -export function targetTypeKindForTransformedStringTypeKind( - kind: PrimitiveStringTypeKind -): PrimitiveNonStringTypeKind | undefined { - const target = transformedStringTypeTargetTypeKindsMap.get(kind); - if (target === undefined) return undefined; - return target.primitive; -} - -export function isNumberTypeKind(kind: TypeKind): kind is "integer" | "double" { - return kind === "integer" || kind === "double"; -} - -export function isPrimitiveTypeKind(kind: TypeKind): kind is PrimitiveTypeKind { - if (isPrimitiveStringTypeKind(kind)) return true; - if (isNumberTypeKind(kind)) return true; - return kind === "none" || kind === "any" || kind === "null" || kind === "bool"; -} +import type { TypeAttributes } from "../attributes/TypeAttributes"; +import { + type TypeNames, + namesTypeAttributeKind, +} from "../attributes/TypeNames"; +import type { + BaseGraphRewriteBuilder, + TypeReconstituter, +} from "../GraphRewriting"; +import { messageAssert } from "../Messages"; +import { assert, defined, panic } from "../support/Support"; -function triviallyStructurallyCompatible(x: Type, y: Type): boolean { - if (x.index === y.index) return true; - if (x.kind === "none" || y.kind === "none") return true; - return false; -} +import { + type ObjectTypeKind, + type PrimitiveTypeKind, + type TypeKind, + isPrimitiveStringTypeKind, + triviallyStructurallyCompatible, +} from "./TransformedStringType"; +import type { TypeGraph } from "./TypeGraph"; +import { + type TypeRef, + attributesForTypeRef, + derefTypeRef, + typeRefIndex, +} from "./TypeRef"; export class TypeIdentity { private readonly _hashCode: number; - constructor(private readonly _kind: TypeKind, private readonly _components: ReadonlyArray) { + public constructor( + private readonly _kind: TypeKind, + // FIXME: strongly type this + private readonly _components: readonly unknown[], + ) { let h = hashCodeInit; h = addHashCode(h, hashCodeOf(this._kind)); for (const c of _components) { h = addHashCode(h, hashCodeOf(c)); } + this._hashCode = h; } - equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof TypeIdentity)) return false; if (this._kind !== other._kind) return false; const n = this._components.length; - assert(n === other._components.length, "Components of a type kind's identity must have the same length"); + assert( + n === other._components.length, + "Components of a type kind's identity must have the same length", + ); for (let i = 0; i < n; i++) { - if (!areEqual(this._components[i], other._components[i])) return false; + if (!areEqual(this._components[i], other._components[i])) + return false; } + return true; } - hashCode(): number { + public hashCode(): number { return this._hashCode; } } @@ -137,61 +88,70 @@ export class TypeIdentity { export type MaybeTypeIdentity = TypeIdentity | undefined; export abstract class Type { - abstract readonly kind: TypeKind; + public abstract readonly kind: TypeKind; - constructor(readonly typeRef: TypeRef, protected readonly graph: TypeGraph) {} + public constructor( + public readonly typeRef: TypeRef, + protected readonly graph: TypeGraph, + ) {} - get index(): number { + public get index(): number { return typeRefIndex(this.typeRef); } // This must return a newly allocated set - abstract getNonAttributeChildren(): Set; + public abstract getNonAttributeChildren(): Set; - getChildren(): ReadonlySet { - let result = this.getNonAttributeChildren(); + public getChildren(): ReadonlySet { + const result = this.getNonAttributeChildren(); for (const [k, v] of this.getAttributes()) { if (k.children === undefined) continue; setUnionInto(result, k.children(v)); } + return result; } - getAttributes(): TypeAttributes { + public getAttributes(): TypeAttributes { return attributesForTypeRef(this.typeRef, this.graph); } - get hasNames(): boolean { - return namesTypeAttributeKind.tryGetInAttributes(this.getAttributes()) !== undefined; + public get hasNames(): boolean { + return ( + namesTypeAttributeKind.tryGetInAttributes(this.getAttributes()) !== + undefined + ); } - getNames(): TypeNames { - return defined(namesTypeAttributeKind.tryGetInAttributes(this.getAttributes())); + public getNames(): TypeNames { + return defined( + namesTypeAttributeKind.tryGetInAttributes(this.getAttributes()), + ); } - getCombinedName(): string { + public getCombinedName(): string { return this.getNames().combinedName; } - abstract get isNullable(): boolean; + public abstract get isNullable(): boolean; // FIXME: Remove `isPrimitive` - abstract isPrimitive(): this is PrimitiveType; - abstract get identity(): MaybeTypeIdentity; - abstract reconstitute( + public abstract isPrimitive(): this is PrimitiveType; + public abstract get identity(): MaybeTypeIdentity; + public abstract reconstitute( builder: TypeReconstituter, - canonicalOrder: boolean + canonicalOrder: boolean, ): void; - get debugPrintKind(): string { + public get debugPrintKind(): string { return this.kind; } - equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof Type)) return false; return this.typeRef === other.typeRef; } - hashCode(): number { + public hashCode(): number { return hashCodeOf(this.typeRef); } @@ -200,10 +160,13 @@ export abstract class Type { protected abstract structuralEqualityStep( other: Type, conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean; - structurallyCompatible(other: Type, conflateNumbers = false): boolean { + public structurallyCompatible( + other: Type, + conflateNumbers = false, + ): boolean { function kindsCompatible(kind1: TypeKind, kind2: TypeKind): boolean { if (kind1 === kind2) return true; if (!conflateNumbers) return false; @@ -215,11 +178,11 @@ export abstract class Type { if (triviallyStructurallyCompatible(this, other)) return true; if (!kindsCompatible(this.kind, other.kind)) return false; - const workList: [Type, Type][] = [[this, other]]; + const workList: Array<[Type, Type]> = [[this, other]]; // This contains a set of pairs which are the type pairs // we have already determined to be equal. We can't just // do comparison recursively because types can have cycles. - const done: [number, number][] = []; + const done: Array<[number, number]> = []; let failed: boolean; const queue = (x: Type, y: Type): boolean => { @@ -228,6 +191,7 @@ export abstract class Type { failed = true; return false; } + workList.push([x, y]); return true; }; @@ -239,8 +203,8 @@ export abstract class Type { } if (!a.isPrimitive()) { - let ai = a.index; - let bi = b.index; + const ai = a.index; + const bi = b.index; let found = false; for (const [dai, dbi] of done) { @@ -249,23 +213,25 @@ export abstract class Type { break; } } + if (found) continue; done.push([ai, bi]); } failed = false; - if (!a.structuralEqualityStep(b, conflateNumbers, queue)) return false; + if (!a.structuralEqualityStep(b, conflateNumbers, queue)) + return false; if (failed) return false; } return true; } - getParentTypes(): ReadonlySet { + public getParentTypes(): ReadonlySet { return this.graph.getParentsOfType(this); } - getAncestorsNotInSet(set: ReadonlySet): ReadonlySet { + public getAncestorsNotInSet(set: ReadonlySet): ReadonlySet { const workList: Type[] = [this]; const processed = new Set(); const ancestors = new Set(); @@ -287,6 +253,7 @@ export abstract class Type { } } } + return ancestors; } } @@ -299,61 +266,83 @@ function identityAttributes(attributes: TypeAttributes): TypeAttributes { return mapFilter(attributes, (_, kind) => kind.inIdentity); } -export function primitiveTypeIdentity(kind: PrimitiveTypeKind, attributes: TypeAttributes): MaybeTypeIdentity { +export function primitiveTypeIdentity( + kind: PrimitiveTypeKind, + attributes: TypeAttributes, +): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes)]); } export class PrimitiveType extends Type { - constructor(typeRef: TypeRef, graph: TypeGraph, public readonly kind: PrimitiveTypeKind) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + public readonly kind: PrimitiveTypeKind, + ) { super(typeRef, graph); } - get isNullable(): boolean { - return this.kind === "null" || this.kind === "any" || this.kind === "none"; + public get isNullable(): boolean { + return ( + this.kind === "null" || this.kind === "any" || this.kind === "none" + ); } - isPrimitive(): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return true; } - getNonAttributeChildren(): Set { + public getNonAttributeChildren(): Set { return new Set(); } - get identity(): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return primitiveTypeIdentity(this.kind, this.getAttributes()); } - reconstitute(builder: TypeReconstituter): void { + public reconstitute( + builder: TypeReconstituter, + ): void { builder.getPrimitiveType(this.kind); } protected structuralEqualityStep( _other: Type, _conflateNumbers: boolean, - _queue: (a: Type, b: Type) => boolean + _queue: (a: Type, b: Type) => boolean, ): boolean { return true; } } -export function arrayTypeIdentity(attributes: TypeAttributes, itemsRef: TypeRef): MaybeTypeIdentity { +export function arrayTypeIdentity( + attributes: TypeAttributes, + itemsRef: TypeRef, +): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; - return new TypeIdentity("array", [identityAttributes(attributes), itemsRef]); + return new TypeIdentity("array", [ + identityAttributes(attributes), + itemsRef, + ]); } export class ArrayType extends Type { public readonly kind = "array"; - constructor(typeRef: TypeRef, graph: TypeGraph, private _itemsRef?: TypeRef) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + private _itemsRef?: TypeRef, + ) { super(typeRef, graph); } - setItems(itemsRef: TypeRef) { + public setItems(itemsRef: TypeRef): void { if (this._itemsRef !== undefined) { - return panic("Can only set array items once"); + panic("Can only set array items once"); } + this._itemsRef = itemsRef; } @@ -361,30 +350,33 @@ export class ArrayType extends Type { if (this._itemsRef === undefined) { return panic("Array items accessed before they were set"); } + return this._itemsRef; } - get items(): Type { + public get items(): Type { return derefTypeRef(this.getItemsRef(), this.graph); } - getNonAttributeChildren(): Set { + public getNonAttributeChildren(): Set { return new Set([this.items]); } - get isNullable(): boolean { + public get isNullable(): boolean { return false; } - isPrimitive(): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return arrayTypeIdentity(this.getAttributes(), this.getItemsRef()); } - reconstitute(builder: TypeReconstituter): void { + public reconstitute( + builder: TypeReconstituter, + ): void { const itemsRef = this.getItemsRef(); const maybeItems = builder.lookup(itemsRef); if (maybeItems === undefined) { @@ -398,37 +390,48 @@ export class ArrayType extends Type { protected structuralEqualityStep( other: ArrayType, _conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean { return queue(this.items, other.items); } } export class GenericClassProperty { - constructor(readonly typeData: T, readonly isOptional: boolean) {} + public constructor( + public readonly typeData: T, + public readonly isOptional: boolean, + ) {} - equals(other: any): boolean { + public equals(other: GenericClassProperty): boolean { if (!(other instanceof GenericClassProperty)) { return false; } - return areEqual(this.typeData, other.typeData) && this.isOptional === other.isOptional; + + return ( + areEqual(this.typeData, other.typeData) && + this.isOptional === other.isOptional + ); } - hashCode(): number { + public hashCode(): number { return hashCodeOf(this.typeData) + (this.isOptional ? 17 : 23); } } export class ClassProperty extends GenericClassProperty { - constructor(typeRef: TypeRef, readonly graph: TypeGraph, isOptional: boolean) { + public constructor( + typeRef: TypeRef, + public readonly graph: TypeGraph, + isOptional: boolean, + ) { super(typeRef, isOptional); } - get typeRef(): TypeRef { + public get typeRef(): TypeRef { return this.typeData; } - get type(): Type { + public get type(): Type { return derefTypeRef(this.typeRef, this.graph); } } @@ -437,34 +440,43 @@ function objectTypeIdentify( kind: ObjectTypeKind, attributes: TypeAttributes, properties: ReadonlyMap, - additionalPropertiesRef: TypeRef | undefined + additionalPropertiesRef: TypeRef | undefined, ): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; - return new TypeIdentity(kind, [identityAttributes(attributes), properties, additionalPropertiesRef]); + return new TypeIdentity(kind, [ + identityAttributes(attributes), + properties, + additionalPropertiesRef, + ]); } export function classTypeIdentity( attributes: TypeAttributes, - properties: ReadonlyMap + properties: ReadonlyMap, ): MaybeTypeIdentity { return objectTypeIdentify("class", attributes, properties, undefined); } export function mapTypeIdentify( attributes: TypeAttributes, - additionalPropertiesRef: TypeRef | undefined + additionalPropertiesRef: TypeRef | undefined, ): MaybeTypeIdentity { - return objectTypeIdentify("map", attributes, new Map(), additionalPropertiesRef); + return objectTypeIdentify( + "map", + attributes, + new Map(), + additionalPropertiesRef, + ); } export class ObjectType extends Type { - constructor( + public constructor( typeRef: TypeRef, graph: TypeGraph, public readonly kind: ObjectTypeKind, - readonly isFixed: boolean, + public readonly isFixed: boolean, private _properties: ReadonlyMap | undefined, - private _additionalPropertiesRef: TypeRef | undefined + private _additionalPropertiesRef: TypeRef | undefined, ) { super(typeRef, graph); @@ -472,6 +484,7 @@ export class ObjectType extends Type { if (_properties !== undefined) { assert(_properties.size === 0); } + assert(!isFixed); } else if (kind === "class") { assert(_additionalPropertiesRef === undefined); @@ -480,26 +493,35 @@ export class ObjectType extends Type { } } - setProperties(properties: ReadonlyMap, additionalPropertiesRef: TypeRef | undefined) { - assert(this._properties === undefined, "Tried to set object properties twice"); + public setProperties( + properties: ReadonlyMap, + additionalPropertiesRef: TypeRef | undefined, + ): void { + assert( + this._properties === undefined, + "Tried to set object properties twice", + ); if (this instanceof MapType) { assert(properties.size === 0, "Cannot set properties on map type"); } if (this instanceof ClassType) { - assert(additionalPropertiesRef === undefined, "Cannot set additional properties of class type"); + assert( + additionalPropertiesRef === undefined, + "Cannot set additional properties of class type", + ); } this._properties = properties; this._additionalPropertiesRef = additionalPropertiesRef; } - getProperties(): ReadonlyMap { + public getProperties(): ReadonlyMap { return defined(this._properties); } - getSortedProperties(): ReadonlyMap { + public getSortedProperties(): ReadonlyMap { return mapSortByKey(this.getProperties()); } @@ -508,57 +530,77 @@ export class ObjectType extends Type { return this._additionalPropertiesRef; } - getAdditionalProperties(): Type | undefined { + public getAdditionalProperties(): Type | undefined { const tref = this.getAdditionalPropertiesRef(); if (tref === undefined) return undefined; return derefTypeRef(tref, this.graph); } - getNonAttributeChildren(): Set { - const types = mapSortToArray(this.getProperties(), (_, k) => k).map(([_, p]) => p.type); + public getNonAttributeChildren(): Set { + const types = mapSortToArray(this.getProperties(), (_, k) => k).map( + ([_, p]) => p.type, + ); const additionalProperties = this.getAdditionalProperties(); if (additionalProperties !== undefined) { types.push(additionalProperties); } + return new Set(types); } - get isNullable(): boolean { + public get isNullable(): boolean { return false; } - isPrimitive(): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { if (this.isFixed) return undefined; return objectTypeIdentify( this.kind, this.getAttributes(), this.getProperties(), - this.getAdditionalPropertiesRef() + this.getAdditionalPropertiesRef(), ); } - reconstitute(builder: TypeReconstituter, canonicalOrder: boolean): void { + public reconstitute( + builder: TypeReconstituter, + canonicalOrder: boolean, + ): void { const sortedProperties = this.getSortedProperties(); - const propertiesInNewOrder = canonicalOrder ? sortedProperties : this.getProperties(); - const maybePropertyTypes = builder.lookupMap(mapMap(sortedProperties, cp => cp.typeRef)); - const maybeAdditionalProperties = definedMap(this._additionalPropertiesRef, r => builder.lookup(r)); + const propertiesInNewOrder = canonicalOrder + ? sortedProperties + : this.getProperties(); + const maybePropertyTypes = builder.lookupMap( + mapMap(sortedProperties, (cp) => cp.typeRef), + ); + const maybeAdditionalProperties = definedMap( + this._additionalPropertiesRef, + (r) => builder.lookup(r), + ); if ( maybePropertyTypes !== undefined && - (maybeAdditionalProperties !== undefined || this._additionalPropertiesRef === undefined) + (maybeAdditionalProperties !== undefined || + this._additionalPropertiesRef === undefined) ) { const properties = mapMap(propertiesInNewOrder, (cp, n) => - builder.makeClassProperty(defined(maybePropertyTypes.get(n)), cp.isOptional) + builder.makeClassProperty( + defined(maybePropertyTypes.get(n)), + cp.isOptional, + ), ); switch (this.kind) { case "object": assert(this.isFixed); - builder.getObjectType(properties, maybeAdditionalProperties); + builder.getObjectType( + properties, + maybeAdditionalProperties, + ); break; case "map": builder.getMapType(defined(maybeAdditionalProperties)); @@ -569,9 +611,10 @@ export class ObjectType extends Type { } else { builder.getClassType(properties); } + break; default: - return panic(`Invalid object type kind ${this.kind}`); + panic(`Invalid object type kind ${this.kind}`); } } else { switch (this.kind) { @@ -586,14 +629,22 @@ export class ObjectType extends Type { builder.getUniqueClassType(this.isFixed, undefined); break; default: - return panic(`Invalid object type kind ${this.kind}`); + panic(`Invalid object type kind ${this.kind}`); } - const reconstitutedTypes = mapMap(sortedProperties, cp => builder.reconstitute(cp.typeRef)); + const reconstitutedTypes = mapMap(sortedProperties, (cp) => + builder.reconstitute(cp.typeRef), + ); const properties = mapMap(propertiesInNewOrder, (cp, n) => - builder.makeClassProperty(defined(reconstitutedTypes.get(n)), cp.isOptional) + builder.makeClassProperty( + defined(reconstitutedTypes.get(n)), + cp.isOptional, + ), + ); + const additionalProperties = definedMap( + this._additionalPropertiesRef, + (r) => builder.reconstitute(r), ); - const additionalProperties = definedMap(this._additionalPropertiesRef, r => builder.reconstitute(r)); builder.setObjectProperties(properties, additionalProperties); } } @@ -601,7 +652,7 @@ export class ObjectType extends Type { protected structuralEqualityStep( other: ObjectType, _conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean { const pa = this.getProperties(); const pb = other.getProperties(); @@ -609,51 +660,71 @@ export class ObjectType extends Type { let failed = false; for (const [name, cpa] of pa) { const cpb = pb.get(name); - if (cpb === undefined || cpa.isOptional !== cpb.isOptional || !queue(cpa.type, cpb.type)) { + if ( + cpb === undefined || + cpa.isOptional !== cpb.isOptional || + !queue(cpa.type, cpb.type) + ) { failed = true; return false; } } + if (failed) return false; const thisAdditionalProperties = this.getAdditionalProperties(); const otherAdditionalProperties = other.getAdditionalProperties(); - if ((thisAdditionalProperties === undefined) !== (otherAdditionalProperties === undefined)) return false; - if (thisAdditionalProperties === undefined || otherAdditionalProperties === undefined) return true; + if ( + (thisAdditionalProperties === undefined) !== + (otherAdditionalProperties === undefined) + ) + return false; + if ( + thisAdditionalProperties === undefined || + otherAdditionalProperties === undefined + ) + return true; return queue(thisAdditionalProperties, otherAdditionalProperties); } } export class ClassType extends ObjectType { - constructor( + public constructor( typeRef: TypeRef, graph: TypeGraph, isFixed: boolean, - properties: ReadonlyMap | undefined + properties: ReadonlyMap | undefined, ) { super(typeRef, graph, "class", isFixed, properties, undefined); } } export class MapType extends ObjectType { - constructor(typeRef: TypeRef, graph: TypeGraph, valuesRef: TypeRef | undefined) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + valuesRef: TypeRef | undefined, + ) { super( typeRef, graph, "map", false, definedMap(valuesRef, () => new Map()), - valuesRef + valuesRef, ); } // FIXME: Remove and use `getAdditionalProperties()` instead. - get values(): Type { + public get values(): Type { return defined(this.getAdditionalProperties()); } } -export function enumTypeIdentity(attributes: TypeAttributes, cases: ReadonlySet): MaybeTypeIdentity { +export function enumTypeIdentity( + attributes: TypeAttributes, + cases: ReadonlySet, +): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity("enum", [identityAttributes(attributes), cases]); } @@ -661,34 +732,40 @@ export function enumTypeIdentity(attributes: TypeAttributes, cases: ReadonlySet< export class EnumType extends Type { public readonly kind = "enum"; - constructor(typeRef: TypeRef, graph: TypeGraph, readonly cases: ReadonlySet) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + public readonly cases: ReadonlySet, + ) { super(typeRef, graph); } - get isNullable(): boolean { + public get isNullable(): boolean { return false; } - isPrimitive(): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { + public get identity(): MaybeTypeIdentity { return enumTypeIdentity(this.getAttributes(), this.cases); } - getNonAttributeChildren(): Set { + public getNonAttributeChildren(): Set { return new Set(); } - reconstitute(builder: TypeReconstituter): void { + public reconstitute( + builder: TypeReconstituter, + ): void { builder.getEnumType(this.cases); } protected structuralEqualityStep( other: EnumType, _conflateNumbers: boolean, - _queue: (a: Type, b: Type) => void + _queue: (a: Type, b: Type) => void, ): boolean { return areEqual(this.cases, other.cases); } @@ -698,20 +775,30 @@ export function setOperationCasesEqual( typesA: Iterable, typesB: Iterable, conflateNumbers: boolean, - membersEqual: (a: Type, b: Type) => boolean + membersEqual: (a: Type, b: Type) => boolean, ): boolean { const ma = toReadonlySet(typesA); const mb = toReadonlySet(typesB); if (ma.size !== mb.size) return false; - return iterableEvery(ma, ta => { - const tb = iterableFind(mb, t => t.kind === ta.kind); + return iterableEvery(ma, (ta) => { + const tb = iterableFind(mb, (t) => t.kind === ta.kind); if (tb !== undefined) { if (membersEqual(ta, tb)) return true; } + if (conflateNumbers) { - if (ta.kind === "integer" && iterableSome(mb, t => t.kind === "double")) return true; - if (ta.kind === "double" && iterableSome(mb, t => t.kind === "integer")) return true; + if ( + ta.kind === "integer" && + iterableSome(mb, (t) => t.kind === "double") + ) + return true; + if ( + ta.kind === "double" && + iterableSome(mb, (t) => t.kind === "integer") + ) + return true; } + return false; }); } @@ -719,37 +806,41 @@ export function setOperationCasesEqual( export function setOperationTypeIdentity( kind: TypeKind, attributes: TypeAttributes, - memberRefs: ReadonlySet + memberRefs: ReadonlySet, ): MaybeTypeIdentity { if (hasUniqueIdentityAttributes(attributes)) return undefined; return new TypeIdentity(kind, [identityAttributes(attributes), memberRefs]); } -export function unionTypeIdentity(attributes: TypeAttributes, memberRefs: ReadonlySet): MaybeTypeIdentity { +export function unionTypeIdentity( + attributes: TypeAttributes, + memberRefs: ReadonlySet, +): MaybeTypeIdentity { return setOperationTypeIdentity("union", attributes, memberRefs); } export function intersectionTypeIdentity( attributes: TypeAttributes, - memberRefs: ReadonlySet + memberRefs: ReadonlySet, ): MaybeTypeIdentity { return setOperationTypeIdentity("intersection", attributes, memberRefs); } export abstract class SetOperationType extends Type { - constructor( + public constructor( typeRef: TypeRef, graph: TypeGraph, public readonly kind: TypeKind, - private _memberRefs?: ReadonlySet + private _memberRefs?: ReadonlySet, ) { super(typeRef, graph); } - setMembers(memberRefs: ReadonlySet): void { + public setMembers(memberRefs: ReadonlySet): void { if (this._memberRefs !== undefined) { - return panic("Can only set map members once"); + panic("Can only set map members once"); } + this._memberRefs = memberRefs; } @@ -757,67 +848,95 @@ export abstract class SetOperationType extends Type { if (this._memberRefs === undefined) { return panic("Map members accessed before they were set"); } + return this._memberRefs; } - get members(): ReadonlySet { - return setMap(this.getMemberRefs(), tref => derefTypeRef(tref, this.graph)); + public get members(): ReadonlySet { + return setMap(this.getMemberRefs(), (tref) => + derefTypeRef(tref, this.graph), + ); } - get sortedMembers(): ReadonlySet { + public get sortedMembers(): ReadonlySet { return this.getNonAttributeChildren(); } - getNonAttributeChildren(): Set { + public getNonAttributeChildren(): Set { // FIXME: We're assuming no two members of the same kind. - return setSortBy(this.members, t => t.kind); + return setSortBy(this.members, (t) => t.kind); } - isPrimitive(): this is PrimitiveType { + public isPrimitive(): this is PrimitiveType { return false; } - get identity(): MaybeTypeIdentity { - return setOperationTypeIdentity(this.kind, this.getAttributes(), this.getMemberRefs()); + public get identity(): MaybeTypeIdentity { + return setOperationTypeIdentity( + this.kind, + this.getAttributes(), + this.getMemberRefs(), + ); } protected reconstituteSetOperation( builder: TypeReconstituter, canonicalOrder: boolean, - getType: (members: ReadonlySet | undefined) => void + getType: (members: ReadonlySet | undefined) => void, ): void { - const sortedMemberRefs = mapMap(this.sortedMembers.entries(), t => t.typeRef); - const membersInOrder = canonicalOrder ? this.sortedMembers : this.members; + const sortedMemberRefs = mapMap( + this.sortedMembers.entries(), + (t) => t.typeRef, + ); + const membersInOrder = canonicalOrder + ? this.sortedMembers + : this.members; const maybeMembers = builder.lookupMap(sortedMemberRefs); if (maybeMembers === undefined) { getType(undefined); const reconstituted = builder.reconstituteMap(sortedMemberRefs); - builder.setSetOperationMembers(setMap(membersInOrder, t => defined(reconstituted.get(t)))); + builder.setSetOperationMembers( + setMap(membersInOrder, (t) => defined(reconstituted.get(t))), + ); } else { - getType(setMap(membersInOrder, t => defined(maybeMembers.get(t)))); + getType( + setMap(membersInOrder, (t) => defined(maybeMembers.get(t))), + ); } } protected structuralEqualityStep( other: SetOperationType, conflateNumbers: boolean, - queue: (a: Type, b: Type) => boolean + queue: (a: Type, b: Type) => boolean, ): boolean { - return setOperationCasesEqual(this.members, other.members, conflateNumbers, queue); + return setOperationCasesEqual( + this.members, + other.members, + conflateNumbers, + queue, + ); } } export class IntersectionType extends SetOperationType { - constructor(typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + memberRefs?: ReadonlySet, + ) { super(typeRef, graph, "intersection", memberRefs); } - get isNullable(): boolean { + public get isNullable(): boolean { return panic("isNullable not implemented for IntersectionType"); } - reconstitute(builder: TypeReconstituter, canonicalOrder: boolean): void { - this.reconstituteSetOperation(builder, canonicalOrder, members => { + public reconstitute( + builder: TypeReconstituter, + canonicalOrder: boolean, + ): void { + this.reconstituteSetOperation(builder, canonicalOrder, (members) => { if (members === undefined) { builder.getUniqueIntersectionType(); } else { @@ -828,34 +947,41 @@ export class IntersectionType extends SetOperationType { } export class UnionType extends SetOperationType { - constructor(typeRef: TypeRef, graph: TypeGraph, memberRefs?: ReadonlySet) { + public constructor( + typeRef: TypeRef, + graph: TypeGraph, + memberRefs?: ReadonlySet, + ) { super(typeRef, graph, "union", memberRefs); if (memberRefs !== undefined) { messageAssert(memberRefs.size > 0, "IRNoEmptyUnions", {}); } } - setMembers(memberRefs: ReadonlySet): void { + public setMembers(memberRefs: ReadonlySet): void { messageAssert(memberRefs.size > 0, "IRNoEmptyUnions", {}); super.setMembers(memberRefs); } - get stringTypeMembers(): ReadonlySet { - return setFilter(this.members, t => isPrimitiveStringTypeKind(t.kind) || t.kind === "enum"); + public get stringTypeMembers(): ReadonlySet { + return setFilter( + this.members, + (t) => isPrimitiveStringTypeKind(t.kind) || t.kind === "enum", + ); } - findMember(kind: TypeKind): Type | undefined { - return iterableFind(this.members, t => t.kind === kind); + public findMember(kind: TypeKind): Type | undefined { + return iterableFind(this.members, (t) => t.kind === kind); } - get isNullable(): boolean { + public get isNullable(): boolean { return this.findMember("null") !== undefined; } - get isCanonical(): boolean { + public get isCanonical(): boolean { const members = this.members; if (members.size <= 1) return false; - const kinds = setMap(members, t => t.kind); + const kinds = setMap(members, (t) => t.kind); if (kinds.size < members.size) return false; if (kinds.has("union") || kinds.has("intersection")) return false; if (kinds.has("none") || kinds.has("any")) return false; @@ -870,8 +996,11 @@ export class UnionType extends SetOperationType { return true; } - reconstitute(builder: TypeReconstituter, canonicalOrder: boolean): void { - this.reconstituteSetOperation(builder, canonicalOrder, members => { + public reconstitute( + builder: TypeReconstituter, + canonicalOrder: boolean, + ): void { + this.reconstituteSetOperation(builder, canonicalOrder, (members) => { if (members === undefined) { builder.getUniqueUnionType(); } else { diff --git a/packages/quicktype-core/src/TypeBuilder.ts b/packages/quicktype-core/src/Type/TypeBuilder.ts similarity index 53% rename from packages/quicktype-core/src/TypeBuilder.ts rename to packages/quicktype-core/src/Type/TypeBuilder.ts index d7d0a4b59..9f04812d9 100644 --- a/packages/quicktype-core/src/TypeBuilder.ts +++ b/packages/quicktype-core/src/Type/TypeBuilder.ts @@ -1,138 +1,114 @@ import { EqualityMap, - mapMap, - mapSortByKey, + areEqual, + definedMap, iterableEvery, mapFilter, mapFind, - areEqual, - setUnionManyInto, - definedMap, - withDefault + mapMap, + mapSortByKey, + withDefault, } from "collection-utils"; import { - PrimitiveTypeKind, - Type, - PrimitiveType, - EnumType, - MapType, + StringTypes, + stringTypesTypeAttributeKind, +} from "../attributes/StringTypes"; +import { + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, +} from "../attributes/TypeAttributes"; +import { assert, defined, panic } from "../support/Support"; + +import { provenanceTypeAttributeKind } from "./ProvenanceTypeAttributeKind"; +import { + type PrimitiveTypeKind, + isPrimitiveStringTypeKind, +} from "./TransformedStringType"; +import { ArrayType, - ClassType, - UnionType, - PrimitiveStringTypeKind, ClassProperty, + ClassType, + EnumType, IntersectionType, + MapType, + type MaybeTypeIdentity, ObjectType, - primitiveTypeIdentity, - enumTypeIdentity, - mapTypeIdentify, + PrimitiveType, + type Type, + type TypeIdentity, + UnionType, arrayTypeIdentity, classTypeIdentity, - unionTypeIdentity, + enumTypeIdentity, intersectionTypeIdentity, - MaybeTypeIdentity, - TypeIdentity, - TransformedStringTypeKind, - isPrimitiveStringTypeKind, - transformedStringTypeKinds, - TypeKind + mapTypeIdentify, + primitiveTypeIdentity, + unionTypeIdentity, } from "./Type"; -import { TypeGraph, TypeRef, makeTypeRef, derefTypeRef, typeRefIndex, assertTypeRefGraph } from "./TypeGraph"; import { - TypeAttributes, - combineTypeAttributes, - TypeAttributeKind, - emptyTypeAttributes -} from "./attributes/TypeAttributes"; -import { defined, assert, panic } from "./support/Support"; -import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTypes"; - -// FIXME: Don't infer provenance. All original types should be present in -// non-inferred form in the final graph. -class ProvenanceTypeAttributeKind extends TypeAttributeKind> { - constructor() { - super("provenance"); - } - - appliesToTypeKind(_kind: TypeKind): boolean { - return true; - } - - combine(arr: Set[]): Set { - return setUnionManyInto(new Set(), arr); - } - - makeInferred(p: Set): Set { - return p; - } - - stringify(p: Set): string { - return Array.from(p) - .sort() - .map(i => i.toString()) - .join(","); - } -} - -export const provenanceTypeAttributeKind: TypeAttributeKind> = new ProvenanceTypeAttributeKind(); - -export type StringTypeMapping = ReadonlyMap; - -export function stringTypeMappingGet(stm: StringTypeMapping, kind: TransformedStringTypeKind): PrimitiveStringTypeKind { - const mapped = stm.get(kind); - if (mapped === undefined) return "string"; - return mapped; -} - -let noStringTypeMapping: StringTypeMapping | undefined; - -export function getNoStringTypeMapping(): StringTypeMapping { - if (noStringTypeMapping === undefined) { - noStringTypeMapping = new Map( - Array.from(transformedStringTypeKinds).map( - k => [k, k] as [TransformedStringTypeKind, PrimitiveStringTypeKind] - ) - ); - } - return noStringTypeMapping; -} + type StringTypeMapping, + stringTypeMappingGet, +} from "./TypeBuilderUtils"; +import type { TypeGraph } from "./TypeGraph"; +import { + type TypeRef, + assertTypeRefGraph, + derefTypeRef, + makeTypeRef, + typeRefIndex, +} from "./TypeRef"; export class TypeBuilder { - readonly typeGraph: TypeGraph; + // @ts-expect-error must manually set TypeGraph + private _typeGraph: TypeGraph; protected readonly topLevels: Map = new Map(); - protected readonly types: (Type | undefined)[] = []; + + protected readonly types: Array = []; + private readonly typeAttributes: TypeAttributes[] = []; private _addedForwardingIntersection = false; - constructor( - typeGraphSerial: number, + public constructor( private readonly _stringTypeMapping: StringTypeMapping, - readonly canonicalOrder: boolean, + public readonly canonicalOrder: boolean, private readonly _allPropertiesOptional: boolean, private readonly _addProvenanceAttributes: boolean, - inheritsProvenanceAttributes: boolean + inheritsProvenanceAttributes: boolean, ) { assert( !_addProvenanceAttributes || !inheritsProvenanceAttributes, - "We can't both inherit as well as add provenance" + "We can't both inherit as well as add provenance", ); - this.typeGraph = new TypeGraph(this, typeGraphSerial, _addProvenanceAttributes || inheritsProvenanceAttributes); } - addTopLevel(name: string, tref: TypeRef): void { + public get typeGraph(): TypeGraph { + assert(!!this._typeGraph, "TypeBuilder must have a TypeGraph"); + return this._typeGraph; + } + + /** typeGraph must be set externally to prevent import cycle of TypeGraph constructor */ + public set typeGraph(typeGraph: TypeGraph) { + this._typeGraph = typeGraph; + } + + public addTopLevel(name: string, tref: TypeRef): void { // assert(t.typeGraph === this.typeGraph, "Adding top-level to wrong type graph"); - assert(!this.topLevels.has(name), "Trying to add top-level with existing name"); + assert( + !this.topLevels.has(name), + "Trying to add top-level with existing name", + ); assert( this.types[typeRefIndex(tref)] !== undefined, - "Trying to add a top-level type that doesn't exist (yet?)" + "Trying to add a top-level type that doesn't exist (yet?)", ); this.topLevels.set(name, tref); } - reserveTypeRef(): TypeRef { + public reserveTypeRef(): TypeRef { const index = this.types.length; // console.log(`reserving ${index}`); this.types.push(undefined); @@ -149,16 +125,24 @@ export class TypeBuilder { assertTypeRefGraph(tref, this.typeGraph); } - private assertTypeRefSetGraph(trefs: ReadonlySet | undefined): void { + private assertTypeRefSetGraph( + trefs: ReadonlySet | undefined, + ): void { if (trefs === undefined) return; - trefs.forEach(tref => this.assertTypeRefGraph(tref)); + trefs.forEach((tref) => this.assertTypeRefGraph(tref)); } - private filterTypeAttributes(t: Type, attributes: TypeAttributes): TypeAttributes { - const filtered = mapFilter(attributes, (_, k) => k.appliesToTypeKind(t.kind)); + private filterTypeAttributes( + t: Type, + attributes: TypeAttributes, + ): TypeAttributes { + const filtered = mapFilter(attributes, (_, k) => + k.appliesToTypeKind(t.kind), + ); if (attributes.size !== filtered.size) { this.setLostTypeAttributes(); } + return filtered; } @@ -167,45 +151,58 @@ export class TypeBuilder { const index = typeRefIndex(tref); // const name = names !== undefined ? ` ${names.combinedName}` : ""; // console.log(`committing ${t.kind}${name} to ${index}`); - assert(this.types[index] === undefined, "A type index was committed twice"); + assert( + this.types[index] === undefined, + "A type index was committed twice", + ); this.types[index] = t; - this.typeAttributes[index] = this.filterTypeAttributes(t, this.typeAttributes[index]); + this.typeAttributes[index] = this.filterTypeAttributes( + t, + this.typeAttributes[index], + ); } protected addType( forwardingRef: TypeRef | undefined, creator: (tref: TypeRef) => T, - attributes: TypeAttributes | undefined + attributes: TypeAttributes | undefined, ): TypeRef { if (forwardingRef !== undefined) { this.assertTypeRefGraph(forwardingRef); assert(this.types[typeRefIndex(forwardingRef)] === undefined); } - const tref = forwardingRef !== undefined ? forwardingRef : this.reserveTypeRef(); + + const tref = forwardingRef ?? this.reserveTypeRef(); if (attributes !== undefined) { const index = typeRefIndex(tref); - this.typeAttributes[index] = combineTypeAttributes("union", this.typeAttributes[index], attributes); + this.typeAttributes[index] = combineTypeAttributes( + "union", + this.typeAttributes[index], + attributes, + ); } + const t = creator(tref); this.commitType(tref, t); return tref; } - typeAtIndex(index: number): Type { + public typeAtIndex(index: number): Type { const maybeType = this.types[index]; if (maybeType === undefined) { return panic("Trying to deref an undefined type in a type builder"); } + return maybeType; } - atIndex(index: number): [Type, TypeAttributes] { + public atIndex(index: number): [Type, TypeAttributes] { const t = this.typeAtIndex(index); const attribtues = this.typeAttributes[index]; return [t, attribtues]; } - addAttributes(tref: TypeRef, attributes: TypeAttributes): void { + public addAttributes(tref: TypeRef, attributes: TypeAttributes): void { this.assertTypeRefGraph(tref); const index = typeRefIndex(tref); const existingAttributes = this.typeAttributes[index]; @@ -216,43 +213,78 @@ export class TypeBuilder { if (existing === undefined) return false; return areEqual(existing, v); }), - "Can't add different identity type attributes to an existing type" + "Can't add different identity type attributes to an existing type", ); const maybeType = this.types[index]; if (maybeType !== undefined) { attributes = this.filterTypeAttributes(maybeType, attributes); } - const nonIdentityAttributes = mapFilter(attributes, (_, k) => !k.inIdentity); - this.typeAttributes[index] = combineTypeAttributes("union", existingAttributes, nonIdentityAttributes); + + const nonIdentityAttributes = mapFilter( + attributes, + (_, k) => !k.inIdentity, + ); + this.typeAttributes[index] = combineTypeAttributes( + "union", + existingAttributes, + nonIdentityAttributes, + ); } - finish(): TypeGraph { - this.typeGraph.freeze(this.topLevels, this.types.map(defined), this.typeAttributes); + public finish(): TypeGraph { + this.typeGraph.freeze( + this.topLevels, + this.types.map(defined), + this.typeAttributes, + ); return this.typeGraph; } - protected addForwardingIntersection(forwardingRef: TypeRef, tref: TypeRef): TypeRef { + protected addForwardingIntersection( + forwardingRef: TypeRef, + tref: TypeRef, + ): TypeRef { this.assertTypeRefGraph(tref); this._addedForwardingIntersection = true; - return this.addType(forwardingRef, tr => new IntersectionType(tr, this.typeGraph, new Set([tref])), undefined); + return this.addType( + forwardingRef, + (tr) => new IntersectionType(tr, this.typeGraph, new Set([tref])), + undefined, + ); } - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: undefined): undefined; - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef): TypeRef; - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined; - protected forwardIfNecessary(forwardingRef: TypeRef | undefined, tref: TypeRef | undefined): TypeRef | undefined { + protected forwardIfNecessary( + forwardingRef: TypeRef | undefined, + tref: undefined, + ): undefined; + protected forwardIfNecessary( + forwardingRef: TypeRef | undefined, + tref: TypeRef, + ): TypeRef; + protected forwardIfNecessary( + forwardingRef: TypeRef | undefined, + tref: TypeRef | undefined, + ): TypeRef | undefined; + protected forwardIfNecessary( + forwardingRef: TypeRef | undefined, + tref: TypeRef | undefined, + ): TypeRef | undefined { if (tref === undefined) return undefined; if (forwardingRef === undefined) return tref; return this.addForwardingIntersection(forwardingRef, tref); } - get didAddForwardingIntersection(): boolean { + public get didAddForwardingIntersection(): boolean { return this._addedForwardingIntersection; } - private readonly _typeForIdentity: EqualityMap = new EqualityMap(); + private readonly _typeForIdentity: EqualityMap = + new EqualityMap(); - private registerTypeForIdentity(identity: MaybeTypeIdentity, tref: TypeRef): void { + private registerTypeForIdentity( + identity: MaybeTypeIdentity, + tref: TypeRef, + ): void { if (identity === undefined) return; this._typeForIdentity.set(identity, tref); } @@ -265,7 +297,7 @@ export class TypeBuilder { identityMaker: () => MaybeTypeIdentity, creator: (tr: TypeRef) => Type, attributes: TypeAttributes | undefined, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { const identity = this.makeIdentity(identityMaker); let maybeTypeRef: TypeRef | undefined; @@ -274,6 +306,7 @@ export class TypeBuilder { } else { maybeTypeRef = this._typeForIdentity.get(identity); } + if (maybeTypeRef !== undefined) { const result = this.forwardIfNecessary(forwardingRef, maybeTypeRef); if (attributes !== undefined) { @@ -283,9 +316,10 @@ export class TypeBuilder { // asserts that no identity attributes are added later. this.addAttributes( result, - mapFilter(attributes, (_, k) => !k.inIdentity) + mapFilter(attributes, (_, k) => !k.inIdentity), ); } + return result; } @@ -298,94 +332,136 @@ export class TypeBuilder { this.registerTypeForIdentity(t.identity, t.typeRef); } - getPrimitiveType(kind: PrimitiveTypeKind, maybeAttributes?: TypeAttributes, forwardingRef?: TypeRef): TypeRef { + public getPrimitiveType( + kind: PrimitiveTypeKind, + maybeAttributes?: TypeAttributes, + forwardingRef?: TypeRef, + ): TypeRef { const attributes = withDefault(maybeAttributes, emptyTypeAttributes); // FIXME: Why do date/time types need a StringTypes attribute? // FIXME: Remove this from here and put it into flattenStrings - let stringTypes = kind === "string" ? undefined : StringTypes.unrestricted; + const stringTypes = + kind === "string" ? undefined : StringTypes.unrestricted; if (isPrimitiveStringTypeKind(kind) && kind !== "string") { kind = stringTypeMappingGet(this._stringTypeMapping, kind); } + if (kind === "string") { return this.getStringType(attributes, stringTypes, forwardingRef); } + return this.getOrAddType( () => primitiveTypeIdentity(kind, attributes), - tr => new PrimitiveType(tr, this.typeGraph, kind), + (tr) => new PrimitiveType(tr, this.typeGraph, kind), attributes, - forwardingRef + forwardingRef, ); } - getStringType(attributes: TypeAttributes, stringTypes: StringTypes | undefined, forwardingRef?: TypeRef): TypeRef { - const existingStringTypes = mapFind(attributes, (_, k) => k === stringTypesTypeAttributeKind); + public getStringType( + attributes: TypeAttributes, + stringTypes: StringTypes | undefined, + forwardingRef?: TypeRef, + ): TypeRef { + const existingStringTypes = mapFind( + attributes, + (_, k) => k === stringTypesTypeAttributeKind, + ); assert( (stringTypes === undefined) !== (existingStringTypes === undefined), - "Must instantiate string type with one enum case attribute" + "Must instantiate string type with one enum case attribute", ); if (existingStringTypes === undefined) { attributes = combineTypeAttributes( "union", attributes, - stringTypesTypeAttributeKind.makeAttributes(defined(stringTypes)) + stringTypesTypeAttributeKind.makeAttributes( + defined(stringTypes), + ), ); } + return this.getOrAddType( () => primitiveTypeIdentity("string", attributes), - tr => new PrimitiveType(tr, this.typeGraph, "string"), + (tr) => new PrimitiveType(tr, this.typeGraph, "string"), attributes, - forwardingRef + forwardingRef, ); } - getEnumType(attributes: TypeAttributes, cases: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + public getEnumType( + attributes: TypeAttributes, + cases: ReadonlySet, + forwardingRef?: TypeRef, + ): TypeRef { return this.getOrAddType( () => enumTypeIdentity(attributes, cases), - tr => new EnumType(tr, this.typeGraph, cases), + (tr) => new EnumType(tr, this.typeGraph, cases), attributes, - forwardingRef + forwardingRef, ); } - makeClassProperty(tref: TypeRef, isOptional: boolean): ClassProperty { + public makeClassProperty( + tref: TypeRef, + isOptional: boolean, + ): ClassProperty { return new ClassProperty(tref, this.typeGraph, isOptional); } - getUniqueObjectType( + public getUniqueObjectType( attributes: TypeAttributes, properties: ReadonlyMap | undefined, additionalProperties: TypeRef | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { this.assertTypeRefGraph(additionalProperties); - properties = definedMap(properties, p => this.modifyPropertiesIfNecessary(p)); + properties = definedMap(properties, (p) => + this.modifyPropertiesIfNecessary(p), + ); return this.addType( forwardingRef, - tref => new ObjectType(tref, this.typeGraph, "object", true, properties, additionalProperties), - attributes + (tref) => + new ObjectType( + tref, + this.typeGraph, + "object", + true, + properties, + additionalProperties, + ), + attributes, ); } - getUniqueMapType(forwardingRef?: TypeRef): TypeRef { - return this.addType(forwardingRef, tr => new MapType(tr, this.typeGraph, undefined), undefined); + public getUniqueMapType(forwardingRef?: TypeRef): TypeRef { + return this.addType( + forwardingRef, + (tr) => new MapType(tr, this.typeGraph, undefined), + undefined, + ); } - getMapType(attributes: TypeAttributes, values: TypeRef, forwardingRef?: TypeRef): TypeRef { + public getMapType( + attributes: TypeAttributes, + values: TypeRef, + forwardingRef?: TypeRef, + ): TypeRef { this.assertTypeRefGraph(values); return this.getOrAddType( () => mapTypeIdentify(attributes, values), - tr => new MapType(tr, this.typeGraph, values), + (tr) => new MapType(tr, this.typeGraph, values), attributes, - forwardingRef + forwardingRef, ); } - setObjectProperties( + public setObjectProperties( ref: TypeRef, properties: ReadonlyMap, - additionalProperties: TypeRef | undefined + additionalProperties: TypeRef | undefined, ): void { this.assertTypeRefGraph(additionalProperties); @@ -393,134 +469,175 @@ export class TypeBuilder { if (!(type instanceof ObjectType)) { return panic("Tried to set properties of non-object type"); } - type.setProperties(this.modifyPropertiesIfNecessary(properties), additionalProperties); + + type.setProperties( + this.modifyPropertiesIfNecessary(properties), + additionalProperties, + ); this.registerType(type); } - getUniqueArrayType(forwardingRef?: TypeRef): TypeRef { - return this.addType(forwardingRef, tr => new ArrayType(tr, this.typeGraph, undefined), undefined); + public getUniqueArrayType(forwardingRef?: TypeRef): TypeRef { + return this.addType( + forwardingRef, + (tr) => new ArrayType(tr, this.typeGraph, undefined), + undefined, + ); } - getArrayType(attributes: TypeAttributes, items: TypeRef, forwardingRef?: TypeRef): TypeRef { + public getArrayType( + attributes: TypeAttributes, + items: TypeRef, + forwardingRef?: TypeRef, + ): TypeRef { this.assertTypeRefGraph(items); return this.getOrAddType( () => arrayTypeIdentity(attributes, items), - tr => new ArrayType(tr, this.typeGraph, items), + (tr) => new ArrayType(tr, this.typeGraph, items), attributes, - forwardingRef + forwardingRef, ); } - setArrayItems(ref: TypeRef, items: TypeRef): void { + public setArrayItems(ref: TypeRef, items: TypeRef): void { this.assertTypeRefGraph(items); const type = derefTypeRef(ref, this.typeGraph); if (!(type instanceof ArrayType)) { - return panic("Tried to set items of non-array type"); + panic("Tried to set items of non-array type"); } + type.setItems(items); this.registerType(type); } - modifyPropertiesIfNecessary(properties: ReadonlyMap): ReadonlyMap { - properties.forEach(p => this.assertTypeRefGraph(p.typeRef)); + public modifyPropertiesIfNecessary( + properties: ReadonlyMap, + ): ReadonlyMap { + properties.forEach((p) => this.assertTypeRefGraph(p.typeRef)); if (this.canonicalOrder) { properties = mapSortByKey(properties); } + if (this._allPropertiesOptional) { - properties = mapMap(properties, cp => this.makeClassProperty(cp.typeRef, true)); + properties = mapMap(properties, (cp) => + this.makeClassProperty(cp.typeRef, true), + ); } + return properties; } - getClassType( + public getClassType( attributes: TypeAttributes, properties: ReadonlyMap, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { properties = this.modifyPropertiesIfNecessary(properties); return this.getOrAddType( () => classTypeIdentity(attributes, properties), - tr => new ClassType(tr, this.typeGraph, false, properties), + (tr) => new ClassType(tr, this.typeGraph, false, properties), attributes, - forwardingRef + forwardingRef, ); } // FIXME: Maybe just distinguish between this and `getClassType` // via a flag? That would make `ClassType.map` simpler. - getUniqueClassType( + public getUniqueClassType( attributes: TypeAttributes, isFixed: boolean, properties: ReadonlyMap | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { - properties = definedMap(properties, p => this.modifyPropertiesIfNecessary(p)); + properties = definedMap(properties, (p) => + this.modifyPropertiesIfNecessary(p), + ); return this.addType( forwardingRef, - tref => new ClassType(tref, this.typeGraph, isFixed, properties), - attributes + (tref) => new ClassType(tref, this.typeGraph, isFixed, properties), + attributes, ); } - getUnionType(attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + public getUnionType( + attributes: TypeAttributes, + members: ReadonlySet, + forwardingRef?: TypeRef, + ): TypeRef { this.assertTypeRefSetGraph(members); return this.getOrAddType( () => unionTypeIdentity(attributes, members), - tr => new UnionType(tr, this.typeGraph, members), + (tr) => new UnionType(tr, this.typeGraph, members), attributes, - forwardingRef + forwardingRef, ); } // FIXME: why do we sometimes call this with defined members??? - getUniqueUnionType( + public getUniqueUnionType( attributes: TypeAttributes, members: ReadonlySet | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { this.assertTypeRefSetGraph(members); - return this.addType(forwardingRef, tref => new UnionType(tref, this.typeGraph, members), attributes); + return this.addType( + forwardingRef, + (tref) => new UnionType(tref, this.typeGraph, members), + attributes, + ); } - getIntersectionType(attributes: TypeAttributes, members: ReadonlySet, forwardingRef?: TypeRef): TypeRef { + public getIntersectionType( + attributes: TypeAttributes, + members: ReadonlySet, + forwardingRef?: TypeRef, + ): TypeRef { this.assertTypeRefSetGraph(members); return this.getOrAddType( () => intersectionTypeIdentity(attributes, members), - tr => new IntersectionType(tr, this.typeGraph, members), + (tr) => new IntersectionType(tr, this.typeGraph, members), attributes, - forwardingRef + forwardingRef, ); } // FIXME: why do we sometimes call this with defined members??? - getUniqueIntersectionType( + public getUniqueIntersectionType( attributes: TypeAttributes, members: ReadonlySet | undefined, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { this.assertTypeRefSetGraph(members); - return this.addType(forwardingRef, tref => new IntersectionType(tref, this.typeGraph, members), attributes); + return this.addType( + forwardingRef, + (tref) => new IntersectionType(tref, this.typeGraph, members), + attributes, + ); } - setSetOperationMembers(ref: TypeRef, members: ReadonlySet): void { + public setSetOperationMembers( + ref: TypeRef, + members: ReadonlySet, + ): void { this.assertTypeRefSetGraph(members); const type = derefTypeRef(ref, this.typeGraph); if (!(type instanceof UnionType || type instanceof IntersectionType)) { - return panic("Tried to set members of non-set-operation type"); + panic("Tried to set members of non-set-operation type"); } + type.setMembers(members); this.registerType(type); } - setLostTypeAttributes(): void { + public setLostTypeAttributes(): void { return; } } diff --git a/packages/quicktype-core/src/Type/TypeBuilderUtils.ts b/packages/quicktype-core/src/Type/TypeBuilderUtils.ts new file mode 100644 index 000000000..7743f361b --- /dev/null +++ b/packages/quicktype-core/src/Type/TypeBuilderUtils.ts @@ -0,0 +1,37 @@ +import { + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + transformedStringTypeKinds, +} from "./TransformedStringType"; + +export type StringTypeMapping = ReadonlyMap< + TransformedStringTypeKind, + PrimitiveStringTypeKind +>; + +export function stringTypeMappingGet( + stm: StringTypeMapping, + kind: TransformedStringTypeKind, +): PrimitiveStringTypeKind { + const mapped = stm.get(kind); + if (mapped === undefined) return "string"; + return mapped; +} + +let noStringTypeMapping: StringTypeMapping | undefined; + +export function getNoStringTypeMapping(): StringTypeMapping { + if (noStringTypeMapping === undefined) { + noStringTypeMapping = new Map( + Array.from(transformedStringTypeKinds).map( + (k) => + [k, k] as [ + TransformedStringTypeKind, + PrimitiveStringTypeKind, + ], + ), + ); + } + + return noStringTypeMapping; +} diff --git a/packages/quicktype-core/src/Type/TypeGraph.ts b/packages/quicktype-core/src/Type/TypeGraph.ts new file mode 100644 index 000000000..f20f3a209 --- /dev/null +++ b/packages/quicktype-core/src/Type/TypeGraph.ts @@ -0,0 +1,526 @@ +import { mapMap, setSubtract, setUnionManyInto } from "collection-utils"; + +import { + type TypeAttributeKind, + type TypeAttributes, + emptyTypeAttributes, +} from "../attributes/TypeAttributes"; +import { Graph } from "../Graph"; +import { + type BaseGraphRewriteBuilder, + GraphRemapBuilder, + GraphRewriteBuilder, +} from "../GraphRewriting"; +import { messageError } from "../Messages"; +import { assert, defined, mustNotHappen } from "../support/Support"; + +import { provenanceTypeAttributeKind } from "./ProvenanceTypeAttributeKind"; +import type { Type } from "./Type"; +import type { TypeBuilder } from "./TypeBuilder"; +import { + type StringTypeMapping, + getNoStringTypeMapping, +} from "./TypeBuilderUtils"; +import { removeIndirectionIntersections } from "./TypeGraphUtils"; +import { + type TypeRef, + assertTypeRefGraph, + derefTypeRef, + typeRefIndex, +} from "./TypeRef"; +import { + type SeparatedNamedTypes, + isNamedType, + separateNamedTypes, +} from "./TypeUtils"; + +export class TypeAttributeStore { + private readonly _topLevelValues: Map = new Map(); + + public constructor( + private readonly _typeGraph: TypeGraph, + private _values: Array, + ) {} + + private getTypeIndex(t: Type): number { + const tref = t.typeRef; + assertTypeRefGraph(tref, this._typeGraph); + return typeRefIndex(tref); + } + + public attributesForType(t: Type): TypeAttributes { + const index = this.getTypeIndex(t); + const maybeAttributes = this._values[index]; + if (maybeAttributes !== undefined) { + return maybeAttributes; + } + + return emptyTypeAttributes; + } + + public attributesForTopLevel(name: string): TypeAttributes { + const maybeAttributes = this._topLevelValues.get(name); + if (maybeAttributes !== undefined) { + return maybeAttributes; + } + + return emptyTypeAttributes; + } + + public setInMap( + attributes: TypeAttributes, + kind: TypeAttributeKind, + value: T, + ): TypeAttributes { + // FIXME: This is potentially super slow + return new Map(attributes).set(kind, value); + } + + public set(kind: TypeAttributeKind, t: Type, value: T): void { + const index = this.getTypeIndex(t); + while (index >= this._values.length) { + this._values.push(undefined); + } + + this._values[index] = this.setInMap( + this.attributesForType(t), + kind, + value, + ); + } + + public setForTopLevel( + kind: TypeAttributeKind, + topLevelName: string, + value: T, + ): void { + this._topLevelValues.set( + topLevelName, + this.setInMap( + this.attributesForTopLevel(topLevelName), + kind, + value, + ), + ); + } + + public tryGetInMap( + attributes: TypeAttributes, + kind: TypeAttributeKind, + ): T | undefined { + return attributes.get(kind); + } + + public tryGet(kind: TypeAttributeKind, t: Type): T | undefined { + return this.tryGetInMap(this.attributesForType(t), kind); + } + + public tryGetForTopLevel( + kind: TypeAttributeKind, + topLevelName: string, + ): T | undefined { + return this.tryGetInMap(this.attributesForTopLevel(topLevelName), kind); + } +} + +export class TypeAttributeStoreView { + public constructor( + private readonly _attributeStore: TypeAttributeStore, + private readonly _definition: TypeAttributeKind, + ) {} + + public set(t: Type, value: T): void { + this._attributeStore.set(this._definition, t, value); + } + + public setForTopLevel(name: string, value: T): void { + this._attributeStore.setForTopLevel(this._definition, name, value); + } + + public tryGet(t: Type): T | undefined { + return this._attributeStore.tryGet(this._definition, t); + } + + public get(t: Type): T { + return defined(this.tryGet(t)); + } + + public tryGetForTopLevel(name: string): T | undefined { + return this._attributeStore.tryGetForTopLevel(this._definition, name); + } + + public getForTopLevel(name: string): T { + return defined(this.tryGetForTopLevel(name)); + } +} + +export class TypeGraph { + private _typeBuilder?: TypeBuilder; + + private _attributeStore: TypeAttributeStore | undefined = undefined; + + // FIXME: OrderedMap? We lose the order in PureScript right now, though, + // and maybe even earlier in the TypeScript driver. + private _topLevels: Map = new Map(); + + private _types?: Type[]; + + private _parents: Array> | undefined = undefined; + + private _printOnRewrite = false; + + public constructor( + typeBuilder: TypeBuilder, + public readonly serial: number, + private readonly _haveProvenanceAttributes: boolean, + ) { + this._typeBuilder = typeBuilder; + } + + private get isFrozen(): boolean { + return this._typeBuilder === undefined; + } + + public get attributeStore(): TypeAttributeStore { + return defined(this._attributeStore); + } + + public freeze( + topLevels: ReadonlyMap, + types: Type[], + typeAttributes: Array, + ): void { + assert(!this.isFrozen, "Tried to freeze TypeGraph a second time"); + for (const t of types) { + assertTypeRefGraph(t.typeRef, this); + } + + this._attributeStore = new TypeAttributeStore(this, typeAttributes); + + // The order of these three statements matters. If we set _typeBuilder + // to undefined before we deref the TypeRefs, then we need to set _types + // before, also, because the deref will call into typeAtIndex, which requires + // either a _typeBuilder or a _types. + this._types = types; + this._typeBuilder = undefined; + this._topLevels = mapMap(topLevels, (tref) => derefTypeRef(tref, this)); + } + + public get topLevels(): ReadonlyMap { + assert(this.isFrozen, "Cannot get top-levels from a non-frozen graph"); + + return this._topLevels; + } + + public typeAtIndex(index: number): Type { + if (this._typeBuilder !== undefined) { + return this._typeBuilder.typeAtIndex(index); + } + + return defined(this._types)[index]; + } + + public atIndex(index: number): [Type, TypeAttributes] { + if (this._typeBuilder !== undefined) { + return this._typeBuilder.atIndex(index); + } + + const t = this.typeAtIndex(index); + + return [t, defined(this._attributeStore).attributesForType(t)]; + } + + private filterTypes( + predicate: ((t: Type) => boolean) | undefined, + ): ReadonlySet { + const seen = new Set(); + const types: Type[] = []; + + function addFromType(t: Type): void { + if (seen.has(t)) { + return; + } + + seen.add(t); + + const required = predicate === undefined || predicate(t); + + if (required) { + types.push(t); + } + + for (const c of t.getChildren()) { + addFromType(c); + } + } + + for (const [, t] of this.topLevels) { + addFromType(t); + } + + return new Set(types); + } + + public allNamedTypes(): ReadonlySet { + return this.filterTypes(isNamedType); + } + + public allNamedTypesSeparated(): SeparatedNamedTypes { + const types = this.allNamedTypes(); + + return separateNamedTypes(types); + } + + private allProvenance(): ReadonlySet { + assert(this._haveProvenanceAttributes); + + const view = new TypeAttributeStoreView( + this.attributeStore, + provenanceTypeAttributeKind, + ); + const sets = Array.from(this.allTypesUnordered()).map((t) => { + const maybeSet = view.tryGet(t); + if (maybeSet !== undefined) return maybeSet; + return new Set(); + }); + const result = new Set(); + setUnionManyInto(result, sets); + + return result; + } + + public setPrintOnRewrite(): void { + this._printOnRewrite = true; + } + + private checkLostTypeAttributes( + builder: BaseGraphRewriteBuilder, + newGraph: TypeGraph, + ): void { + if (!this._haveProvenanceAttributes || builder.lostTypeAttributes) { + return; + } + + const oldProvenance = this.allProvenance(); + const newProvenance = newGraph.allProvenance(); + if (oldProvenance.size !== newProvenance.size) { + const difference = setSubtract(oldProvenance, newProvenance); + const indexes = Array.from(difference); + messageError("IRTypeAttributesNotPropagated", { + count: difference.size, + indexes, + }); + } + } + + private printRewrite(title: string): void { + if (!this._printOnRewrite) { + return; + } + + console.log(`\n# ${title}`); + } + + // Each array in `replacementGroups` is a bunch of types to be replaced by a + // single new type. `replacer` is a function that takes a group and a + // TypeBuilder, and builds a new type with that builder that replaces the group. + // That particular TypeBuilder will have to take as inputs types in the old + // graph, but return types in the new graph. Recursive types must be handled + // carefully. + public rewrite( + title: string, + stringTypeMapping: StringTypeMapping, + alphabetizeProperties: boolean, + replacementGroups: T[][], + debugPrintReconstitution: boolean, + replacer: ( + typesToReplace: ReadonlySet, + builder: GraphRewriteBuilder, + forwardingRef: TypeRef, + ) => TypeRef, + force = false, + ): TypeGraph { + this.printRewrite(title); + + if (!force && replacementGroups.length === 0) { + return this; + } + + const builder = new GraphRewriteBuilder( + this, + stringTypeMapping, + alphabetizeProperties, + this._haveProvenanceAttributes, + replacementGroups, + debugPrintReconstitution, + replacer, + ); + builder.typeGraph = new TypeGraph( + builder, + this.serial + 1, + this._haveProvenanceAttributes, + ); + const newGraph = builder.finish(); + + this.checkLostTypeAttributes(builder, newGraph); + + if (this._printOnRewrite) { + newGraph.setPrintOnRewrite(); + newGraph.printGraph(); + } + + if (!builder.didAddForwardingIntersection) { + return newGraph; + } + + return removeIndirectionIntersections( + newGraph, + stringTypeMapping, + debugPrintReconstitution, + ); + } + + public remap( + title: string, + stringTypeMapping: StringTypeMapping, + alphabetizeProperties: boolean, + map: ReadonlyMap, + debugPrintRemapping: boolean, + force = false, + ): TypeGraph { + this.printRewrite(title); + + if (!force && map.size === 0) { + return this; + } + + const builder = new GraphRemapBuilder( + this, + stringTypeMapping, + alphabetizeProperties, + this._haveProvenanceAttributes, + map, + debugPrintRemapping, + ); + builder.typeGraph = new TypeGraph( + builder, + this.serial + 1, + this._haveProvenanceAttributes, + ); + const newGraph = builder.finish(); + + this.checkLostTypeAttributes(builder, newGraph); + + if (this._printOnRewrite) { + newGraph.setPrintOnRewrite(); + newGraph.printGraph(); + } + + assert(!builder.didAddForwardingIntersection); + + return newGraph; + } + + public garbageCollect( + alphabetizeProperties: boolean, + debugPrintReconstitution: boolean, + ): TypeGraph { + const newGraph = this.remap( + "GC", + getNoStringTypeMapping(), + alphabetizeProperties, + new Map(), + debugPrintReconstitution, + true, + ); + + return newGraph; + } + + public rewriteFixedPoint( + alphabetizeProperties: boolean, + debugPrintReconstitution: boolean, + ): TypeGraph { + // eslint-disable-next-line @typescript-eslint/no-this-alias + let graph: TypeGraph = this; + for (;;) { + const newGraph = this.rewrite( + "fixed-point", + getNoStringTypeMapping(), + alphabetizeProperties, + [], + debugPrintReconstitution, + mustNotHappen, + true, + ); + if ( + graph.allTypesUnordered().size === + newGraph.allTypesUnordered().size + ) { + return graph; + } + + graph = newGraph; + } + } + + public allTypesUnordered(): ReadonlySet { + assert( + this.isFrozen, + "Tried to get all graph types before it was frozen", + ); + return new Set(defined(this._types)); + } + + public makeGraph( + invertDirection: boolean, + childrenOfType: (t: Type) => ReadonlySet, + ): Graph { + return new Graph(defined(this._types), invertDirection, childrenOfType); + } + + public getParentsOfType(t: Type): Set { + assertTypeRefGraph(t.typeRef, this); + if (this._parents === undefined) { + const parents = defined(this._types).map((_) => new Set()); + for (const p of this.allTypesUnordered()) { + for (const c of p.getChildren()) { + const index = c.index; + parents[index] = parents[index].add(p); + } + } + + this._parents = parents; + } + + return this._parents[t.index]; + } + + public printGraph(): void { + const types = defined(this._types); + for (let i = 0; i < types.length; i++) { + const t = types[i]; + const parts: string[] = []; + parts.push( + `${t.debugPrintKind}${t.hasNames ? ` ${t.getCombinedName()}` : ""}`, + ); + const children = t.getChildren(); + if (children.size > 0) { + parts.push( + `children ${Array.from(children) + .map((c) => c.index) + .join(",")}`, + ); + } + + for (const [kind, value] of t.getAttributes()) { + const maybeString = kind.stringify(value); + if (maybeString !== undefined) { + parts.push(maybeString); + } + } + + console.log(`${i}: ${parts.join(" | ")}`); + } + } +} diff --git a/packages/quicktype-core/src/Type/TypeGraphUtils.ts b/packages/quicktype-core/src/Type/TypeGraphUtils.ts new file mode 100644 index 000000000..cecc04fb9 --- /dev/null +++ b/packages/quicktype-core/src/Type/TypeGraphUtils.ts @@ -0,0 +1,165 @@ +import { + iterableFirst, + mapMap, + mapSome, + setFilter, + setMap, +} from "collection-utils"; + +import { TypeNames, namesTypeAttributeKind } from "../attributes/TypeNames"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import { assert, defined, panic } from "../support/Support"; + +import { ClassType, IntersectionType, type Type, UnionType } from "./Type"; +import type { StringTypeMapping } from "./TypeBuilderUtils"; +import type { TypeGraph } from "./TypeGraph"; +import type { TypeRef } from "./TypeRef"; +import { combineTypeAttributesOfTypes } from "./TypeUtils"; + +export function noneToAny( + graph: TypeGraph, + stringTypeMapping: StringTypeMapping, + debugPrintReconstitution: boolean, +): TypeGraph { + const noneTypes = setFilter( + graph.allTypesUnordered(), + (t) => t.kind === "none", + ); + if (noneTypes.size === 0) { + return graph; + } + + assert(noneTypes.size === 1, "Cannot have more than one none type"); + return graph.rewrite( + "none to any", + stringTypeMapping, + false, + [Array.from(noneTypes)], + debugPrintReconstitution, + (types, builder, forwardingRef) => { + const attributes = combineTypeAttributesOfTypes("union", types); + const tref = builder.getPrimitiveType( + "any", + attributes, + forwardingRef, + ); + return tref; + }, + ); +} + +export function optionalToNullable( + graph: TypeGraph, + stringTypeMapping: StringTypeMapping, + debugPrintReconstitution: boolean, +): TypeGraph { + function rewriteClass( + c: ClassType, + builder: GraphRewriteBuilder, + forwardingRef: TypeRef, + ): TypeRef { + const properties = mapMap(c.getProperties(), (p, name) => { + const t = p.type; + let ref: TypeRef; + if (!p.isOptional || t.isNullable) { + ref = builder.reconstituteType(t); + } else { + const nullType = builder.getPrimitiveType("null"); + let members: ReadonlySet; + if (t instanceof UnionType) { + members = setMap(t.members, (m) => + builder.reconstituteType(m), + ).add(nullType); + } else { + members = new Set([builder.reconstituteType(t), nullType]); + } + + const attributes = + namesTypeAttributeKind.setDefaultInAttributes( + t.getAttributes(), + () => TypeNames.make(new Set([name]), new Set(), true), + ); + ref = builder.getUnionType(attributes, members); + } + + return builder.makeClassProperty(ref, p.isOptional); + }); + if (c.isFixed) { + return builder.getUniqueClassType( + c.getAttributes(), + true, + properties, + forwardingRef, + ); + } else { + return builder.getClassType( + c.getAttributes(), + properties, + forwardingRef, + ); + } + } + + const classesWithOptional = setFilter( + graph.allTypesUnordered(), + (t) => + t instanceof ClassType && + mapSome(t.getProperties(), (p) => p.isOptional), + ); + const replacementGroups = Array.from(classesWithOptional).map((c) => [ + c as ClassType, + ]); + if (classesWithOptional.size === 0) { + return graph; + } + + return graph.rewrite( + "optional to nullable", + stringTypeMapping, + false, + replacementGroups, + debugPrintReconstitution, + (setOfClass, builder, forwardingRef) => { + assert(setOfClass.size === 1); + const c = defined(iterableFirst(setOfClass)); + return rewriteClass(c, builder, forwardingRef); + }, + ); +} + +export function removeIndirectionIntersections( + graph: TypeGraph, + stringTypeMapping: StringTypeMapping, + debugPrintRemapping: boolean, +): TypeGraph { + const map: Array<[Type, Type]> = []; + + for (const t of graph.allTypesUnordered()) { + if (!(t instanceof IntersectionType)) continue; + const seen = new Set([t]); + let current = t; + while (current.members.size === 1) { + const member = defined(iterableFirst(current.members)); + if (!(member instanceof IntersectionType)) { + map.push([t, member]); + break; + } + + if (seen.has(member)) { + // FIXME: Technically, this is an any type. + return panic("There's a cycle of intersection types"); + } + + seen.add(member); + current = member; + } + } + + return graph.remap( + "remove indirection intersections", + stringTypeMapping, + false, + new Map(map), + debugPrintRemapping, + ); +} diff --git a/packages/quicktype-core/src/Type/TypeRef.ts b/packages/quicktype-core/src/Type/TypeRef.ts new file mode 100644 index 000000000..c7afd16e7 --- /dev/null +++ b/packages/quicktype-core/src/Type/TypeRef.ts @@ -0,0 +1,71 @@ +import type { TypeAttributes } from "../attributes/TypeAttributes"; +import type { BaseGraphRewriteBuilder } from "../GraphRewriting"; +import { assert } from "../support/Support"; + +import type { Type } from "./Type"; +import type { TypeGraph } from "./TypeGraph"; + +const indexBits = 26; +const indexMask = (1 << indexBits) - 1; +const serialBits = 31 - indexBits; +const serialMask = (1 << serialBits) - 1; + +export type TypeRef = number; + +export function isTypeRef(x: unknown): x is TypeRef { + return typeof x === "number"; +} + +export function makeTypeRef(graph: TypeGraph, index: number): TypeRef { + assert(index <= indexMask, "Too many types in graph"); + return ((graph.serial & serialMask) << indexBits) | index; +} + +export function typeRefIndex(tref: TypeRef): number { + return tref & indexMask; +} + +export function assertTypeRefGraph(tref: TypeRef, graph: TypeGraph): void { + assert( + ((tref >> indexBits) & serialMask) === (graph.serial & serialMask), + "Mixing the wrong type reference and graph", + ); +} + +function getGraph( + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, +): TypeGraph { + if ("originalGraph" in graphOrBuilder) { + return graphOrBuilder.originalGraph; + } + + // do not use `graphOrBuilder instanceof TypeGraph` to check if is TypeGraph to prevent import cycle + return graphOrBuilder; +} + +export function derefTypeRef( + tref: TypeRef, + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, +): Type { + const graph = getGraph(graphOrBuilder); + assertTypeRefGraph(tref, graph); + return graph.typeAtIndex(typeRefIndex(tref)); +} + +export function attributesForTypeRef( + tref: TypeRef, + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, +): TypeAttributes { + const graph = getGraph(graphOrBuilder); + assertTypeRefGraph(tref, graph); + return graph.atIndex(typeRefIndex(tref))[1]; +} + +export function typeAndAttributesForTypeRef( + tref: TypeRef, + graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder, +): [Type, TypeAttributes] { + const graph = getGraph(graphOrBuilder); + assertTypeRefGraph(tref, graph); + return graph.atIndex(typeRefIndex(tref)); +} diff --git a/packages/quicktype-core/src/TypeUtils.ts b/packages/quicktype-core/src/Type/TypeUtils.ts similarity index 70% rename from packages/quicktype-core/src/TypeUtils.ts rename to packages/quicktype-core/src/Type/TypeUtils.ts index 4f3c57f29..499f7c05b 100644 --- a/packages/quicktype-core/src/TypeUtils.ts +++ b/packages/quicktype-core/src/Type/TypeUtils.ts @@ -1,31 +1,42 @@ -import { setFilter, setSortBy, iterableFirst, setUnion, EqualityMap } from "collection-utils"; +import { + EqualityMap, + iterableFirst, + setFilter, + setSortBy, + setUnion, +} from "collection-utils"; -import { defined, panic, assert, assertNever } from "./support/Support"; import { - TypeAttributes, + type StringTypes, + stringTypesTypeAttributeKind, +} from "../attributes/StringTypes"; +import { + type CombinationKind, + type TypeAttributes, combineTypeAttributes, emptyTypeAttributes, - CombinationKind -} from "./attributes/TypeAttributes"; +} from "../attributes/TypeAttributes"; +import { assert, assertNever, defined, panic } from "../support/Support"; + +import { isPrimitiveStringTypeKind } from "./TransformedStringType"; import { - Type, - PrimitiveType, ArrayType, + type ClassProperty, + ClassType, EnumType, - ObjectType, MapType, - ClassType, - ClassProperty, - SetOperationType, + ObjectType, + type PrimitiveType, + type SetOperationType, + type Type, UnionType, - isPrimitiveStringTypeKind } from "./Type"; -import { stringTypesTypeAttributeKind, StringTypes } from "./attributes/StringTypes"; export function assertIsObject(t: Type): ObjectType { if (t instanceof ObjectType) { return t; } + return panic("Supposed object type is not an object type"); } @@ -33,20 +44,17 @@ export function assertIsClass(t: Type): ClassType { if (!(t instanceof ClassType)) { return panic("Supposed class type is not a class type"); } + return t; } export function setOperationMembersRecursively( - setOperation: T, - combinationKind: CombinationKind | undefined -): [ReadonlySet, TypeAttributes]; -export function setOperationMembersRecursively( - setOperations: T[], - combinationKind: CombinationKind | undefined + setOperations: T | T[], + combinationKind: CombinationKind | undefined, ): [ReadonlySet, TypeAttributes]; export function setOperationMembersRecursively( oneOrMany: T | T[], - combinationKind: CombinationKind | undefined + combinationKind: CombinationKind | undefined, ): [ReadonlySet, TypeAttributes] { const setOperations = Array.isArray(oneOrMany) ? oneOrMany : [oneOrMany]; const kind = setOperations[0].kind; @@ -61,8 +69,13 @@ export function setOperationMembersRecursively( if (processedSetOperations.has(so)) return; processedSetOperations.add(so); if (combinationKind !== undefined) { - attributes = combineTypeAttributes(combinationKind, attributes, t.getAttributes()); + attributes = combineTypeAttributes( + combinationKind, + attributes, + t.getAttributes(), + ); } + for (const m of so.members) { process(m); } @@ -70,7 +83,11 @@ export function setOperationMembersRecursively( members.add(t); } else { if (combinationKind !== undefined) { - attributes = combineTypeAttributes(combinationKind, attributes, t.getAttributes()); + attributes = combineTypeAttributes( + combinationKind, + attributes, + t.getAttributes(), + ); } } } @@ -78,18 +95,21 @@ export function setOperationMembersRecursively( for (const so of setOperations) { process(so); } + return [members, attributes]; } export function makeGroupsToFlatten( setOperations: Iterable, - include: ((members: ReadonlySet) => boolean) | undefined + include: ((members: ReadonlySet) => boolean) | undefined, ): Type[][] { const typeGroups = new EqualityMap, Set>(); for (const u of setOperations) { // FIXME: We shouldn't have to make a new set here once we got rid // of immutable. - const members = new Set(setOperationMembersRecursively(u, undefined)[0]); + const members = new Set( + setOperationMembersRecursively(u, undefined)[0], + ); if (include !== undefined) { if (!include(members)) continue; @@ -102,17 +122,21 @@ export function makeGroupsToFlatten( maybeSet.add(defined(iterableFirst(members))); } } + maybeSet.add(u); typeGroups.set(members, maybeSet); } - return Array.from(typeGroups.values()).map(ts => Array.from(ts)); + return Array.from(typeGroups.values()).map((ts) => Array.from(ts)); } -export function combineTypeAttributesOfTypes(combinationKind: CombinationKind, types: Iterable): TypeAttributes { +export function combineTypeAttributesOfTypes( + combinationKind: CombinationKind, + types: Iterable, +): TypeAttributes { return combineTypeAttributes( combinationKind, - Array.from(types).map(t => t.getAttributes()) + Array.from(types).map((t) => t.getAttributes()), ); } @@ -125,11 +149,11 @@ export function isAnyOrNull(t: Type): boolean { // introduced. export function removeNullFromUnion( t: UnionType, - sortBy: boolean | ((t: Type) => any) = false + sortBy: boolean | ((t: Type) => string | number) = false, ): [PrimitiveType | null, ReadonlySet] { function sort(s: ReadonlySet): ReadonlySet { if (sortBy === false) return s; - if (sortBy === true) return setSortBy(s, m => m.kind); + if (sortBy === true) return setSortBy(s, (m) => m.kind); return setSortBy(s, sortBy); } @@ -137,16 +161,24 @@ export function removeNullFromUnion( if (nullType === undefined) { return [null, sort(t.members)]; } - return [nullType as PrimitiveType, sort(setFilter(t.members, m => m.kind !== "null"))]; + + return [ + nullType as PrimitiveType, + sort(setFilter(t.members, (m) => m.kind !== "null")), + ]; } -export function removeNullFromType(t: Type): [PrimitiveType | null, ReadonlySet] { +export function removeNullFromType( + t: Type, +): [PrimitiveType | null, ReadonlySet] { if (t.kind === "null") { return [t as PrimitiveType, new Set()]; } + if (!(t instanceof UnionType)) { return [null, new Set([t])]; } + return removeNullFromUnion(t); } @@ -161,71 +193,94 @@ export function nonNullTypeCases(t: Type): ReadonlySet { return removeNullFromType(t)[1]; } -export function getNullAsOptional(cp: ClassProperty): [boolean, ReadonlySet] { +export function getNullAsOptional( + cp: ClassProperty, +): [boolean, ReadonlySet] { const [maybeNull, nonNulls] = removeNullFromType(cp.type); if (cp.isOptional) { return [true, nonNulls]; } + return [maybeNull !== null, nonNulls]; } // FIXME: Give this an appropriate name, considering that we don't distinguish // between named and non-named types anymore. export function isNamedType(t: Type): boolean { - return ["class", "union", "enum", "object"].indexOf(t.kind) >= 0; + return ["class", "union", "enum", "object"].includes(t.kind); } -export type SeparatedNamedTypes = { - objects: ReadonlySet; +export interface SeparatedNamedTypes { enums: ReadonlySet; + objects: ReadonlySet; unions: ReadonlySet; -}; +} export function separateNamedTypes(types: Iterable): SeparatedNamedTypes { const objects = setFilter( types, - t => t.kind === "object" || t.kind === "class" + (t) => t.kind === "object" || t.kind === "class", ) as Set as ReadonlySet; - const enums = setFilter(types, t => t instanceof EnumType) as Set as ReadonlySet; - const unions = setFilter(types, t => t instanceof UnionType) as Set as ReadonlySet; + const enums = setFilter( + types, + (t) => t instanceof EnumType, + ) as Set as ReadonlySet; + const unions = setFilter( + types, + (t) => t instanceof UnionType, + ) as Set as ReadonlySet; return { objects, enums, unions }; } -export function directlyReachableTypes(t: Type, setForType: (t: Type) => ReadonlySet | null): ReadonlySet { +export function directlyReachableTypes( + t: Type, + setForType: (t: Type) => ReadonlySet | null, +): ReadonlySet { const set = setForType(t); if (set !== null) return set; - return setUnion(...Array.from(t.getNonAttributeChildren()).map(c => directlyReachableTypes(c, setForType))); + return setUnion( + ...Array.from(t.getNonAttributeChildren()).map((c) => + directlyReachableTypes(c, setForType), + ), + ); } export function directlyReachableSingleNamedType(type: Type): Type | undefined { - const definedTypes = directlyReachableTypes(type, t => { + const definedTypes = directlyReachableTypes(type, (t) => { if ( (!(t instanceof UnionType) && isNamedType(t)) || (t instanceof UnionType && nullableFromUnion(t) === null) ) { return new Set([t]); } + return null; }); - assert(definedTypes.size <= 1, "Cannot have more than one defined type per top-level"); + assert( + definedTypes.size <= 1, + "Cannot have more than one defined type per top-level", + ); return iterableFirst(definedTypes); } export function stringTypesForType(t: PrimitiveType): StringTypes { assert(t.kind === "string", "Only strings can have string types"); - const stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes(t.getAttributes()); + const stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes( + t.getAttributes(), + ); if (stringTypes === undefined) { return panic("All strings must have a string type attribute"); } + return stringTypes; } -export type StringTypeMatchers = { +export interface StringTypeMatchers { + dateTimeType?: (dateTimeType: PrimitiveType) => U; dateType?: (dateType: PrimitiveType) => U; timeType?: (timeType: PrimitiveType) => U; - dateTimeType?: (dateTimeType: PrimitiveType) => U; -}; +} export function matchTypeExhaustive( t: Type, @@ -242,15 +297,17 @@ export function matchTypeExhaustive( objectType: (objectType: ObjectType) => U, enumType: (enumType: EnumType) => U, unionType: (unionType: UnionType) => U, - transformedStringType: (transformedStringType: PrimitiveType) => U + transformedStringType: (transformedStringType: PrimitiveType) => U, ): U { if (t.isPrimitive()) { if (isPrimitiveStringTypeKind(t.kind)) { if (t.kind === "string") { return stringType(t); } + return transformedStringType(t); } + const kind = t.kind; const f = { none: noneType, @@ -258,16 +315,17 @@ export function matchTypeExhaustive( null: nullType, bool: boolType, integer: integerType, - double: doubleType + double: doubleType, }[kind]; if (f !== undefined) return f(t); return assertNever(f); - } else if (t instanceof ArrayType) return arrayType(t); - else if (t instanceof ClassType) return classType(t); - else if (t instanceof MapType) return mapType(t); - else if (t instanceof ObjectType) return objectType(t); - else if (t instanceof EnumType) return enumType(t); - else if (t instanceof UnionType) return unionType(t); + } + if (t instanceof ArrayType) return arrayType(t); + if (t instanceof ClassType) return classType(t); + if (t instanceof MapType) return mapType(t); + if (t instanceof ObjectType) return objectType(t); + if (t instanceof EnumType) return enumType(t); + if (t instanceof UnionType) return unionType(t); return panic(`Unknown type ${t.kind}`); } @@ -284,13 +342,12 @@ export function matchType( mapType: (mapType: MapType) => U, enumType: (enumType: EnumType) => U, unionType: (unionType: UnionType) => U, - transformedStringType?: (transformedStringType: PrimitiveType) => U + transformedStringType?: (transformedStringType: PrimitiveType) => U, ): U { - function typeNotSupported(t: Type) { + function typeNotSupported(t: Type): never { return panic(`Unsupported type ${t.kind} in non-exhaustive match`); } - /* tslint:disable:strict-boolean-expressions */ return matchTypeExhaustive( type, typeNotSupported, @@ -306,9 +363,8 @@ export function matchType( typeNotSupported, enumType, unionType, - transformedStringType || typeNotSupported + transformedStringType ?? typeNotSupported, ); - /* tslint:enable */ } export function matchCompoundType( @@ -317,13 +373,13 @@ export function matchCompoundType( classType: (classType: ClassType) => void, mapType: (mapType: MapType) => void, objectType: (objectType: ObjectType) => void, - unionType: (unionType: UnionType) => void + unionType: (unionType: UnionType) => void, ): void { function ignore(_: T): void { return; } - return matchTypeExhaustive( + matchTypeExhaustive( t, ignore, ignore, @@ -338,6 +394,6 @@ export function matchCompoundType( objectType, ignore, unionType, - ignore + ignore, ); } diff --git a/packages/quicktype-core/src/Type/index.ts b/packages/quicktype-core/src/Type/index.ts new file mode 100644 index 000000000..b9639f9fe --- /dev/null +++ b/packages/quicktype-core/src/Type/index.ts @@ -0,0 +1,7 @@ +export * from "./Type"; +export * from "./TypeBuilder"; +export * from "./TypeGraph"; +export * from "./TypeUtils"; + +// TODO: update this to type * post TS upgrade +export * from "./TransformedStringType"; diff --git a/packages/quicktype-core/src/TypeGraph.ts b/packages/quicktype-core/src/TypeGraph.ts deleted file mode 100644 index 09993039e..000000000 --- a/packages/quicktype-core/src/TypeGraph.ts +++ /dev/null @@ -1,561 +0,0 @@ -import { iterableFirst, setFilter, setUnionManyInto, setSubtract, mapMap, mapSome, setMap } from "collection-utils"; - -import { Type, ClassType, UnionType, IntersectionType } from "./Type"; -import { separateNamedTypes, SeparatedNamedTypes, isNamedType, combineTypeAttributesOfTypes } from "./TypeUtils"; -import { defined, assert, panic, mustNotHappen } from "./support/Support"; -import { TypeBuilder, StringTypeMapping, getNoStringTypeMapping, provenanceTypeAttributeKind } from "./TypeBuilder"; -import { GraphRewriteBuilder, GraphRemapBuilder, BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { TypeNames, namesTypeAttributeKind } from "./attributes/TypeNames"; -import { Graph } from "./Graph"; -import { TypeAttributeKind, TypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { messageError } from "./Messages"; - -export type TypeRef = number; - -const indexBits = 26; -const indexMask = (1 << indexBits) - 1; -const serialBits = 31 - indexBits; -const serialMask = (1 << serialBits) - 1; - -export function isTypeRef(x: any): x is TypeRef { - return typeof x === "number"; -} - -export function makeTypeRef(graph: TypeGraph, index: number): TypeRef { - assert(index <= indexMask, "Too many types in graph"); - return ((graph.serial & serialMask) << indexBits) | index; -} - -export function typeRefIndex(tref: TypeRef): number { - return tref & indexMask; -} - -export function assertTypeRefGraph(tref: TypeRef, graph: TypeGraph): void { - assert( - ((tref >> indexBits) & serialMask) === (graph.serial & serialMask), - "Mixing the wrong type reference and graph" - ); -} - -function getGraph(graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): TypeGraph { - if (graphOrBuilder instanceof TypeGraph) return graphOrBuilder; - return graphOrBuilder.originalGraph; -} - -export function derefTypeRef(tref: TypeRef, graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder): Type { - const graph = getGraph(graphOrBuilder); - assertTypeRefGraph(tref, graph); - return graph.typeAtIndex(typeRefIndex(tref)); -} - -export function attributesForTypeRef( - tref: TypeRef, - graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder -): TypeAttributes { - const graph = getGraph(graphOrBuilder); - assertTypeRefGraph(tref, graph); - return graph.atIndex(typeRefIndex(tref))[1]; -} - -export function typeAndAttributesForTypeRef( - tref: TypeRef, - graphOrBuilder: TypeGraph | BaseGraphRewriteBuilder -): [Type, TypeAttributes] { - const graph = getGraph(graphOrBuilder); - assertTypeRefGraph(tref, graph); - return graph.atIndex(typeRefIndex(tref)); -} - -export class TypeAttributeStore { - private readonly _topLevelValues: Map = new Map(); - - constructor(private readonly _typeGraph: TypeGraph, private _values: (TypeAttributes | undefined)[]) {} - - private getTypeIndex(t: Type): number { - const tref = t.typeRef; - assertTypeRefGraph(tref, this._typeGraph); - return typeRefIndex(tref); - } - - attributesForType(t: Type): TypeAttributes { - const index = this.getTypeIndex(t); - const maybeAttributes = this._values[index]; - if (maybeAttributes !== undefined) { - return maybeAttributes; - } - return emptyTypeAttributes; - } - - attributesForTopLevel(name: string): TypeAttributes { - const maybeAttributes = this._topLevelValues.get(name); - if (maybeAttributes !== undefined) { - return maybeAttributes; - } - return emptyTypeAttributes; - } - - private setInMap(attributes: TypeAttributes, kind: TypeAttributeKind, value: T): TypeAttributes { - // FIXME: This is potentially super slow - return new Map(attributes).set(kind, value); - } - - set(kind: TypeAttributeKind, t: Type, value: T): void { - const index = this.getTypeIndex(t); - while (index >= this._values.length) { - this._values.push(undefined); - } - this._values[index] = this.setInMap(this.attributesForType(t), kind, value); - } - - setForTopLevel(kind: TypeAttributeKind, topLevelName: string, value: T): void { - this._topLevelValues.set(topLevelName, this.setInMap(this.attributesForTopLevel(topLevelName), kind, value)); - } - - private tryGetInMap(attributes: TypeAttributes, kind: TypeAttributeKind): T | undefined { - return attributes.get(kind); - } - - tryGet(kind: TypeAttributeKind, t: Type): T | undefined { - return this.tryGetInMap(this.attributesForType(t), kind); - } - - tryGetForTopLevel(kind: TypeAttributeKind, topLevelName: string): T | undefined { - return this.tryGetInMap(this.attributesForTopLevel(topLevelName), kind); - } -} - -export class TypeAttributeStoreView { - constructor( - private readonly _attributeStore: TypeAttributeStore, - private readonly _definition: TypeAttributeKind - ) {} - - set(t: Type, value: T): void { - this._attributeStore.set(this._definition, t, value); - } - - setForTopLevel(name: string, value: T): void { - this._attributeStore.setForTopLevel(this._definition, name, value); - } - - tryGet(t: Type): T | undefined { - return this._attributeStore.tryGet(this._definition, t); - } - - get(t: Type): T { - return defined(this.tryGet(t)); - } - - tryGetForTopLevel(name: string): T | undefined { - return this._attributeStore.tryGetForTopLevel(this._definition, name); - } - - getForTopLevel(name: string): T { - return defined(this.tryGetForTopLevel(name)); - } -} - -export class TypeGraph { - private _typeBuilder?: TypeBuilder; - private _attributeStore: TypeAttributeStore | undefined = undefined; - - // FIXME: OrderedMap? We lose the order in PureScript right now, though, - // and maybe even earlier in the TypeScript driver. - private _topLevels: Map = new Map(); - - private _types?: Type[]; - - private _parents: Set[] | undefined = undefined; - - private _printOnRewrite = false; - - constructor( - typeBuilder: TypeBuilder, - readonly serial: number, - private readonly _haveProvenanceAttributes: boolean - ) { - this._typeBuilder = typeBuilder; - } - - private get isFrozen(): boolean { - return this._typeBuilder === undefined; - } - - get attributeStore(): TypeAttributeStore { - return defined(this._attributeStore); - } - - freeze( - topLevels: ReadonlyMap, - types: Type[], - typeAttributes: (TypeAttributes | undefined)[] - ): void { - assert(!this.isFrozen, "Tried to freeze TypeGraph a second time"); - for (const t of types) { - assertTypeRefGraph(t.typeRef, this); - } - - this._attributeStore = new TypeAttributeStore(this, typeAttributes); - - // The order of these three statements matters. If we set _typeBuilder - // to undefined before we deref the TypeRefs, then we need to set _types - // before, also, because the deref will call into typeAtIndex, which requires - // either a _typeBuilder or a _types. - this._types = types; - this._typeBuilder = undefined; - this._topLevels = mapMap(topLevels, tref => derefTypeRef(tref, this)); - } - - get topLevels(): ReadonlyMap { - assert(this.isFrozen, "Cannot get top-levels from a non-frozen graph"); - return this._topLevels; - } - - typeAtIndex(index: number): Type { - if (this._typeBuilder !== undefined) { - return this._typeBuilder.typeAtIndex(index); - } - return defined(this._types)[index]; - } - - atIndex(index: number): [Type, TypeAttributes] { - if (this._typeBuilder !== undefined) { - return this._typeBuilder.atIndex(index); - } - const t = this.typeAtIndex(index); - return [t, defined(this._attributeStore).attributesForType(t)]; - } - - private filterTypes(predicate: ((t: Type) => boolean) | undefined): ReadonlySet { - const seen = new Set(); - let types: Type[] = []; - - function addFromType(t: Type): void { - if (seen.has(t)) return; - seen.add(t); - - const required = predicate === undefined || predicate(t); - - if (required) { - types.push(t); - } - - for (const c of t.getChildren()) { - addFromType(c); - } - } - - for (const [, t] of this.topLevels) { - addFromType(t); - } - return new Set(types); - } - - allNamedTypes(): ReadonlySet { - return this.filterTypes(isNamedType); - } - - allNamedTypesSeparated(): SeparatedNamedTypes { - const types = this.allNamedTypes(); - return separateNamedTypes(types); - } - - private allProvenance(): ReadonlySet { - assert(this._haveProvenanceAttributes); - - const view = new TypeAttributeStoreView(this.attributeStore, provenanceTypeAttributeKind); - const sets = Array.from(this.allTypesUnordered()).map(t => { - const maybeSet = view.tryGet(t); - if (maybeSet !== undefined) return maybeSet; - return new Set(); - }); - const result = new Set(); - setUnionManyInto(result, sets); - return result; - } - - setPrintOnRewrite(): void { - this._printOnRewrite = true; - } - - private checkLostTypeAttributes(builder: BaseGraphRewriteBuilder, newGraph: TypeGraph): void { - if (!this._haveProvenanceAttributes || builder.lostTypeAttributes) return; - - const oldProvenance = this.allProvenance(); - const newProvenance = newGraph.allProvenance(); - if (oldProvenance.size !== newProvenance.size) { - const difference = setSubtract(oldProvenance, newProvenance); - const indexes = Array.from(difference); - return messageError("IRTypeAttributesNotPropagated", { count: difference.size, indexes }); - } - } - - private printRewrite(title: string): void { - if (!this._printOnRewrite) return; - - console.log(`\n# ${title}`); - } - - // Each array in `replacementGroups` is a bunch of types to be replaced by a - // single new type. `replacer` is a function that takes a group and a - // TypeBuilder, and builds a new type with that builder that replaces the group. - // That particular TypeBuilder will have to take as inputs types in the old - // graph, but return types in the new graph. Recursive types must be handled - // carefully. - rewrite( - title: string, - stringTypeMapping: StringTypeMapping, - alphabetizeProperties: boolean, - replacementGroups: T[][], - debugPrintReconstitution: boolean, - replacer: (typesToReplace: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef) => TypeRef, - force = false - ): TypeGraph { - this.printRewrite(title); - - if (!force && replacementGroups.length === 0) return this; - - const builder = new GraphRewriteBuilder( - this, - stringTypeMapping, - alphabetizeProperties, - this._haveProvenanceAttributes, - replacementGroups, - debugPrintReconstitution, - replacer - ); - const newGraph = builder.finish(); - - this.checkLostTypeAttributes(builder, newGraph); - - if (this._printOnRewrite) { - newGraph.setPrintOnRewrite(); - newGraph.printGraph(); - } - - if (!builder.didAddForwardingIntersection) return newGraph; - - return removeIndirectionIntersections(newGraph, stringTypeMapping, debugPrintReconstitution); - } - - remap( - title: string, - stringTypeMapping: StringTypeMapping, - alphabetizeProperties: boolean, - map: ReadonlyMap, - debugPrintRemapping: boolean, - force = false - ): TypeGraph { - this.printRewrite(title); - - if (!force && map.size === 0) return this; - - const builder = new GraphRemapBuilder( - this, - stringTypeMapping, - alphabetizeProperties, - this._haveProvenanceAttributes, - map, - debugPrintRemapping - ); - const newGraph = builder.finish(); - - this.checkLostTypeAttributes(builder, newGraph); - - if (this._printOnRewrite) { - newGraph.setPrintOnRewrite(); - newGraph.printGraph(); - } - - assert(!builder.didAddForwardingIntersection); - - return newGraph; - } - - garbageCollect(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { - const newGraph = this.remap( - "GC", - getNoStringTypeMapping(), - alphabetizeProperties, - new Map(), - debugPrintReconstitution, - true - ); - return newGraph; - } - - rewriteFixedPoint(alphabetizeProperties: boolean, debugPrintReconstitution: boolean): TypeGraph { - let graph: TypeGraph = this; - for (;;) { - const newGraph = this.rewrite( - "fixed-point", - getNoStringTypeMapping(), - alphabetizeProperties, - [], - debugPrintReconstitution, - mustNotHappen, - true - ); - if (graph.allTypesUnordered().size === newGraph.allTypesUnordered().size) { - return graph; - } - graph = newGraph; - } - } - - allTypesUnordered(): ReadonlySet { - assert(this.isFrozen, "Tried to get all graph types before it was frozen"); - return new Set(defined(this._types)); - } - - makeGraph(invertDirection: boolean, childrenOfType: (t: Type) => ReadonlySet): Graph { - return new Graph(defined(this._types), invertDirection, childrenOfType); - } - - getParentsOfType(t: Type): Set { - assertTypeRefGraph(t.typeRef, this); - if (this._parents === undefined) { - const parents = defined(this._types).map(_ => new Set()); - for (const p of this.allTypesUnordered()) { - for (const c of p.getChildren()) { - const index = c.index; - parents[index] = parents[index].add(p); - } - } - this._parents = parents; - } - return this._parents[t.index]; - } - - printGraph(): void { - const types = defined(this._types); - for (let i = 0; i < types.length; i++) { - const t = types[i]; - const parts: string[] = []; - parts.push(`${t.debugPrintKind}${t.hasNames ? ` ${t.getCombinedName()}` : ""}`); - const children = t.getChildren(); - if (children.size > 0) { - parts.push( - `children ${Array.from(children) - .map(c => c.index) - .join(",")}` - ); - } - for (const [kind, value] of t.getAttributes()) { - const maybeString = kind.stringify(value); - if (maybeString !== undefined) { - parts.push(maybeString); - } - } - console.log(`${i}: ${parts.join(" | ")}`); - } - } -} - -export function noneToAny( - graph: TypeGraph, - stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean -): TypeGraph { - const noneTypes = setFilter(graph.allTypesUnordered(), t => t.kind === "none"); - if (noneTypes.size === 0) { - return graph; - } - assert(noneTypes.size === 1, "Cannot have more than one none type"); - return graph.rewrite( - "none to any", - stringTypeMapping, - false, - [Array.from(noneTypes)], - debugPrintReconstitution, - (types, builder, forwardingRef) => { - const attributes = combineTypeAttributesOfTypes("union", types); - const tref = builder.getPrimitiveType("any", attributes, forwardingRef); - return tref; - } - ); -} - -export function optionalToNullable( - graph: TypeGraph, - stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean -): TypeGraph { - function rewriteClass(c: ClassType, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { - const properties = mapMap(c.getProperties(), (p, name) => { - const t = p.type; - let ref: TypeRef; - if (!p.isOptional || t.isNullable) { - ref = builder.reconstituteType(t); - } else { - const nullType = builder.getPrimitiveType("null"); - let members: ReadonlySet; - if (t instanceof UnionType) { - members = setMap(t.members, m => builder.reconstituteType(m)).add(nullType); - } else { - members = new Set([builder.reconstituteType(t), nullType]); - } - const attributes = namesTypeAttributeKind.setDefaultInAttributes(t.getAttributes(), () => - TypeNames.make(new Set([name]), new Set(), true) - ); - ref = builder.getUnionType(attributes, members); - } - return builder.makeClassProperty(ref, p.isOptional); - }); - if (c.isFixed) { - return builder.getUniqueClassType(c.getAttributes(), true, properties, forwardingRef); - } else { - return builder.getClassType(c.getAttributes(), properties, forwardingRef); - } - } - - const classesWithOptional = setFilter( - graph.allTypesUnordered(), - t => t instanceof ClassType && mapSome(t.getProperties(), p => p.isOptional) - ); - const replacementGroups = Array.from(classesWithOptional).map(c => [c as ClassType]); - if (classesWithOptional.size === 0) { - return graph; - } - return graph.rewrite( - "optional to nullable", - stringTypeMapping, - false, - replacementGroups, - debugPrintReconstitution, - (setOfClass, builder, forwardingRef) => { - assert(setOfClass.size === 1); - const c = defined(iterableFirst(setOfClass)); - return rewriteClass(c, builder, forwardingRef); - } - ); -} - -export function removeIndirectionIntersections( - graph: TypeGraph, - stringTypeMapping: StringTypeMapping, - debugPrintRemapping: boolean -): TypeGraph { - const map: [Type, Type][] = []; - - for (const t of graph.allTypesUnordered()) { - if (!(t instanceof IntersectionType)) continue; - const seen = new Set([t]); - let current = t; - while (current.members.size === 1) { - const member = defined(iterableFirst(current.members)); - if (!(member instanceof IntersectionType)) { - map.push([t, member]); - break; - } - if (seen.has(member)) { - // FIXME: Technically, this is an any type. - return panic("There's a cycle of intersection types"); - } - seen.add(member); - current = member; - } - } - - return graph.remap("remove indirection intersections", stringTypeMapping, false, new Map(map), debugPrintRemapping); -} diff --git a/packages/quicktype-core/src/UnifyClasses.ts b/packages/quicktype-core/src/UnifyClasses.ts index cb445ae82..5c1e0094e 100644 --- a/packages/quicktype-core/src/UnifyClasses.ts +++ b/packages/quicktype-core/src/UnifyClasses.ts @@ -1,38 +1,56 @@ import { iterableFirst, setUnionInto } from "collection-utils"; -import { Type, ClassProperty, UnionType, ObjectType } from "./Type"; -import { assertIsObject } from "./TypeUtils"; -import { TypeBuilder } from "./TypeBuilder"; -import { TypeLookerUp, GraphRewriteBuilder, BaseGraphRewriteBuilder } from "./GraphRewriting"; -import { UnionBuilder, TypeRefUnionAccumulator } from "./UnionBuilder"; -import { panic, assert, defined } from "./support/Support"; -import { TypeAttributes, combineTypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -import { TypeRef, derefTypeRef } from "./TypeGraph"; +import { + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, +} from "./attributes/TypeAttributes"; +import type { + BaseGraphRewriteBuilder, + GraphRewriteBuilder, + TypeLookerUp, +} from "./GraphRewriting"; +import { assert, defined, panic } from "./support/Support"; +import { + type ClassProperty, + type ObjectType, + type Type, + UnionType, +} from "./Type/Type"; +import type { TypeBuilder } from "./Type/TypeBuilder"; +import { type TypeRef, derefTypeRef } from "./Type/TypeRef"; +import { assertIsObject } from "./Type/TypeUtils"; +import { TypeRefUnionAccumulator, UnionBuilder } from "./UnionBuilder"; function getCliqueProperties( clique: ObjectType[], builder: TypeBuilder, - makePropertyType: (types: ReadonlySet) => TypeRef + makePropertyType: (types: ReadonlySet) => TypeRef, ): [ReadonlyMap, TypeRef | undefined, boolean] { - let lostTypeAttributes = false; - let propertyNames = new Set(); + const lostTypeAttributes = false; + const propertyNames = new Set(); for (const o of clique) { setUnionInto(propertyNames, o.getProperties().keys()); } - let properties = Array.from(propertyNames).map(name => [name, new Set(), false] as [string, Set, boolean]); + const properties = Array.from(propertyNames).map( + (name) => [name, new Set(), false] as [string, Set, boolean], + ); let additionalProperties: Set | undefined = undefined; for (const o of clique) { - let additional = o.getAdditionalProperties(); + const additional = o.getAdditionalProperties(); if (additional !== undefined) { if (additionalProperties === undefined) { additionalProperties = new Set(); } + if (additional !== undefined) { additionalProperties.add(additional); } } + // FIXME: refactor this + // eslint-disable-next-line @typescript-eslint/prefer-for-of for (let i = 0; i < properties.length; i++) { let [name, types, isOptional] = properties[i]; const maybeProperty = o.getProperties().get(name); @@ -45,6 +63,7 @@ function getCliqueProperties( if (maybeProperty.isOptional) { isOptional = true; } + types.add(maybeProperty.type); } @@ -53,20 +72,27 @@ function getCliqueProperties( } const unifiedAdditionalProperties = - additionalProperties === undefined ? undefined : makePropertyType(additionalProperties); + additionalProperties === undefined + ? undefined + : makePropertyType(additionalProperties); - const unifiedPropertiesArray = properties.map(([name, types, isOptional]) => { - return [name, builder.makeClassProperty(makePropertyType(types), isOptional)] as [string, ClassProperty]; - }); + const unifiedPropertiesArray = properties.map( + ([name, types, isOptional]) => { + return [ + name, + builder.makeClassProperty(makePropertyType(types), isOptional), + ] as [string, ClassProperty]; + }, + ); const unifiedProperties = new Map(unifiedPropertiesArray); return [unifiedProperties, unifiedAdditionalProperties, lostTypeAttributes]; } function countProperties(clique: ObjectType[]): { - hasProperties: boolean; hasAdditionalProperties: boolean; hasNonAnyAdditionalProperties: boolean; + hasProperties: boolean; } { let hasProperties = false; let hasAdditionalProperties = false; @@ -75,6 +101,7 @@ function countProperties(clique: ObjectType[]): { if (o.getProperties().size > 0) { hasProperties = true; } + const additional = o.getAdditionalProperties(); if (additional !== undefined) { hasAdditionalProperties = true; @@ -83,15 +110,24 @@ function countProperties(clique: ObjectType[]): { } } } - return { hasProperties, hasAdditionalProperties, hasNonAnyAdditionalProperties }; + + return { + hasProperties, + hasAdditionalProperties, + hasNonAnyAdditionalProperties, + }; } -export class UnifyUnionBuilder extends UnionBuilder { - constructor( +export class UnifyUnionBuilder extends UnionBuilder< + BaseGraphRewriteBuilder, + TypeRef[], + TypeRef[] +> { + public constructor( typeBuilder: BaseGraphRewriteBuilder, private readonly _makeObjectTypes: boolean, private readonly _makeClassesFixed: boolean, - private readonly _unifyTypes: (typesToUnify: TypeRef[]) => TypeRef + private readonly _unifyTypes: (typesToUnify: TypeRef[]) => TypeRef, ) { super(typeBuilder); } @@ -99,66 +135,92 @@ export class UnifyUnionBuilder extends UnionBuilder assertIsObject(derefTypeRef(r, this.typeBuilder))); - const { hasProperties, hasAdditionalProperties, hasNonAnyAdditionalProperties } = countProperties(objectTypes); + const objectTypes = objectRefs.map((r) => + assertIsObject(derefTypeRef(r, this.typeBuilder)), + ); + const { + hasProperties, + hasAdditionalProperties, + hasNonAnyAdditionalProperties, + } = countProperties(objectTypes); - if (!this._makeObjectTypes && (hasNonAnyAdditionalProperties || (!hasProperties && hasAdditionalProperties))) { + if ( + !this._makeObjectTypes && + (hasNonAnyAdditionalProperties || + (!hasProperties && hasAdditionalProperties)) + ) { const propertyTypes = new Set(); for (const o of objectTypes) { setUnionInto( propertyTypes, - Array.from(o.getProperties().values()).map(cp => cp.typeRef) + Array.from(o.getProperties().values()).map( + (cp) => cp.typeRef, + ), ); } + const additionalPropertyTypes = new Set( objectTypes - .filter(o => o.getAdditionalProperties() !== undefined) - .map(o => defined(o.getAdditionalProperties()).typeRef) + .filter((o) => o.getAdditionalProperties() !== undefined) + .map((o) => defined(o.getAdditionalProperties()).typeRef), ); setUnionInto(propertyTypes, additionalPropertyTypes); - return this.typeBuilder.getMapType(typeAttributes, this._unifyTypes(Array.from(propertyTypes))); + return this.typeBuilder.getMapType( + typeAttributes, + this._unifyTypes(Array.from(propertyTypes)), + ); } else { - const [properties, additionalProperties, lostTypeAttributes] = getCliqueProperties( - objectTypes, - this.typeBuilder, - types => { + const [properties, additionalProperties, lostTypeAttributes] = + getCliqueProperties(objectTypes, this.typeBuilder, (types) => { assert(types.size > 0, "Property has no type"); - return this._unifyTypes(Array.from(types).map(t => t.typeRef)); - } - ); + return this._unifyTypes( + Array.from(types).map((t) => t.typeRef), + ); + }); if (lostTypeAttributes) { this.typeBuilder.setLostTypeAttributes(); } + if (this._makeObjectTypes) { return this.typeBuilder.getUniqueObjectType( typeAttributes, properties, additionalProperties, - forwardingRef + forwardingRef, ); } else { - assert(additionalProperties === undefined, "We have additional properties but want to make a class"); + assert( + additionalProperties === undefined, + "We have additional properties but want to make a class", + ); return this.typeBuilder.getUniqueClassType( typeAttributes, this._makeClassesFixed, properties, - forwardingRef + forwardingRef, ); } } @@ -167,9 +229,13 @@ export class UnifyUnionBuilder extends UnionBuilder( typeBuilder: GraphRewriteBuilder, makeObjectTypes: boolean, makeClassesFixed: boolean, - conflateNumbers: boolean + conflateNumbers: boolean, ): UnionBuilder { - return new UnifyUnionBuilder(typeBuilder, makeObjectTypes, makeClassesFixed, trefs => - unifyTypes( - new Set(trefs.map(tref => derefTypeRef(tref, typeBuilder))), - emptyTypeAttributes, - typeBuilder, - unionBuilderForUnification(typeBuilder, makeObjectTypes, makeClassesFixed, conflateNumbers), - conflateNumbers - ) + return new UnifyUnionBuilder( + typeBuilder, + makeObjectTypes, + makeClassesFixed, + (trefs) => + unifyTypes( + new Set(trefs.map((tref) => derefTypeRef(tref, typeBuilder))), + emptyTypeAttributes, + typeBuilder, + unionBuilderForUnification( + typeBuilder, + makeObjectTypes, + makeClassesFixed, + conflateNumbers, + ), + conflateNumbers, + ), ); } @@ -197,9 +272,13 @@ export function unifyTypes( types: ReadonlySet, typeAttributes: TypeAttributes, typeBuilder: GraphRewriteBuilder, - unionBuilder: UnionBuilder, + unionBuilder: UnionBuilder< + TypeBuilder & TypeLookerUp, + TypeRef[], + TypeRef[] + >, conflateNumbers: boolean, - maybeForwardingRef?: TypeRef + maybeForwardingRef?: TypeRef, ): TypeRef { typeAttributes = typeBuilder.reconstituteTypeAttributes(typeAttributes); if (types.size === 0) { @@ -207,23 +286,44 @@ export function unifyTypes( } else if (types.size === 1) { const first = defined(iterableFirst(types)); if (!(first instanceof UnionType)) { - return typeBuilder.reconstituteTypeRef(first.typeRef, typeAttributes, maybeForwardingRef); + return typeBuilder.reconstituteTypeRef( + first.typeRef, + typeAttributes, + maybeForwardingRef, + ); } } - const typeRefs = Array.from(types).map(t => t.typeRef); - const maybeTypeRef = typeBuilder.lookupTypeRefs(typeRefs, maybeForwardingRef); + const typeRefs = Array.from(types).map((t) => t.typeRef); + const maybeTypeRef = typeBuilder.lookupTypeRefs( + typeRefs, + maybeForwardingRef, + ); if (maybeTypeRef !== undefined) { typeBuilder.addAttributes(maybeTypeRef, typeAttributes); return maybeTypeRef; } const accumulator = new TypeRefUnionAccumulator(conflateNumbers); - const nestedAttributes = typeBuilder.reconstituteTypeAttributes(accumulator.addTypes(types)); - typeAttributes = combineTypeAttributes("union", typeAttributes, nestedAttributes); + const nestedAttributes = typeBuilder.reconstituteTypeAttributes( + accumulator.addTypes(types), + ); + typeAttributes = combineTypeAttributes( + "union", + typeAttributes, + nestedAttributes, + ); - return typeBuilder.withForwardingRef(maybeForwardingRef, forwardingRef => { - typeBuilder.registerUnion(typeRefs, forwardingRef); - return unionBuilder.buildUnion(accumulator, false, typeAttributes, forwardingRef); - }); + return typeBuilder.withForwardingRef( + maybeForwardingRef, + (forwardingRef) => { + typeBuilder.registerUnion(typeRefs, forwardingRef); + return unionBuilder.buildUnion( + accumulator, + false, + typeAttributes, + forwardingRef, + ); + }, + ); } diff --git a/packages/quicktype-core/src/UnionBuilder.ts b/packages/quicktype-core/src/UnionBuilder.ts index c4a21d9d8..d5ed2b033 100644 --- a/packages/quicktype-core/src/UnionBuilder.ts +++ b/packages/quicktype-core/src/UnionBuilder.ts @@ -1,18 +1,33 @@ -import { mapMerge, mapUpdateInto, mapMap, setUnionInto } from "collection-utils"; +import { + mapMap, + mapMerge, + mapUpdateInto, + setUnionInto, +} from "collection-utils"; -import { TypeKind, PrimitiveStringTypeKind, Type, UnionType, PrimitiveTypeKind, isPrimitiveTypeKind } from "./Type"; -import { matchTypeExhaustive } from "./TypeUtils"; import { - TypeAttributes, + StringTypes, + stringTypesTypeAttributeKind, +} from "./attributes/StringTypes"; +import { + type TypeAttributes, combineTypeAttributes, emptyTypeAttributes, + increaseTypeAttributesDistance, makeTypeAttributesInferred, - increaseTypeAttributesDistance } from "./attributes/TypeAttributes"; -import { defined, assert, panic, assertNever } from "./support/Support"; -import { TypeBuilder } from "./TypeBuilder"; -import { StringTypes, stringTypesTypeAttributeKind } from "./attributes/StringTypes"; -import { TypeRef } from "./TypeGraph"; +import { assert, assertNever, defined, panic } from "./support/Support"; +import { + type PrimitiveStringTypeKind, + type PrimitiveTypeKind, + type Type, + type TypeKind, + UnionType, + isPrimitiveTypeKind, +} from "./Type"; +import type { TypeBuilder } from "./Type/TypeBuilder"; +import type { TypeRef } from "./Type/TypeRef"; +import { matchTypeExhaustive } from "./Type/TypeUtils"; // FIXME: This interface is badly designed. All the properties // should use immutable types, and getMemberKinds should be @@ -22,13 +37,13 @@ import { TypeRef } from "./TypeGraph"; // Well, maybe getMemberKinds() is fine as it is. export interface UnionTypeProvider { readonly arrayData: TArrayData; - readonly objectData: TObjectData; - readonly enumCases: ReadonlySet; - getMemberKinds(): TypeAttributeMap; + getMemberKinds: () => TypeAttributeMap; readonly lostTypeAttributes: boolean; + + readonly objectData: TObjectData; } export type TypeAttributeMap = Map; @@ -37,7 +52,7 @@ type TypeAttributeMapBuilder = Map; function addAttributes( accumulatorAttributes: TypeAttributes | undefined, - newAttributes: TypeAttributes + newAttributes: TypeAttributes, ): TypeAttributes { if (accumulatorAttributes === undefined) return newAttributes; return combineTypeAttributes("union", accumulatorAttributes, newAttributes); @@ -46,181 +61,274 @@ function addAttributes( function setAttributes( attributeMap: TypeAttributeMap, kind: T, - newAttributes: TypeAttributes + newAttributes: TypeAttributes, ): void { - attributeMap.set(kind, addAttributes(attributeMap.get(kind), newAttributes)); + attributeMap.set( + kind, + addAttributes(attributeMap.get(kind), newAttributes), + ); } function addAttributesToBuilder( builder: TypeAttributeMapBuilder, kind: T, - newAttributes: TypeAttributes + newAttributes: TypeAttributes, ): void { let arr = builder.get(kind); if (arr === undefined) { arr = []; builder.set(kind, arr); } + arr.push(newAttributes); } -function buildTypeAttributeMap(builder: TypeAttributeMapBuilder): TypeAttributeMap { - return mapMap(builder, arr => combineTypeAttributes("union", arr)); +function buildTypeAttributeMap( + builder: TypeAttributeMapBuilder, +): TypeAttributeMap { + return mapMap(builder, (arr) => combineTypeAttributes("union", arr)); } -function moveAttributes(map: TypeAttributeMap, fromKind: T, toKind: T): void { +function moveAttributes( + map: TypeAttributeMap, + fromKind: T, + toKind: T, +): void { const fromAttributes = defined(map.get(fromKind)); map.delete(fromKind); setAttributes(map, toKind, fromAttributes); } -export class UnionAccumulator implements UnionTypeProvider { - private readonly _nonStringTypeAttributes: TypeAttributeMapBuilder = new Map(); - private readonly _stringTypeAttributes: TypeAttributeMapBuilder = new Map(); +export class UnionAccumulator + implements UnionTypeProvider +{ + private readonly _nonStringTypeAttributes: TypeAttributeMapBuilder = + new Map(); + + private readonly _stringTypeAttributes: TypeAttributeMapBuilder = + new Map(); - readonly arrayData: TArray[] = []; - readonly objectData: TObject[] = []; + public readonly arrayData: TArray[] = []; + + public readonly objectData: TObject[] = []; private readonly _enumCases: Set = new Set(); private _lostTypeAttributes = false; - constructor(private readonly _conflateNumbers: boolean) {} + public constructor(private readonly _conflateNumbers: boolean) {} private have(kind: TypeKind): boolean { return ( - this._nonStringTypeAttributes.has(kind) || this._stringTypeAttributes.has(kind as PrimitiveStringTypeKind) + this._nonStringTypeAttributes.has(kind) || + this._stringTypeAttributes.has(kind as PrimitiveStringTypeKind) ); } - addNone(_attributes: TypeAttributes): void { + public addNone(_attributes: TypeAttributes): void { // FIXME: Add them to all members? Or add them to the union, which means we'd have // to change getMemberKinds() to also return the attributes for the union itself, // or add a new method that does that. this._lostTypeAttributes = true; } - addAny(attributes: TypeAttributes): void { - addAttributesToBuilder(this._nonStringTypeAttributes, "any", attributes); + + public addAny(attributes: TypeAttributes): void { + addAttributesToBuilder( + this._nonStringTypeAttributes, + "any", + attributes, + ); this._lostTypeAttributes = true; } - addPrimitive(kind: PrimitiveTypeKind, attributes: TypeAttributes): void { + + public addPrimitive( + kind: PrimitiveTypeKind, + attributes: TypeAttributes, + ): void { assert(kind !== "any", "any must be added with addAny"); addAttributesToBuilder(this._nonStringTypeAttributes, kind, attributes); } - protected addFullStringType(attributes: TypeAttributes, stringTypes: StringTypes | undefined): void { + protected addFullStringType( + attributes: TypeAttributes, + stringTypes: StringTypes | undefined, + ): void { let stringTypesAttributes: TypeAttributes | undefined = undefined; if (stringTypes === undefined) { - stringTypes = stringTypesTypeAttributeKind.tryGetInAttributes(attributes); + stringTypes = + stringTypesTypeAttributeKind.tryGetInAttributes(attributes); } else { - stringTypesAttributes = stringTypesTypeAttributeKind.makeAttributes(stringTypes); + stringTypesAttributes = + stringTypesTypeAttributeKind.makeAttributes(stringTypes); } + if (stringTypes === undefined) { stringTypes = StringTypes.unrestricted; - stringTypesAttributes = stringTypesTypeAttributeKind.makeAttributes(stringTypes); + stringTypesAttributes = + stringTypesTypeAttributeKind.makeAttributes(stringTypes); } const maybeEnumAttributes = this._nonStringTypeAttributes.get("enum"); if (stringTypes.isRestricted) { assert( maybeEnumAttributes === undefined, - "We can't add both an enum as well as a restricted string type to a union builder" + "We can't add both an enum as well as a restricted string type to a union builder", ); } - addAttributesToBuilder(this._stringTypeAttributes, "string", attributes); + addAttributesToBuilder( + this._stringTypeAttributes, + "string", + attributes, + ); if (stringTypesAttributes !== undefined) { - addAttributesToBuilder(this._stringTypeAttributes, "string", stringTypesAttributes); + addAttributesToBuilder( + this._stringTypeAttributes, + "string", + stringTypesAttributes, + ); } } - addStringType(kind: PrimitiveStringTypeKind, attributes: TypeAttributes, stringTypes?: StringTypes): void { + public addStringType( + kind: PrimitiveStringTypeKind, + attributes: TypeAttributes, + stringTypes?: StringTypes, + ): void { if (kind === "string") { this.addFullStringType(attributes, stringTypes); return; } + addAttributesToBuilder(this._stringTypeAttributes, kind, attributes); if (stringTypes !== undefined) { addAttributesToBuilder( this._stringTypeAttributes, kind, - stringTypesTypeAttributeKind.makeAttributes(stringTypes) + stringTypesTypeAttributeKind.makeAttributes(stringTypes), ); } } - addArray(t: TArray, attributes: TypeAttributes): void { + public addArray(t: TArray, attributes: TypeAttributes): void { this.arrayData.push(t); - addAttributesToBuilder(this._nonStringTypeAttributes, "array", attributes); + addAttributesToBuilder( + this._nonStringTypeAttributes, + "array", + attributes, + ); } - addObject(t: TObject, attributes: TypeAttributes): void { + + public addObject(t: TObject, attributes: TypeAttributes): void { this.objectData.push(t); - addAttributesToBuilder(this._nonStringTypeAttributes, "object", attributes); + addAttributesToBuilder( + this._nonStringTypeAttributes, + "object", + attributes, + ); } - addEnum(cases: ReadonlySet, attributes: TypeAttributes): void { + public addEnum( + cases: ReadonlySet, + attributes: TypeAttributes, + ): void { const maybeStringAttributes = this._stringTypeAttributes.get("string"); if (maybeStringAttributes !== undefined) { - addAttributesToBuilder(this._stringTypeAttributes, "string", attributes); + addAttributesToBuilder( + this._stringTypeAttributes, + "string", + attributes, + ); return; } - addAttributesToBuilder(this._nonStringTypeAttributes, "enum", attributes); + + addAttributesToBuilder( + this._nonStringTypeAttributes, + "enum", + attributes, + ); setUnionInto(this._enumCases, cases); } - addStringCases(cases: string[], attributes: TypeAttributes): void { + public addStringCases(cases: string[], attributes: TypeAttributes): void { this.addFullStringType(attributes, StringTypes.fromCases(cases)); } - addStringCase(s: string, count: number, attributes: TypeAttributes): void { + + public addStringCase( + s: string, + count: number, + attributes: TypeAttributes, + ): void { this.addFullStringType(attributes, StringTypes.fromCase(s, count)); } - get enumCases(): ReadonlySet { + public get enumCases(): ReadonlySet { return this._enumCases; } - getMemberKinds(): TypeAttributeMap { - assert(!(this.have("enum") && this.have("string")), "We can't have both strings and enums in the same union"); + public getMemberKinds(): TypeAttributeMap { + assert( + !(this.have("enum") && this.have("string")), + "We can't have both strings and enums in the same union", + ); - let merged = mapMerge( + const merged = mapMerge( buildTypeAttributeMap(this._nonStringTypeAttributes), - buildTypeAttributeMap(this._stringTypeAttributes) + buildTypeAttributeMap(this._stringTypeAttributes), ); if (merged.size === 0) { - return new Map([["none", emptyTypeAttributes] as [TypeKind, TypeAttributes]]); + return new Map([ + ["none", emptyTypeAttributes] as [TypeKind, TypeAttributes], + ]); } if (this._nonStringTypeAttributes.has("any")) { - assert(this._lostTypeAttributes, "This had to be set when we added 'any'"); + assert( + this._lostTypeAttributes, + "This had to be set when we added 'any'", + ); - const allAttributes = combineTypeAttributes("union", Array.from(merged.values())); - return new Map([["any", allAttributes] as [TypeKind, TypeAttributes]]); + const allAttributes = combineTypeAttributes( + "union", + Array.from(merged.values()), + ); + return new Map([ + ["any", allAttributes] as [TypeKind, TypeAttributes], + ]); } - if (this._conflateNumbers && this.have("integer") && this.have("double")) { + if ( + this._conflateNumbers && + this.have("integer") && + this.have("double") + ) { moveAttributes(merged, "integer", "double"); } + if (this.have("map")) { moveAttributes(merged, "map", "class"); } + return merged; } - get lostTypeAttributes(): boolean { + public get lostTypeAttributes(): boolean { return this._lostTypeAttributes; } } class FauxUnion { - getAttributes(): TypeAttributes { + public getAttributes(): TypeAttributes { return emptyTypeAttributes; } } type UnionOrFaux = UnionType | FauxUnion; -function attributesForTypes(types: Iterable): [ReadonlyMap, TypeAttributes] { +function attributesForTypes( + types: Iterable, +): [ReadonlyMap, TypeAttributes] { // These two maps are the reverse of each other. unionsForType is all the unions // that are ancestors of that type, when going from one of the given types, only // following unions. @@ -232,7 +340,11 @@ function attributesForTypes(types: Iterable): [ReadonlyMap = new Set(); - function traverse(t: Type, path: UnionOrFaux[], isEquivalentToRoot: boolean): void { + function traverse( + t: Type, + path: UnionOrFaux[], + isEquivalentToRoot: boolean, + ): void { if (t instanceof UnionType) { unions.add(t); if (isEquivalentToRoot) { @@ -244,11 +356,16 @@ function attributesForTypes(types: Iterable): [ReadonlyMap (s === undefined ? new Set(path) : setUnionInto(s, path))); + mapUpdateInto(unionsForType, t, (s) => + s === undefined ? new Set(path) : setUnionInto(s, path), + ); for (const u of path) { - mapUpdateInto(typesForUnion, u, s => (s === undefined ? new Set([t]) : s.add(t))); + mapUpdateInto(typesForUnion, u, (s) => + s === undefined ? new Set([t]) : s.add(t), + ); } } } @@ -260,112 +377,161 @@ function attributesForTypes(types: Iterable): [ReadonlyMap { - const singleAncestors = Array.from(unionForType).filter(u => defined(typesForUnion.get(u)).size === 1); + const singleAncestors = Array.from(unionForType).filter( + (u) => defined(typesForUnion.get(u)).size === 1, + ); assert( - singleAncestors.every(u => defined(typesForUnion.get(u)).has(t)), - "We messed up bookkeeping" + singleAncestors.every((u) => defined(typesForUnion.get(u)).has(t)), + "We messed up bookkeeping", + ); + const inheritedAttributes = singleAncestors.map((u) => + u.getAttributes(), + ); + return combineTypeAttributes( + "union", + [t.getAttributes()].concat(inheritedAttributes), ); - const inheritedAttributes = singleAncestors.map(u => u.getAttributes()); - return combineTypeAttributes("union", [t.getAttributes()].concat(inheritedAttributes)); }); - const unionAttributes = Array.from(unions).map(u => { + const unionAttributes = Array.from(unions).map((u) => { const t = typesForUnion.get(u); if (t !== undefined && t.size === 1) { return emptyTypeAttributes; } + const attributes = u.getAttributes(); if (unionsEquivalentToRoot.has(u)) { return attributes; } + return makeTypeAttributesInferred(attributes); }); return [resultAttributes, combineTypeAttributes("union", unionAttributes)]; } // FIXME: Move this to UnifyClasses.ts? -export class TypeRefUnionAccumulator extends UnionAccumulator { +export class TypeRefUnionAccumulator extends UnionAccumulator< + TypeRef, + TypeRef +> { // There is a method analogous to this in the IntersectionAccumulator. It might // make sense to find a common interface. private addType(t: Type, attributes: TypeAttributes): void { matchTypeExhaustive( t, - _noneType => this.addNone(attributes), - _anyType => this.addAny(attributes), - _nullType => this.addPrimitive("null", attributes), - _boolType => this.addPrimitive("bool", attributes), - _integerType => this.addPrimitive("integer", attributes), - _doubleType => this.addPrimitive("double", attributes), - _stringType => this.addStringType("string", attributes), - arrayType => this.addArray(arrayType.items.typeRef, attributes), - classType => this.addObject(classType.typeRef, attributes), - mapType => this.addObject(mapType.typeRef, attributes), - objectType => this.addObject(objectType.typeRef, attributes), + (_noneType) => this.addNone(attributes), + (_anyType) => this.addAny(attributes), + (_nullType) => this.addPrimitive("null", attributes), + (_boolType) => this.addPrimitive("bool", attributes), + (_integerType) => this.addPrimitive("integer", attributes), + (_doubleType) => this.addPrimitive("double", attributes), + (_stringType) => this.addStringType("string", attributes), + (arrayType) => this.addArray(arrayType.items.typeRef, attributes), + (classType) => this.addObject(classType.typeRef, attributes), + (mapType) => this.addObject(mapType.typeRef, attributes), + (objectType) => this.addObject(objectType.typeRef, attributes), // FIXME: We're not carrying counts, so this is not correct if we do enum // inference. JSON Schema input uses this case, however, without enum // inference, which is fine, but still a bit ugly. - enumType => this.addEnum(enumType.cases, attributes), - _unionType => { - return panic("The unions should have been eliminated in attributesForTypesInUnion"); + (enumType) => this.addEnum(enumType.cases, attributes), + (_unionType) => { + return panic( + "The unions should have been eliminated in attributesForTypesInUnion", + ); }, - transformedStringType => - this.addStringType(transformedStringType.kind as PrimitiveStringTypeKind, attributes) + (transformedStringType) => + this.addStringType( + transformedStringType.kind as PrimitiveStringTypeKind, + attributes, + ), ); } - addTypes(types: Iterable): TypeAttributes { + public addTypes(types: Iterable): TypeAttributes { const [attributesMap, unionAttributes] = attributesForTypes(types); for (const [t, attributes] of attributesMap) { this.addType(t, attributes); } + return unionAttributes; } } -export abstract class UnionBuilder { - constructor(protected readonly typeBuilder: TBuilder) {} +export abstract class UnionBuilder< + TBuilder extends TypeBuilder, + TArrayData, + TObjectData, +> { + public constructor(protected readonly typeBuilder: TBuilder) {} protected abstract makeObject( objects: TObjectData, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef; protected abstract makeArray( arrays: TArrayData, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef; private makeTypeOfKind( typeProvider: UnionTypeProvider, kind: TypeKind, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { switch (kind) { case "string": - return this.typeBuilder.getStringType(typeAttributes, undefined, forwardingRef); + return this.typeBuilder.getStringType( + typeAttributes, + undefined, + forwardingRef, + ); case "enum": - return this.typeBuilder.getEnumType(typeAttributes, typeProvider.enumCases, forwardingRef); + return this.typeBuilder.getEnumType( + typeAttributes, + typeProvider.enumCases, + forwardingRef, + ); case "object": - return this.makeObject(typeProvider.objectData, typeAttributes, forwardingRef); + return this.makeObject( + typeProvider.objectData, + typeAttributes, + forwardingRef, + ); case "array": - return this.makeArray(typeProvider.arrayData, typeAttributes, forwardingRef); + return this.makeArray( + typeProvider.arrayData, + typeAttributes, + forwardingRef, + ); default: if (isPrimitiveTypeKind(kind)) { - return this.typeBuilder.getPrimitiveType(kind, typeAttributes, forwardingRef); + return this.typeBuilder.getPrimitiveType( + kind, + typeAttributes, + forwardingRef, + ); } - if (kind === "union" || kind === "class" || kind === "map" || kind === "intersection") { + + if ( + kind === "union" || + kind === "class" || + kind === "map" || + kind === "intersection" + ) { return panic(`getMemberKinds() shouldn't return ${kind}`); } + return assertNever(kind); } } - buildUnion( + public buildUnion( typeProvider: UnionTypeProvider, unique: boolean, typeAttributes: TypeAttributes, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const kinds = typeProvider.getMemberKinds(); @@ -382,26 +548,47 @@ export abstract class UnionBuilder; export type AccessorNames = Map; class AccessorNamesTypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("accessorNames"); } - makeInferred(_: AccessorNames): undefined { + public makeInferred(_: AccessorNames): undefined { return undefined; } } -export const accessorNamesTypeAttributeKind: TypeAttributeKind = new AccessorNamesTypeAttributeKind(); +export const accessorNamesTypeAttributeKind: TypeAttributeKind = + new AccessorNamesTypeAttributeKind(); // Returns [name, isFixed]. -function getFromEntry(entry: AccessorEntry, language: string): [string, boolean] | undefined { +function getFromEntry( + entry: AccessorEntry, + language: string, +): [string, boolean] | undefined { if (typeof entry === "string") return [entry, false]; const maybeForLanguage = entry.get(language); @@ -43,28 +62,43 @@ function getFromEntry(entry: AccessorEntry, language: string): [string, boolean] return undefined; } -export function lookupKey(accessors: AccessorNames, key: string, language: string): [string, boolean] | undefined { +export function lookupKey( + accessors: AccessorNames, + key: string, + language: string, +): [string, boolean] | undefined { const entry = accessors.get(key); if (entry === undefined) return undefined; return getFromEntry(entry, language); } -export function objectPropertyNames(o: ObjectType, language: string): Map { - const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes(o.getAttributes()); +export function objectPropertyNames( + o: ObjectType, + language: string, +): Map { + const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes( + o.getAttributes(), + ); const map = o.getProperties(); - if (accessors === undefined) return mapMap(map, _ => undefined); + if (accessors === undefined) return mapMap(map, (_) => undefined); return mapMap(map, (_cp, n) => lookupKey(accessors, n, language)); } -export function enumCaseNames(e: EnumType, language: string): Map { - const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes(e.getAttributes()); - if (accessors === undefined) return mapMap(e.cases.entries(), _ => undefined); - return mapMap(e.cases.entries(), c => lookupKey(accessors, c, language)); +export function enumCaseNames( + e: EnumType, + language: string, +): Map { + const accessors = accessorNamesTypeAttributeKind.tryGetInAttributes( + e.getAttributes(), + ); + if (accessors === undefined) + return mapMap(e.cases.entries(), (_) => undefined); + return mapMap(e.cases.entries(), (c) => lookupKey(accessors, c, language)); } export function getAccessorName( names: Map, - original: string + original: string, ): [string | undefined, boolean] { const maybeName = names.get(original); if (maybeName === undefined) return [undefined, false]; @@ -78,59 +112,83 @@ export function getAccessorName( // That way, no matter how the types are recombined, if we find a union member, we can look // up its union's identifier(s), and then look up the member's accessor entries for that // identifier. Of course we might find more than one, potentially conflicting. -class UnionIdentifierTypeAttributeKind extends TypeAttributeKind> { - constructor() { +class UnionIdentifierTypeAttributeKind extends TypeAttributeKind< + ReadonlySet +> { + public constructor() { super("unionIdentifier"); } - combine(arr: ReadonlySet[]): ReadonlySet { + public combine(arr: Array>): ReadonlySet { return setUnionManyInto(new Set(), arr); } - makeInferred(_: ReadonlySet): ReadonlySet { + public makeInferred(_: ReadonlySet): ReadonlySet { return new Set(); } } -export const unionIdentifierTypeAttributeKind: TypeAttributeKind> = - new UnionIdentifierTypeAttributeKind(); +export const unionIdentifierTypeAttributeKind: TypeAttributeKind< + ReadonlySet +> = new UnionIdentifierTypeAttributeKind(); let nextUnionIdentifier = 0; export function makeUnionIdentifierAttribute(): TypeAttributes { - const attributes = unionIdentifierTypeAttributeKind.makeAttributes(new Set([nextUnionIdentifier])); + const attributes = unionIdentifierTypeAttributeKind.makeAttributes( + new Set([nextUnionIdentifier]), + ); nextUnionIdentifier += 1; return attributes; } -class UnionMemberNamesTypeAttributeKind extends TypeAttributeKind> { - constructor() { +class UnionMemberNamesTypeAttributeKind extends TypeAttributeKind< + Map +> { + public constructor() { super("unionMemberNames"); } - combine(arr: Map[]): Map { + public combine( + arr: Array>, + ): Map { const result = new Map(); for (const m of arr) { mapMergeInto(result, m); } + return result; } } -export const unionMemberNamesTypeAttributeKind: TypeAttributeKind> = - new UnionMemberNamesTypeAttributeKind(); - -export function makeUnionMemberNamesAttribute(unionAttributes: TypeAttributes, entry: AccessorEntry): TypeAttributes { - const identifiers = defined(unionIdentifierTypeAttributeKind.tryGetInAttributes(unionAttributes)); - const map = mapFromIterable(identifiers, _ => entry); +export const unionMemberNamesTypeAttributeKind: TypeAttributeKind< + Map +> = new UnionMemberNamesTypeAttributeKind(); + +export function makeUnionMemberNamesAttribute( + unionAttributes: TypeAttributes, + entry: AccessorEntry, +): TypeAttributes { + const identifiers = defined( + unionIdentifierTypeAttributeKind.tryGetInAttributes(unionAttributes), + ); + const map = mapFromIterable(identifiers, (_) => entry); return unionMemberNamesTypeAttributeKind.makeAttributes(map); } -export function unionMemberName(u: UnionType, member: Type, language: string): [string | undefined, boolean] { - const identifiers = unionIdentifierTypeAttributeKind.tryGetInAttributes(u.getAttributes()); +export function unionMemberName( + u: UnionType, + member: Type, + language: string, +): [string | undefined, boolean] { + const identifiers = unionIdentifierTypeAttributeKind.tryGetInAttributes( + u.getAttributes(), + ); if (identifiers === undefined) return [undefined, false]; - const memberNames = unionMemberNamesTypeAttributeKind.tryGetInAttributes(member.getAttributes()); + const memberNames = unionMemberNamesTypeAttributeKind.tryGetInAttributes( + member.getAttributes(), + ); if (memberNames === undefined) return [undefined, false]; const names = new Set(); @@ -162,23 +220,30 @@ export function unionMemberName(u: UnionType, member: Type, language: string): [ isFixed = false; } - messageAssert(size === 1, "SchemaMoreThanOneUnionMemberName", { names: Array.from(names) }); + messageAssert(size === 1, "SchemaMoreThanOneUnionMemberName", { + names: Array.from(names), + }); return [first, isFixed]; } -function isAccessorEntry(x: any): x is string | { [language: string]: string } { +function isAccessorEntry( + x: unknown, +): x is string | { [language: string]: string } { if (typeof x === "string") { return true; } - return isStringMap(x, (v: any): v is string => typeof v === "string"); + + return isStringMap(x, (v: unknown): v is string => typeof v === "string"); } -function makeAccessorEntry(ae: string | { [language: string]: string }): AccessorEntry { +function makeAccessorEntry( + ae: string | { [language: string]: string }, +): AccessorEntry { if (typeof ae === "string") return ae; return mapFromObject(ae); } -export function makeAccessorNames(x: any): AccessorNames { +export function makeAccessorNames(x: unknown): AccessorNames { // FIXME: Do proper error reporting const stringMap = checkStringMap(x, isAccessorEntry); return mapMap(mapFromObject(stringMap), makeAccessorEntry); @@ -188,24 +253,35 @@ export function accessorNamesAttributeProducer( schema: JSONSchema, canonicalRef: Ref, _types: Set, - cases: JSONSchema[] | undefined + cases: JSONSchema[] | undefined, ): JSONSchemaAttributes | undefined { if (typeof schema !== "object") return undefined; const maybeAccessors = schema["qt-accessors"]; if (maybeAccessors === undefined) return undefined; if (cases === undefined) { - return { forType: accessorNamesTypeAttributeKind.makeAttributes(makeAccessorNames(maybeAccessors)) }; + return { + forType: accessorNamesTypeAttributeKind.makeAttributes( + makeAccessorNames(maybeAccessors), + ), + }; } else { const identifierAttribute = makeUnionIdentifierAttribute(); const accessors = checkArray(maybeAccessors, isAccessorEntry); - messageAssert(cases.length === accessors.length, "SchemaWrongAccessorEntryArrayLength", { - operation: "oneOf", - ref: canonicalRef.push("oneOf") - }); - const caseAttributes = accessors.map(accessor => - makeUnionMemberNamesAttribute(identifierAttribute, makeAccessorEntry(accessor)) + messageAssert( + cases.length === accessors.length, + "SchemaWrongAccessorEntryArrayLength", + { + operation: "oneOf", + ref: canonicalRef.push("oneOf"), + }, + ); + const caseAttributes = accessors.map((accessor) => + makeUnionMemberNamesAttribute( + identifierAttribute, + makeAccessorEntry(accessor), + ), ); return { forUnion: identifierAttribute, forCases: caseAttributes }; } diff --git a/packages/quicktype-core/src/attributes/Constraints.ts b/packages/quicktype-core/src/attributes/Constraints.ts index a0370f4cc..3266e9bc5 100644 --- a/packages/quicktype-core/src/attributes/Constraints.ts +++ b/packages/quicktype-core/src/attributes/Constraints.ts @@ -1,41 +1,50 @@ -import { Type, TypeKind } from "../Type"; -import { TypeAttributeKind } from "./TypeAttributes"; -import { assert } from "../support/Support"; +import type { + JSONSchemaAttributes, + JSONSchemaType, + Ref, +} from "../input/JSONSchemaInput"; +import type { JSONSchema } from "../input/JSONSchemaStore"; import { messageError } from "../Messages"; -import { JSONSchemaType, JSONSchemaAttributes, Ref } from "../input/JSONSchemaInput"; -import { JSONSchema } from "../input/JSONSchemaStore"; +import { assert } from "../support/Support"; +import type { Type, TypeKind } from "../Type"; + +import { TypeAttributeKind } from "./TypeAttributes"; // This can't be an object type, unfortunately, because it's in the // type's identity and as such must be comparable and hashable with // `areEqual`, `hashCodeOf`. export type MinMaxConstraint = [number | undefined, number | undefined]; -function checkMinMaxConstraint(minmax: MinMaxConstraint): MinMaxConstraint | undefined { +function checkMinMaxConstraint( + minmax: MinMaxConstraint, +): MinMaxConstraint | undefined { const [min, max] = minmax; if (typeof min === "number" && typeof max === "number" && min > max) { return messageError("MiscInvalidMinMaxConstraint", { min, max }); } + if (min === undefined && max === undefined) { return undefined; } + return minmax; } export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind { - constructor( + public constructor( name: string, - private _typeKinds: Set, + private readonly _typeKinds: Set, private _minSchemaProperty: string, - private _maxSchemaProperty: string + private _maxSchemaProperty: string, ) { super(name); } - get inIdentity(): boolean { + public get inIdentity(): boolean { return true; } - combine(arr: MinMaxConstraint[]): MinMaxConstraint | undefined { + public combine(arr: MinMaxConstraint[]): MinMaxConstraint | undefined { assert(arr.length > 0); let [min, max] = arr[0]; @@ -46,16 +55,18 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind 0); let [min, max] = arr[0]; @@ -66,51 +77,64 @@ export class MinMaxConstraintTypeAttributeKind extends TypeAttributeKind = new MinMaxConstraintTypeAttributeKind( - "minMax", - new Set(["integer", "double"]), - "minimum", - "maximum" -); - -export const minMaxLengthTypeAttributeKind: TypeAttributeKind = new MinMaxConstraintTypeAttributeKind( - "minMaxLength", - new Set(["string"]), - "minLength", - "maxLength" -); - -function producer(schema: JSONSchema, minProperty: string, maxProperty: string): MinMaxConstraint | undefined { +export const minMaxTypeAttributeKind: TypeAttributeKind = + new MinMaxConstraintTypeAttributeKind( + "minMax", + new Set(["integer", "double"]), + "minimum", + "maximum", + ); + +export const minMaxLengthTypeAttributeKind: TypeAttributeKind = + new MinMaxConstraintTypeAttributeKind( + "minMaxLength", + new Set(["string"]), + "minLength", + "maxLength", + ); + +function producer( + schema: JSONSchema, + minProperty: string, + maxProperty: string, +): MinMaxConstraint | undefined { if (!(typeof schema === "object")) return undefined; let min: number | undefined = undefined; @@ -119,6 +143,7 @@ function producer(schema: JSONSchema, minProperty: string, maxProperty: string): if (typeof schema[minProperty] === "number") { min = schema[minProperty]; } + if (typeof schema[maxProperty] === "number") { max = schema[maxProperty]; } @@ -130,7 +155,7 @@ function producer(schema: JSONSchema, minProperty: string, maxProperty: string): export function minMaxAttributeProducer( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!types.has("number") && !types.has("integer")) return undefined; @@ -142,13 +167,16 @@ export function minMaxAttributeProducer( export function minMaxLengthAttributeProducer( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!types.has("string")) return undefined; const maybeMinMaxLength = producer(schema, "minLength", "maxLength"); if (maybeMinMaxLength === undefined) return undefined; - return { forString: minMaxLengthTypeAttributeKind.makeAttributes(maybeMinMaxLength) }; + return { + forString: + minMaxLengthTypeAttributeKind.makeAttributes(maybeMinMaxLength), + }; } export function minMaxValueForType(t: Type): MinMaxConstraint | undefined { @@ -160,40 +188,45 @@ export function minMaxLengthForType(t: Type): MinMaxConstraint | undefined { } export class PatternTypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("pattern"); } - get inIdentity(): boolean { + public get inIdentity(): boolean { return true; } - combine(arr: string[]): string { + public combine(arr: string[]): string { assert(arr.length > 0); - return arr.map(p => `(${p})`).join("|"); + return arr.map((p) => `(${p})`).join("|"); } - intersect(_arr: string[]): string | undefined { + public intersect(_arr: string[]): string | undefined { /** FIXME!!! what is the intersection of regexps? */ return undefined; } - makeInferred(_: string): undefined { + public makeInferred(_: string): undefined { return undefined; } - addToSchema(schema: { [name: string]: unknown }, t: Type, attr: string): void { + public addToSchema( + schema: { [name: string]: unknown }, + t: Type, + attr: string, + ): void { if (t.kind !== "string") return; schema.pattern = attr; } } -export const patternTypeAttributeKind: TypeAttributeKind = new PatternTypeAttributeKind(); +export const patternTypeAttributeKind: TypeAttributeKind = + new PatternTypeAttributeKind(); export function patternAttributeProducer( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; if (!types.has("string")) return undefined; diff --git a/packages/quicktype-core/src/attributes/Description.ts b/packages/quicktype-core/src/attributes/Description.ts index 6684b95c3..e6a568d8e 100644 --- a/packages/quicktype-core/src/attributes/Description.ts +++ b/packages/quicktype-core/src/attributes/Description.ts @@ -1,87 +1,108 @@ import { + iterableFirst, mapFilterMap, mapFromObject, + mapMergeWithInto, + setSubtract, setUnion, - iterableFirst, setUnionManyInto, - mapMergeWithInto, - setSubtract } from "collection-utils"; -// There's a cyclic import here. Ignoring now because it requires a large refactor. -// skipcq: JS-E1008 +import type { + JSONSchemaAttributes, + JSONSchemaType, + Ref, +} from "../input/JSONSchemaInput"; +import type { JSONSchema } from "../input/JSONSchemaStore"; +import { type PathElement, PathElementKind } from "../input/PathElement"; +import type { Type } from "../Type/Type"; + import { TypeAttributeKind, emptyTypeAttributes } from "./TypeAttributes"; -// FIXME: This is a circular import -import { JSONSchemaType, Ref, JSONSchemaAttributes, PathElementKind, PathElement } from "../input/JSONSchemaInput"; -import { JSONSchema } from "../input/JSONSchemaStore"; -import { Type } from "../Type"; export function addDescriptionToSchema( schema: { [name: string]: unknown }, - description: Iterable | undefined + description: Iterable | undefined, ): void { if (description === undefined) return; schema.description = Array.from(description).join("\n"); } -class DescriptionTypeAttributeKind extends TypeAttributeKind> { - constructor() { +class DescriptionTypeAttributeKind extends TypeAttributeKind< + ReadonlySet +> { + public constructor() { super("description"); } - combine(attrs: ReadonlySet[]): ReadonlySet { + public combine(attrs: Array>): ReadonlySet { return setUnionManyInto(new Set(), attrs); } - makeInferred(_: ReadonlySet): undefined { + public makeInferred(_: ReadonlySet): undefined { return undefined; } - addToSchema(schema: { [name: string]: unknown }, _t: Type, attrs: ReadonlySet): void { + public addToSchema( + schema: { [name: string]: unknown }, + _t: Type, + attrs: ReadonlySet, + ): void { addDescriptionToSchema(schema, attrs); } - stringify(descriptions: ReadonlySet): string | undefined { + public stringify(descriptions: ReadonlySet): string | undefined { let result = iterableFirst(descriptions); if (result === undefined) return undefined; if (result.length > 5 + 3) { result = `${result.slice(0, 5)}...`; } + if (descriptions.size > 1) { result = `${result}, ...`; } + return result; } } -export const descriptionTypeAttributeKind: TypeAttributeKind> = new DescriptionTypeAttributeKind(); +export const descriptionTypeAttributeKind: TypeAttributeKind< + ReadonlySet +> = new DescriptionTypeAttributeKind(); -class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind>> { - constructor() { +class PropertyDescriptionsTypeAttributeKind extends TypeAttributeKind< + Map> +> { + public constructor() { super("propertyDescriptions"); } - combine(attrs: Map>[]): Map> { + public combine( + attrs: Array>>, + ): Map> { // FIXME: Implement this with mutable sets const result = new Map>(); for (const attr of attrs) { mapMergeWithInto(result, (sa, sb) => setUnion(sa, sb), attr); } + return result; } - makeInferred(_: Map>): undefined { + public makeInferred(_: Map>): undefined { return undefined; } - stringify(propertyDescriptions: Map>): string | undefined { + public stringify( + propertyDescriptions: Map>, + ): string | undefined { if (propertyDescriptions.size === 0) return undefined; return `prop descs: ${propertyDescriptions.size}`; } } -export const propertyDescriptionsTypeAttributeKind: TypeAttributeKind>> = - new PropertyDescriptionsTypeAttributeKind(); +export const propertyDescriptionsTypeAttributeKind: TypeAttributeKind< + Map> +> = new PropertyDescriptionsTypeAttributeKind(); function isPropertiesKey(el: PathElement): boolean { return el.kind === PathElementKind.KeyOrIndex && el.key === "properties"; @@ -90,7 +111,7 @@ function isPropertiesKey(el: PathElement): boolean { export function descriptionAttributeProducer( schema: JSONSchema, ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; @@ -107,22 +128,35 @@ export function descriptionAttributeProducer( ) { const maybeDescription = schema.description; if (typeof maybeDescription === "string") { - description = descriptionTypeAttributeKind.makeAttributes(new Set([maybeDescription])); + description = descriptionTypeAttributeKind.makeAttributes( + new Set([maybeDescription]), + ); } } if (types.has("object") && typeof schema.properties === "object") { - const propertyDescriptions = mapFilterMap(mapFromObject(schema.properties), propSchema => { - if (typeof propSchema === "object") { - const desc = propSchema.description; - if (typeof desc === "string") { - return new Set([desc]); + const propertyDescriptions = mapFilterMap( + mapFromObject(schema.properties), + (propSchema) => { + if ( + propSchema && + typeof propSchema === "object" && + "description" in propSchema + ) { + const desc = propSchema.description; + if (typeof desc === "string") { + return new Set([desc]); + } } - } - return undefined; - }); + + return undefined; + }, + ); if (propertyDescriptions.size > 0) { - propertyDescription = propertyDescriptionsTypeAttributeKind.makeAttributes(propertyDescriptions); + propertyDescription = + propertyDescriptionsTypeAttributeKind.makeAttributes( + propertyDescriptions, + ); } } diff --git a/packages/quicktype-core/src/attributes/EnumValues.ts b/packages/quicktype-core/src/attributes/EnumValues.ts index f81b73a37..6c1c83199 100644 --- a/packages/quicktype-core/src/attributes/EnumValues.ts +++ b/packages/quicktype-core/src/attributes/EnumValues.ts @@ -1,32 +1,49 @@ import { mapMap } from "collection-utils"; -import { lookupKey, AccessorNames, makeAccessorNames } from "./AccessorNames"; -import { EnumType } from "../Type"; +import type { + JSONSchemaAttributes, + JSONSchemaType, + Ref, +} from "../input/JSONSchemaInput"; +import type { JSONSchema } from "../input/JSONSchemaStore"; +import type { EnumType } from "../Type/Type"; + +import { + type AccessorNames, + lookupKey, + makeAccessorNames, +} from "./AccessorNames"; import { TypeAttributeKind } from "./TypeAttributes"; -import { JSONSchema } from "../input/JSONSchemaStore"; -import { Ref, JSONSchemaType, JSONSchemaAttributes } from "../input/JSONSchemaInput"; class EnumValuesTypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("enumValues"); } - makeInferred(_: AccessorNames) { + + public makeInferred(_: AccessorNames): undefined { return undefined; } } -export const enumValuesTypeAttributeKind: TypeAttributeKind = new EnumValuesTypeAttributeKind(); - -export function enumCaseValues(e: EnumType, language: string): Map { - const enumValues = enumValuesTypeAttributeKind.tryGetInAttributes(e.getAttributes()); - if (enumValues === undefined) return mapMap(e.cases.entries(), _ => undefined); - return mapMap(e.cases.entries(), c => lookupKey(enumValues, c, language)); +export const enumValuesTypeAttributeKind: TypeAttributeKind = + new EnumValuesTypeAttributeKind(); + +export function enumCaseValues( + e: EnumType, + language: string, +): Map { + const enumValues = enumValuesTypeAttributeKind.tryGetInAttributes( + e.getAttributes(), + ); + if (enumValues === undefined) + return mapMap(e.cases.entries(), (_) => undefined); + return mapMap(e.cases.entries(), (c) => lookupKey(enumValues, c, language)); } export function enumValuesAttributeProducer( schema: JSONSchema, _canonicalRef: Ref | undefined, - _types: Set + _types: Set, ): JSONSchemaAttributes | undefined { if (typeof schema !== "object") return undefined; @@ -34,5 +51,9 @@ export function enumValuesAttributeProducer( if (maybeEnumValues === undefined) return undefined; - return { forType: enumValuesTypeAttributeKind.makeAttributes(makeAccessorNames(maybeEnumValues)) }; + return { + forType: enumValuesTypeAttributeKind.makeAttributes( + makeAccessorNames(maybeEnumValues), + ), + }; } diff --git a/packages/quicktype-core/src/attributes/StringTypes.ts b/packages/quicktype-core/src/attributes/StringTypes.ts index 63ea20db9..ea890bd0e 100644 --- a/packages/quicktype-core/src/attributes/StringTypes.ts +++ b/packages/quicktype-core/src/attributes/StringTypes.ts @@ -1,53 +1,70 @@ import { - mapMap, - iterableFirst, - setIntersect, - hashCodeOf, + addHashCode, areEqual, - mapMergeWithInto, definedMap, - addHashCode, - setUnionInto + hashCodeOf, + iterableFirst, + mapMap, + mapMergeWithInto, + setIntersect, + setUnionInto, } from "collection-utils"; +import type { DateTimeRecognizer } from "../DateTime"; +import { assert, defined } from "../support/Support"; +import type { TransformedStringTypeKind } from "../Type/TransformedStringType"; +import { + type StringTypeMapping, + stringTypeMappingGet, +} from "../Type/TypeBuilderUtils"; + import { TypeAttributeKind } from "./TypeAttributes"; -import { defined, assert } from "../support/Support"; -import { StringTypeMapping, stringTypeMappingGet } from "../TypeBuilder"; -import { TransformedStringTypeKind } from "../Type"; -import { DateTimeRecognizer } from "../DateTime"; export class StringTypes { - static readonly unrestricted: StringTypes = new StringTypes(undefined, new Set()); + public static readonly unrestricted: StringTypes = new StringTypes( + undefined, + new Set(), + ); - static fromCase(s: string, count: number): StringTypes { + public static fromCase(s: string, count: number): StringTypes { const caseMap: { [name: string]: number } = {}; caseMap[s] = count; - return new StringTypes(new Map([[s, count] as [string, number]]), new Set()); + return new StringTypes( + new Map([[s, count] as [string, number]]), + new Set(), + ); } - static fromCases(cases: string[]): StringTypes { + public static fromCases(cases: string[]): StringTypes { const caseMap: { [name: string]: number } = {}; for (const s of cases) { caseMap[s] = 1; } - return new StringTypes(new Map(cases.map(s => [s, 1] as [string, number])), new Set()); + + return new StringTypes( + new Map(cases.map((s) => [s, 1] as [string, number])), + new Set(), + ); } // undefined means no restrictions - constructor( - readonly cases: ReadonlyMap | undefined, - readonly transformations: ReadonlySet + public constructor( + public readonly cases: ReadonlyMap | undefined, + public readonly transformations: ReadonlySet, ) { if (cases === undefined) { - assert(transformations.size === 0, "We can't have an unrestricted string that also allows transformations"); + assert( + transformations.size === 0, + "We can't have an unrestricted string that also allows transformations", + ); } } - get isRestricted(): boolean { + public get isRestricted(): boolean { return this.cases !== undefined; } - union(othersArray: StringTypes[], startIndex: number): StringTypes { + public union(othersArray: StringTypes[], startIndex: number): StringTypes { if (this.cases === undefined) return this; const cases = new Map(this.cases); @@ -65,7 +82,10 @@ export class StringTypes { return new StringTypes(cases, transformations); } - intersect(othersArray: StringTypes[], startIndex: number): StringTypes { + public intersect( + othersArray: StringTypes[], + startIndex: number, + ): StringTypes { let cases = this.cases; let transformations = this.transformations; @@ -73,21 +93,36 @@ export class StringTypes { const other = othersArray[i]; if (cases === undefined) { - cases = definedMap(other.cases, m => new Map(m)); + cases = definedMap(other.cases, (m) => new Map(m)); } else if (other.cases !== undefined) { const thisCases = cases; const otherCases = other.cases; - cases = mapMap(setIntersect(thisCases.keys(), new Set(otherCases.keys())).entries(), k => - Math.min(defined(thisCases.get(k)), defined(otherCases.get(k))) + + const intersects = setIntersect( + thisCases.keys(), + new Set(otherCases.keys()), ); + const entries = + intersects.size > 0 + ? intersects.entries() + : new Set(thisCases.keys()).entries(); + cases = mapMap(entries, (k) => { + const thisValue = defined(thisCases.get(k)); + const otherValue = otherCases.get(k) ?? Math.min(); + return Math.min(thisValue, otherValue); + }); } - transformations = setIntersect(transformations, other.transformations); + transformations = setIntersect( + transformations, + other.transformations, + ); } + return new StringTypes(cases, transformations); } - applyStringTypeMapping(mapping: StringTypeMapping): StringTypes { + public applyStringTypeMapping(mapping: StringTypeMapping): StringTypes { if (!this.isRestricted) return this; const kinds = new Set(); @@ -96,21 +131,25 @@ export class StringTypes { if (mapped === "string") return StringTypes.unrestricted; kinds.add(mapped); } + return new StringTypes(this.cases, new Set(kinds)); } - equals(other: any): boolean { + public equals(other: T): boolean { if (!(other instanceof StringTypes)) return false; - return areEqual(this.cases, other.cases) && areEqual(this.transformations, other.transformations); + return ( + areEqual(this.cases, other.cases) && + areEqual(this.transformations, other.transformations) + ); } - hashCode(): number { + public hashCode(): number { let h = hashCodeOf(this.cases); h = addHashCode(h, hashCodeOf(this.transformations)); return h; } - toString(): string { + public toString(): string { const parts: string[] = []; const enumCases = this.cases; @@ -121,7 +160,9 @@ export class StringTypes { if (firstKey === undefined) { parts.push("enum with no cases"); } else { - parts.push(`${enumCases.size.toString()} enums: ${firstKey} (${enumCases.get(firstKey)}), ...`); + parts.push( + `${enumCases.size.toString()} enums: ${firstKey} (${enumCases.get(firstKey)}), ...`, + ); } } @@ -130,38 +171,39 @@ export class StringTypes { } class StringTypesTypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("stringTypes"); } - get inIdentity(): boolean { + public get inIdentity(): boolean { return true; } - requiresUniqueIdentity(st: StringTypes): boolean { + public requiresUniqueIdentity(st: StringTypes): boolean { return st.cases !== undefined && st.cases.size > 0; } - combine(arr: StringTypes[]): StringTypes { + public combine(arr: StringTypes[]): StringTypes { assert(arr.length > 0); return arr[0].union(arr, 1); } - intersect(arr: StringTypes[]): StringTypes { + public intersect(arr: StringTypes[]): StringTypes { assert(arr.length > 0); return arr[0].intersect(arr, 1); } - makeInferred(_: StringTypes): undefined { + public makeInferred(_: StringTypes): undefined { return undefined; } - stringify(st: StringTypes): string { + public stringify(st: StringTypes): string { return st.toString(); } } -export const stringTypesTypeAttributeKind: TypeAttributeKind = new StringTypesTypeAttributeKind(); +export const stringTypesTypeAttributeKind: TypeAttributeKind = + new StringTypesTypeAttributeKind(); const INTEGER_STRING = /^(0|-?[1-9]\d*)$/; // We're restricting numbers to what's representable as 32 bit @@ -170,17 +212,18 @@ const MIN_INTEGER_STRING = 1 << 31; const MAX_INTEGER_STRING = -(MIN_INTEGER_STRING + 1); function isIntegerString(s: string): boolean { - if (s.match(INTEGER_STRING) === null) { + if (INTEGER_STRING.exec(s) === null) { return false; } - const i = parseInt(s, 10); + + const i = Number.parseInt(s, 10); return i >= MIN_INTEGER_STRING && i <= MAX_INTEGER_STRING; } const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/; function isUUID(s: string): boolean { - return s.match(UUID) !== null; + return UUID.exec(s) !== null; } // FIXME: This is obviously not a complete URI regex. The exclusion of @@ -189,7 +232,7 @@ function isUUID(s: string): boolean { const URI = /^(https?|ftp):\/\/[^{}]+$/; function isURI(s: string): boolean { - return s.match(URI) !== null; + return URI.exec(s) !== null; } /** @@ -201,24 +244,32 @@ function isURI(s: string): boolean { */ export function inferTransformedStringTypeKindForString( s: string, - recognizer: DateTimeRecognizer + recognizer: DateTimeRecognizer, ): TransformedStringTypeKind | undefined { - if (s.length === 0 || "0123456789-abcdefth".indexOf(s[0]) < 0) return undefined; + if (s.length === 0 || !"0123456789-abcdefth".includes(s[0])) + return undefined; if (recognizer.isDate(s)) { return "date"; - } else if (recognizer.isTime(s)) { + } + if (recognizer.isTime(s)) { return "time"; - } else if (recognizer.isDateTime(s)) { + } + if (recognizer.isDateTime(s)) { return "date-time"; - } else if (isIntegerString(s)) { + } + if (isIntegerString(s)) { return "integer-string"; - } else if (s === "false" || s === "true") { + } + if (s === "false" || s === "true") { return "bool-string"; - } else if (isUUID(s)) { + } + if (isUUID(s)) { return "uuid"; - } else if (isURI(s)) { + } + if (isURI(s)) { return "uri"; } + return undefined; } diff --git a/packages/quicktype-core/src/attributes/TypeAttributes.ts b/packages/quicktype-core/src/attributes/TypeAttributes.ts index 1c73e8ffc..069377e80 100644 --- a/packages/quicktype-core/src/attributes/TypeAttributes.ts +++ b/packages/quicktype-core/src/attributes/TypeAttributes.ts @@ -1,62 +1,74 @@ -import { mapFilterMap, mapFilter, mapTranspose, hashString } from "collection-utils"; +import { + hashString, + mapFilter, + mapFilterMap, + mapTranspose, +} from "collection-utils"; -import { panic, assert } from "../support/Support"; -import { Type, TypeKind } from "../Type"; -import { BaseGraphRewriteBuilder } from "../GraphRewriting"; +import type { BaseGraphRewriteBuilder } from "../GraphRewriting"; +import { assert, panic } from "../support/Support"; +import type { Type, TypeKind } from "../Type"; export class TypeAttributeKind { - constructor(readonly name: string) {} + public constructor(public readonly name: string) {} - appliesToTypeKind(kind: TypeKind): boolean { + public appliesToTypeKind(kind: TypeKind): boolean { return kind !== "any"; } - combine(_attrs: T[]): T | undefined { + public combine(_attrs: T[]): T | undefined { return panic(`Cannot combine type attribute ${this.name}`); } - intersect(attrs: T[]): T | undefined { + public intersect(attrs: T[]): T | undefined { return this.combine(attrs); } - makeInferred(_: T): T | undefined { + public makeInferred(_: T): T | undefined { return panic(`Cannot make type attribute ${this.name} inferred`); } - increaseDistance(attrs: T): T | undefined { + public increaseDistance(attrs: T): T | undefined { return attrs; } - addToSchema(_schema: { [name: string]: unknown }, _t: Type, _attrs: T): void { + public addToSchema( + _schema: { [name: string]: unknown }, + _t: Type, + _attrs: T, + ): void { return; } - children(_: T): ReadonlySet { + public children(_: T): ReadonlySet { return new Set(); } - stringify(_: T): string | undefined { + public stringify(_: T): string | undefined { return undefined; } - get inIdentity(): boolean { + public get inIdentity(): boolean { return false; } - requiresUniqueIdentity(_: T): boolean { + public requiresUniqueIdentity(_: T): boolean { return false; } - reconstitute(_builder: TBuilder, a: T): T { + public reconstitute( + _builder: TBuilder, + a: T, + ): T { return a; } - makeAttributes(value: T): TypeAttributes { - const kvps: [this, T][] = [[this, value]]; + public makeAttributes(value: T): TypeAttributes { + const kvps: Array<[this, T]> = [[this, value]]; return new Map(kvps); } - tryGetInAttributes(a: TypeAttributes): T | undefined { + public tryGetInAttributes(a: TypeAttributes): T | undefined { return a.get(this); } @@ -65,7 +77,10 @@ export class TypeAttributeKind { return new Map(a).set(this, value); } - modifyInAttributes(a: TypeAttributes, modify: (value: T | undefined) => T | undefined): TypeAttributes { + public modifyInAttributes( + a: TypeAttributes, + modify: (value: T | undefined) => T | undefined, + ): TypeAttributes { const modified = modify(this.tryGetInAttributes(a)); if (modified === undefined) { // FIXME: This is potentially super slow @@ -73,42 +88,56 @@ export class TypeAttributeKind { result.delete(this); return result; } + return this.setInAttributes(a, modified); } - setDefaultInAttributes(a: TypeAttributes, makeDefault: () => T): TypeAttributes { + public setDefaultInAttributes( + a: TypeAttributes, + makeDefault: () => T, + ): TypeAttributes { if (this.tryGetInAttributes(a) !== undefined) return a; return this.modifyInAttributes(a, makeDefault); } - removeInAttributes(a: TypeAttributes): TypeAttributes { + public removeInAttributes(a: TypeAttributes): TypeAttributes { return mapFilter(a, (_, k) => k !== this); } - equals(other: any): boolean { + public equals(other: TypeAttributeKind): boolean { if (!(other instanceof TypeAttributeKind)) { return false; } + return this.name === other.name; } - hashCode(): number { + public hashCode(): number { return hashString(this.name); } } +// FIXME: strongly type this +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type TypeAttributes = ReadonlyMap, any>; export const emptyTypeAttributes: TypeAttributes = new Map(); export type CombinationKind = "union" | "intersect"; -export function combineTypeAttributes(kind: CombinationKind, attributeArray: TypeAttributes[]): TypeAttributes; -export function combineTypeAttributes(kind: CombinationKind, a: TypeAttributes, b: TypeAttributes): TypeAttributes; +export function combineTypeAttributes( + kind: CombinationKind, + attributeArray: TypeAttributes[], +): TypeAttributes; +export function combineTypeAttributes( + kind: CombinationKind, + a: TypeAttributes, + b: TypeAttributes, +): TypeAttributes; export function combineTypeAttributes( combinationKind: CombinationKind, firstOrArray: TypeAttributes[] | TypeAttributes, - second?: TypeAttributes + second?: TypeAttributes, ): TypeAttributes { const union = combinationKind === "union"; let attributeArray: TypeAttributes[]; @@ -118,11 +147,14 @@ export function combineTypeAttributes( if (second === undefined) { return panic("Must have on array or two attributes"); } + attributeArray = [firstOrArray, second]; } const attributesByKind = mapTranspose(attributeArray); + // FIXME: strongly type this + // eslint-disable-next-line @typescript-eslint/no-explicit-any function combine(attrs: any[], kind: TypeAttributeKind): any { assert(attrs.length > 0, "Cannot combine zero type attributes"); if (attrs.length === 1) return attrs[0]; @@ -136,10 +168,14 @@ export function combineTypeAttributes( return mapFilterMap(attributesByKind, combine); } -export function makeTypeAttributesInferred(attr: TypeAttributes): TypeAttributes { +export function makeTypeAttributesInferred( + attr: TypeAttributes, +): TypeAttributes { return mapFilterMap(attr, (value, kind) => kind.makeInferred(value)); } -export function increaseTypeAttributesDistance(attr: TypeAttributes): TypeAttributes { +export function increaseTypeAttributesDistance( + attr: TypeAttributes, +): TypeAttributes { return mapFilterMap(attr, (value, kind) => kind.increaseDistance(value)); } diff --git a/packages/quicktype-core/src/attributes/TypeNames.ts b/packages/quicktype-core/src/attributes/TypeNames.ts index c7225f3b7..dbc583c32 100644 --- a/packages/quicktype-core/src/attributes/TypeNames.ts +++ b/packages/quicktype-core/src/attributes/TypeNames.ts @@ -1,10 +1,17 @@ +import { + definedMap, + iterableFirst, + iterableSkip, + setMap, + setUnionInto, +} from "collection-utils"; import * as pluralize from "pluralize"; -import { setMap, iterableFirst, iterableSkip, setUnionInto, definedMap } from "collection-utils"; -import { panic, defined, assert } from "../support/Support"; -import { TypeAttributeKind, TypeAttributes } from "./TypeAttributes"; -import { splitIntoWords } from "../support/Strings"; import { Chance } from "../support/Chance"; +import { splitIntoWords } from "../support/Strings"; +import { assert, defined, panic } from "../support/Support"; + +import { TypeAttributeKind, type TypeAttributes } from "./TypeAttributes"; let chance: Chance; let usedRandomNames: Set; @@ -32,18 +39,19 @@ export type NameOrNames = string | TypeNames; // the names "aaa" and "aaaa" we have the common prefix "aaa" and the // common suffix "aaa", so we will produce the combined name "aaaaaa". function combineNames(names: ReadonlySet): string { - let originalFirst = iterableFirst(names); + const originalFirst = iterableFirst(names); if (originalFirst === undefined) { return panic("Named type has no names"); } + if (names.size === 1) { return originalFirst; } - const namesSet = setMap(names, s => + const namesSet = setMap(names, (s) => splitIntoWords(s) - .map(w => w.word.toLowerCase()) - .join("_") + .map((w) => w.word.toLowerCase()) + .join("_"), ); const first = defined(iterableFirst(namesSet)); if (namesSet.size === 1) { @@ -69,87 +77,110 @@ function combineNames(names: ReadonlySet): string { } } } + const prefix = prefixLength > 2 ? first.slice(0, prefixLength) : ""; - const suffix = suffixLength > 2 ? first.slice(first.length - suffixLength) : ""; + const suffix = + suffixLength > 2 ? first.slice(first.length - suffixLength) : ""; const combined = prefix + suffix; if (combined.length > 2) { return combined; } + return first; } export const tooManyNamesThreshold = 1000; export abstract class TypeNames { - static makeWithDistance( + public static makeWithDistance( names: ReadonlySet, alternativeNames: ReadonlySet | undefined, - distance: number + distance: number, ): TypeNames { if (names.size >= tooManyNamesThreshold) { return new TooManyTypeNames(distance); } - if (alternativeNames === undefined || alternativeNames.size > tooManyNamesThreshold) { + if ( + alternativeNames === undefined || + alternativeNames.size > tooManyNamesThreshold + ) { alternativeNames = undefined; } return new RegularTypeNames(names, alternativeNames, distance); } - static make( + public static make( names: ReadonlySet, alternativeNames: ReadonlySet | undefined, - areInferred: boolean + areInferred: boolean, ): TypeNames { - return TypeNames.makeWithDistance(names, alternativeNames, areInferred ? 1 : 0); + return TypeNames.makeWithDistance( + names, + alternativeNames, + areInferred ? 1 : 0, + ); } - constructor(readonly distance: number) {} + public constructor(public readonly distance: number) {} - get areInferred(): boolean { + public get areInferred(): boolean { return this.distance > 0; } - abstract get names(): ReadonlySet; - abstract get combinedName(): string; - abstract get proposedNames(): ReadonlySet; - - abstract add(namesArray: TypeNames[], startIndex?: number): TypeNames; - abstract clearInferred(): TypeNames; - abstract makeInferred(): TypeNames; - abstract singularize(): TypeNames; - abstract toString(): string; + public abstract get names(): ReadonlySet; + public abstract get combinedName(): string; + public abstract get proposedNames(): ReadonlySet; + + public abstract add( + namesArray: TypeNames[], + startIndex?: number, + ): TypeNames; + public abstract clearInferred(): TypeNames; + public abstract makeInferred(): TypeNames; + public abstract singularize(): TypeNames; + public abstract toString(): string; } export class RegularTypeNames extends TypeNames { - constructor( - readonly names: ReadonlySet, + public constructor( + public readonly names: ReadonlySet, private readonly _alternativeNames: ReadonlySet | undefined, - distance: number + distance: number, ) { super(distance); } - add(namesArray: TypeNames[], startIndex = 0): TypeNames { + public add(namesArray: TypeNames[], startIndex = 0): TypeNames { let newNames = new Set(this.names); let newDistance = this.distance; - let newAlternativeNames = definedMap(this._alternativeNames, s => new Set(s)); + let newAlternativeNames = definedMap( + this._alternativeNames, + (s) => new Set(s), + ); for (let i = startIndex; i < namesArray.length; i++) { const other = namesArray[i]; - if (other instanceof RegularTypeNames && other._alternativeNames !== undefined) { + if ( + other instanceof RegularTypeNames && + other._alternativeNames !== undefined + ) { if (newAlternativeNames === undefined) { newAlternativeNames = new Set(); } + setUnionInto(newAlternativeNames, other._alternativeNames); } if (other.distance > newDistance) continue; if (!(other instanceof RegularTypeNames)) { - assert(other instanceof TooManyTypeNames, "Unknown TypeNames instance"); + assert( + other instanceof TooManyTypeNames, + "Unknown TypeNames instance", + ); // The other one is at most our distance, so let it sort it out return other.add(namesArray, i + 1); } @@ -158,77 +189,99 @@ export class RegularTypeNames extends TypeNames { // The other one is closer, so take its names newNames = new Set(other.names); newDistance = other.distance; - newAlternativeNames = definedMap(other._alternativeNames, s => new Set(s)); + newAlternativeNames = definedMap( + other._alternativeNames, + (s) => new Set(s), + ); } else { // Same distance, merge them - assert(other.distance === newDistance, "This should be the only case left"); + assert( + other.distance === newDistance, + "This should be the only case left", + ); setUnionInto(newNames, other.names); } } - return TypeNames.makeWithDistance(newNames, newAlternativeNames, newDistance); + + return TypeNames.makeWithDistance( + newNames, + newAlternativeNames, + newDistance, + ); } - clearInferred(): TypeNames { + public clearInferred(): TypeNames { const newNames = this.areInferred ? new Set() : this.names; return TypeNames.makeWithDistance(newNames, new Set(), this.distance); } - get combinedName(): string { + public get combinedName(): string { return combineNames(this.names); } - get proposedNames(): ReadonlySet { + public get proposedNames(): ReadonlySet { const set = new Set([this.combinedName]); if (this._alternativeNames === undefined) { return set; } + setUnionInto(set, this._alternativeNames); return set; } - makeInferred(): TypeNames { - return TypeNames.makeWithDistance(this.names, this._alternativeNames, this.distance + 1); + public makeInferred(): TypeNames { + return TypeNames.makeWithDistance( + this.names, + this._alternativeNames, + this.distance + 1, + ); } - singularize(): TypeNames { + public singularize(): TypeNames { return TypeNames.makeWithDistance( setMap(this.names, pluralize.singular), - definedMap(this._alternativeNames, an => setMap(an, pluralize.singular)), - this.distance + 1 + definedMap(this._alternativeNames, (an) => + setMap(an, pluralize.singular), + ), + this.distance + 1, ); } - toString(): string { - const inferred = this.areInferred ? `distance ${this.distance}` : "given"; + public toString(): string { + const inferred = this.areInferred + ? `distance ${this.distance}` + : "given"; const names = `${inferred} ${Array.from(this.names).join(",")}`; if (this._alternativeNames === undefined) { return names; } + return `${names} (${Array.from(this._alternativeNames).join(",")})`; } } export class TooManyTypeNames extends TypeNames { - readonly names: ReadonlySet; + public readonly names: ReadonlySet; - constructor(distance: number, name?: string) { + public constructor(distance: number, name?: string) { super(distance); if (name === undefined) { name = makeRandomName(); } + this.names = new Set([name]); } - get combinedName(): string { + public get combinedName(): string { return defined(iterableFirst(this.names)); } - get proposedNames(): ReadonlySet { + public get proposedNames(): ReadonlySet { return this.names; } - add(namesArray: TypeNames[], startIndex = 0): TypeNames { + public add(namesArray: TypeNames[], startIndex = 0): TypeNames { if (!this.areInferred) return this; for (let i = startIndex; i < namesArray.length; i++) { @@ -241,72 +294,87 @@ export class TooManyTypeNames extends TypeNames { return this; } - clearInferred(): TypeNames { + public clearInferred(): TypeNames { if (!this.areInferred) { return this; } + return TypeNames.makeWithDistance(new Set(), new Set(), this.distance); } - makeInferred(): TypeNames { - return new TooManyTypeNames(this.distance + 1, iterableFirst(this.names)); + public makeInferred(): TypeNames { + return new TooManyTypeNames( + this.distance + 1, + iterableFirst(this.names), + ); } - singularize(): TypeNames { + public singularize(): TypeNames { return this; } - toString(): string { + public toString(): string { return `too many ${this.combinedName}`; } } class TypeNamesTypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("names"); } - combine(namesArray: TypeNames[]): TypeNames { + public combine(namesArray: TypeNames[]): TypeNames { assert(namesArray.length > 0, "Can't combine zero type names"); return namesArray[0].add(namesArray, 1); } - makeInferred(tn: TypeNames): TypeNames { + public makeInferred(tn: TypeNames): TypeNames { return tn.makeInferred(); } - increaseDistance(tn: TypeNames): TypeNames { + public increaseDistance(tn: TypeNames): TypeNames { return tn.makeInferred(); } - stringify(tn: TypeNames): string { + public stringify(tn: TypeNames): string { return tn.toString(); } } -export const namesTypeAttributeKind: TypeAttributeKind = new TypeNamesTypeAttributeKind(); +export const namesTypeAttributeKind: TypeAttributeKind = + new TypeNamesTypeAttributeKind(); export function modifyTypeNames( attributes: TypeAttributes, - modifier: (tn: TypeNames | undefined) => TypeNames | undefined + modifier: (tn: TypeNames | undefined) => TypeNames | undefined, ): TypeAttributes { return namesTypeAttributeKind.modifyInAttributes(attributes, modifier); } -export function singularizeTypeNames(attributes: TypeAttributes): TypeAttributes { - return modifyTypeNames(attributes, maybeNames => { +export function singularizeTypeNames( + attributes: TypeAttributes, +): TypeAttributes { + return modifyTypeNames(attributes, (maybeNames) => { if (maybeNames === undefined) return undefined; return maybeNames.singularize(); }); } -export function makeNamesTypeAttributes(nameOrNames: NameOrNames, areNamesInferred?: boolean): TypeAttributes { +export function makeNamesTypeAttributes( + nameOrNames: NameOrNames, + areNamesInferred?: boolean, +): TypeAttributes { let typeNames: TypeNames; if (typeof nameOrNames === "string") { - typeNames = TypeNames.make(new Set([nameOrNames]), new Set(), defined(areNamesInferred)); + typeNames = TypeNames.make( + new Set([nameOrNames]), + new Set(), + defined(areNamesInferred), + ); } else { typeNames = nameOrNames as TypeNames; } + return namesTypeAttributeKind.makeAttributes(typeNames); } diff --git a/packages/quicktype-core/src/attributes/URIAttributes.ts b/packages/quicktype-core/src/attributes/URIAttributes.ts index 1f779708b..29c6f917b 100644 --- a/packages/quicktype-core/src/attributes/URIAttributes.ts +++ b/packages/quicktype-core/src/attributes/URIAttributes.ts @@ -1,11 +1,20 @@ +import { setUnionManyInto } from "collection-utils"; import URI from "urijs"; -import { TypeAttributeKind, TypeAttributes, emptyTypeAttributes } from "./TypeAttributes"; -import { setUnionManyInto } from "collection-utils"; -import { JSONSchemaType, JSONSchemaAttributes, Ref } from "../input/JSONSchemaInput"; -import { JSONSchema } from "../input/JSONSchemaStore"; +import type { + JSONSchemaAttributes, + JSONSchemaType, + Ref, +} from "../input/JSONSchemaInput"; +import type { JSONSchema } from "../input/JSONSchemaStore"; import { checkArray, checkString } from "../support/Support"; -import { Type } from "../Type"; +import type { Type } from "../Type/Type"; + +import { + TypeAttributeKind, + type TypeAttributes, + emptyTypeAttributes, +} from "./TypeAttributes"; const protocolsSchemaProperty = "qt-uri-protocols"; const extensionsSchemaProperty = "qt-uri-extensions"; @@ -14,43 +23,52 @@ const extensionsSchemaProperty = "qt-uri-extensions"; type URIAttributes = [ReadonlySet, ReadonlySet]; class URITypeAttributeKind extends TypeAttributeKind { - constructor() { + public constructor() { super("uriAttributes"); } - get inIdentity(): boolean { + public get inIdentity(): boolean { return true; } - combine(attrs: URIAttributes[]): URIAttributes { - const protocolSets = attrs.map(a => a[0]); - const extensionSets = attrs.map(a => a[1]); - return [setUnionManyInto(new Set(), protocolSets), setUnionManyInto(new Set(), extensionSets)]; + public combine(attrs: URIAttributes[]): URIAttributes { + const protocolSets = attrs.map((a) => a[0]); + const extensionSets = attrs.map((a) => a[1]); + return [ + setUnionManyInto(new Set(), protocolSets), + setUnionManyInto(new Set(), extensionSets), + ]; } - makeInferred(_: URIAttributes): undefined { + public makeInferred(_: URIAttributes): undefined { return undefined; } - addToSchema(schema: { [name: string]: unknown }, t: Type, attrs: URIAttributes): void { + public addToSchema( + schema: { [name: string]: unknown }, + t: Type, + attrs: URIAttributes, + ): void { if (t.kind !== "string" && t.kind !== "uri") return; const [protocols, extensions] = attrs; if (protocols.size > 0) { schema[protocolsSchemaProperty] = Array.from(protocols).sort(); } + if (extensions.size > 0) { schema[extensionsSchemaProperty] = Array.from(extensions).sort(); } } } -export const uriTypeAttributeKind: TypeAttributeKind = new URITypeAttributeKind(); +export const uriTypeAttributeKind: TypeAttributeKind = + new URITypeAttributeKind(); const extensionRegex = /^.+(\.[^./\\]+)$/; function pathExtension(path: string): string | undefined { - const matches = path.match(extensionRegex); + const matches = extensionRegex.exec(path); if (matches === null) return undefined; return matches[1]; } @@ -59,8 +77,12 @@ export function uriInferenceAttributesProducer(s: string): TypeAttributes { try { const uri = URI(s); const extension = pathExtension(uri.path()); - const extensions = extension === undefined ? [] : [extension.toLowerCase()]; - return uriTypeAttributeKind.makeAttributes([new Set([uri.protocol().toLowerCase()]), new Set(extensions)]); + const extensions = + extension === undefined ? [] : [extension.toLowerCase()]; + return uriTypeAttributeKind.makeAttributes([ + new Set([uri.protocol().toLowerCase()]), + new Set(extensions), + ]); } catch { return emptyTypeAttributes; } @@ -69,7 +91,7 @@ export function uriInferenceAttributesProducer(s: string): TypeAttributes { export function uriSchemaAttributesProducer( schema: JSONSchema, _ref: Ref, - types: Set + types: Set, ): JSONSchemaAttributes | undefined { if (!(typeof schema === "object")) return undefined; if (!types.has("string")) return undefined; @@ -92,5 +114,7 @@ export function uriSchemaAttributesProducer( if (protocols.size === 0 && extensions.size === 0) return undefined; - return { forString: uriTypeAttributeKind.makeAttributes([protocols, extensions]) }; + return { + forString: uriTypeAttributeKind.makeAttributes([protocols, extensions]), + }; } diff --git a/packages/quicktype-core/src/index.ts b/packages/quicktype-core/src/index.ts index aa04f0857..840052701 100644 --- a/packages/quicktype-core/src/index.ts +++ b/packages/quicktype-core/src/index.ts @@ -1,35 +1,54 @@ export { - Options, - RendererOptions, + type Options, getTargetLanguage, quicktypeMultiFile, quicktypeMultiFileSync, quicktype, combineRenderResults, + type RunContext, +} from "./Run"; +export { inferenceFlags, inferenceFlagNames, defaultInferenceFlags, inferenceFlagsObject, - InferenceFlags, - InferenceFlagName, - RunContext -} from "./Run"; -export { CompressedJSON, Value } from "./input/CompressedJSON"; -export { Input, InputData, JSONInput, JSONSourceData, jsonInputForTargetLanguage } from "./input/Inputs"; -export { JSONSchemaInput, JSONSchemaSourceData } from "./input/JSONSchemaInput"; -export { Ref, JSONSchemaType, JSONSchemaAttributes } from "./input/JSONSchemaInput"; -export { RenderContext } from "./Renderer"; -export { Option, OptionDefinition, getOptionValues, OptionValues } from "./RendererOptions"; -export { TargetLanguage, MultiFileRenderResult } from "./TargetLanguage"; -export { all as defaultTargetLanguages, languageNamed } from "./language/All"; + type InferenceFlags, + type InferenceFlagName, +} from "./Inference"; +export { CompressedJSON, type Value } from "./input/CompressedJSON"; +export { + type Input, + InputData, + JSONInput, + type JSONSourceData, + jsonInputForTargetLanguage, +} from "./input/Inputs"; +export { + JSONSchemaInput, + type JSONSchemaSourceData, +} from "./input/JSONSchemaInput"; +export { + Ref, + type JSONSchemaType, + type JSONSchemaAttributes, +} from "./input/JSONSchemaInput"; +export type { RenderContext } from "./Renderer"; +export { + Option, + type OptionDefinition, + getOptionValues, + type OptionValues, +} from "./RendererOptions"; +export { TargetLanguage, type MultiFileRenderResult } from "./TargetLanguage"; + export { - MultiWord, - Sourcelike, - SerializedRenderResult, - Annotation, + type MultiWord, + type Sourcelike, + type SerializedRenderResult, + type Annotation, modifySource, singleWord, - parenIfNeeded + parenIfNeeded, } from "./Source"; export { Name, funPrefixNamer, Namer } from "./Naming"; export { IssueAnnotationData } from "./Annotation"; @@ -41,7 +60,7 @@ export { parseJSON, checkStringMap, checkArray, - inflateBase64 + inflateBase64, } from "./support/Support"; export { splitIntoWords, @@ -50,7 +69,7 @@ export { firstUpperWordStyle, allUpperWordStyle, legalizeCharacters, - isLetterOrDigit + isLetterOrDigit, } from "./support/Strings"; export { train as trainMarkovChain } from "./MarkovChain"; export { QuickTypeError, messageError, messageAssert } from "./Messages"; @@ -63,53 +82,38 @@ export { EnumType, MapType, UnionType, - TypeKind, ObjectType, - TransformedStringTypeKind, - PrimitiveStringTypeKind + type TypeKind, + type TransformedStringTypeKind, + type PrimitiveStringTypeKind, } from "./Type"; export { getStream } from "./input/io/get-stream"; + export { readableFromFileOrURL, readFromFileOrURL } from "./input/io/NodeIO"; + export { FetchingJSONSchemaStore } from "./input/FetchingJSONSchemaStore"; -export { JSONSchemaStore, JSONSchema } from "./input/JSONSchemaStore"; +export { JSONSchemaStore, type JSONSchema } from "./input/JSONSchemaStore"; export { sourcesFromPostmanCollection } from "./input/PostmanCollection"; -export { TypeBuilder, StringTypeMapping } from "./TypeBuilder"; -export { TypeRef, derefTypeRef } from "./TypeGraph"; -export { TypeAttributeKind, TypeAttributes, emptyTypeAttributes } from "./attributes/TypeAttributes"; -export { TypeNames, makeNamesTypeAttributes, namesTypeAttributeKind } from "./attributes/TypeNames"; +export { TypeBuilder } from "./Type/TypeBuilder"; +export type { StringTypeMapping } from "./Type/TypeBuilderUtils"; +export { type TypeRef, derefTypeRef } from "./Type/TypeRef"; +export { + TypeAttributeKind, + type TypeAttributes, + emptyTypeAttributes, +} from "./attributes/TypeAttributes"; +export { + TypeNames, + makeNamesTypeAttributes, + namesTypeAttributeKind, +} from "./attributes/TypeNames"; export { StringTypes } from "./attributes/StringTypes"; -export { removeNullFromUnion, matchType, nullableFromUnion } from "./TypeUtils"; +export { + removeNullFromUnion, + matchType, + nullableFromUnion, +} from "./Type/TypeUtils"; export { ConvenienceRenderer } from "./ConvenienceRenderer"; export { uriTypeAttributeKind } from "./attributes/URIAttributes"; -export { CJSONTargetLanguage, CJSONRenderer, cJSONOptions } from "./language/CJSON"; -export { CPlusPlusTargetLanguage, CPlusPlusRenderer, cPlusPlusOptions } from "./language/CPlusPlus"; -export { CSharpTargetLanguage, cSharpOptions, CSharpRenderer } from "./language/CSharp"; -export { PythonTargetLanguage, PythonRenderer, pythonOptions } from "./language/Python"; -export { GoTargetLanguage, GoRenderer, goOptions } from "./language/Golang"; -export { ObjectiveCTargetLanguage, ObjectiveCRenderer, objcOptions } from "./language/Objective-C"; -export { JavaTargetLanguage, JavaRenderer, javaOptions } from "./language/Java"; -export { JavaScriptTargetLanguage, JavaScriptRenderer, javaScriptOptions } from "./language/JavaScript"; -export { - JavaScriptPropTypesTargetLanguage, - JavaScriptPropTypesRenderer, - javaScriptPropTypesOptions -} from "./language/JavaScriptPropTypes"; -export { - TypeScriptTargetLanguage, - TypeScriptRenderer, - FlowTargetLanguage, - FlowRenderer, - tsFlowOptions -} from "./language/TypeScriptFlow"; -export { SwiftTargetLanguage, SwiftRenderer, swiftOptions } from "./language/Swift"; -export { KotlinTargetLanguage, KotlinRenderer, kotlinOptions } from "./language/Kotlin"; -export { Scala3TargetLanguage, Scala3Renderer, scala3Options } from "./language/Scala3"; -export { SmithyTargetLanguage, Smithy4sRenderer, SmithyOptions } from "./language/Smithy4s"; -export { ElmTargetLanguage, ElmRenderer, elmOptions } from "./language/Elm"; -export { JSONSchemaTargetLanguage, JSONSchemaRenderer } from "./language/JSONSchema"; -export { RustTargetLanguage, RustRenderer, rustOptions } from "./language/Rust"; -export { RubyTargetLanguage, RubyRenderer, rubyOptions } from "./language/ruby"; -export { CrystalTargetLanguage, CrystalRenderer } from "./language/Crystal"; -export { HaskellTargetLanguage, HaskellRenderer, haskellOptions } from "./language/Haskell"; -export { DartTargetLanguage, DartRenderer, dartOptions } from "./language/Dart"; +export * from "./language"; diff --git a/packages/quicktype-core/src/input/CompressedJSON.ts b/packages/quicktype-core/src/input/CompressedJSON.ts index 2bdb2cc85..40f9d9a49 100644 --- a/packages/quicktype-core/src/input/CompressedJSON.ts +++ b/packages/quicktype-core/src/input/CompressedJSON.ts @@ -1,22 +1,26 @@ import { addHashCode, hashCodeInit, hashString } from "collection-utils"; -import { defined, panic, assert } from "../support/Support"; -import { TransformedStringTypeKind, isPrimitiveStringTypeKind, transformedStringTypeTargetTypeKindsMap } from "../Type"; -import { DateTimeRecognizer } from "../DateTime"; import { inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; +import type { DateTimeRecognizer } from "../DateTime"; +import { assert, defined, panic } from "../support/Support"; +import { + type TransformedStringTypeKind, + isPrimitiveStringTypeKind, + transformedStringTypeTargetTypeKindsMap, +} from "../Type"; export enum Tag { - Null, - False, - True, - Integer, - Double, - InternedString, - UninternedString, - Object, - Array, - StringFormat, - TransformedString + Null = 1, + False = 2, + True = 3, + Integer = 4, + Double = 5, + InternedString = 6, + UninternedString = 7, + Object = 8, + Array = 9, + StringFormat = 10, + TransformedString = 11, } export type Value = number; @@ -29,7 +33,10 @@ export function makeValue(t: Tag, index: number): Value { } function getIndex(v: Value, tag: Tag): number { - assert(valueTag(v) === tag, "Trying to get index for value with invalid tag"); + assert( + valueTag(v) === tag, + "Trying to get index for value with invalid tag", + ); return v >> TAG_BITS; } @@ -37,51 +44,59 @@ export function valueTag(v: Value): Tag { return v & TAG_MASK; } -type Context = { - currentObject: Value[] | undefined; +interface Context { currentArray: Value[] | undefined; currentKey: string | undefined; currentNumberIsDouble: boolean; -}; + currentObject: Value[] | undefined; +} export abstract class CompressedJSON { private _rootValue: Value | undefined; private _ctx: Context | undefined; + private _contextStack: Context[] = []; private _strings: string[] = []; + private _stringIndexes: { [str: string]: number } = {}; + private _objects: Value[][] = []; + private _arrays: Value[][] = []; - constructor(readonly dateTimeRecognizer: DateTimeRecognizer, readonly handleRefs: boolean) {} + public constructor( + public readonly dateTimeRecognizer: DateTimeRecognizer, + public readonly handleRefs: boolean, + ) {} - abstract parse(input: T): Promise; + public abstract parse(input: T): Promise; - parseSync(_input: T): Value { + public parseSync(_input: T): Value { return panic("parseSync not implemented in CompressedJSON"); } - getStringForValue(v: Value): string { + public getStringForValue(v: Value): string { const tag = valueTag(v); assert(tag === Tag.InternedString || tag === Tag.TransformedString); return this._strings[getIndex(v, tag)]; } - getObjectForValue = (v: Value): Value[] => { + public getObjectForValue = (v: Value): Value[] => { return this._objects[getIndex(v, Tag.Object)]; }; - getArrayForValue = (v: Value): Value[] => { + public getArrayForValue = (v: Value): Value[] => { return this._arrays[getIndex(v, Tag.Array)]; }; - getStringFormatTypeKind(v: Value): TransformedStringTypeKind { + public getStringFormatTypeKind(v: Value): TransformedStringTypeKind { const kind = this._strings[getIndex(v, Tag.StringFormat)]; if (!isPrimitiveStringTypeKind(kind) || kind === "string") { return panic("Not a transformed string type kind"); } + return kind; } @@ -93,6 +108,7 @@ export abstract class CompressedJSON { if (Object.prototype.hasOwnProperty.call(this._stringIndexes, s)) { return this._stringIndexes[s]; } + const index = this._strings.length; this._strings.push(s); this._stringIndexes[s] = index; @@ -101,7 +117,10 @@ export abstract class CompressedJSON { protected makeString(s: string): Value { const value = makeValue(Tag.InternedString, this.internString(s)); - assert(typeof value === "number", `Interned string value is not a number: ${value}`); + assert( + typeof value === "number", + `Interned string value is not a number: ${value}`, + ); return value; } @@ -122,18 +141,27 @@ export abstract class CompressedJSON { } protected commitValue(value: Value): void { - assert(typeof value === "number", `CompressedJSON value is not a number: ${value}`); + assert( + typeof value === "number", + `CompressedJSON value is not a number: ${value}`, + ); if (this._ctx === undefined) { assert( this._rootValue === undefined, - "Committing value but nowhere to commit to - root value still there." + "Committing value but nowhere to commit to - root value still there.", ); this._rootValue = value; } else if (this._ctx.currentObject !== undefined) { if (this._ctx.currentKey === undefined) { - return panic("Must have key and can't have string when committing"); + return panic( + "Must have key and can't have string when committing", + ); } - this._ctx.currentObject.push(this.makeString(this._ctx.currentKey), value); + + this._ctx.currentObject.push( + this.makeString(this._ctx.currentKey), + value, + ); this._ctx.currentKey = undefined; } else if (this._ctx.currentArray !== undefined) { this._ctx.currentArray.push(value); @@ -160,12 +188,24 @@ export abstract class CompressedJSON { if (this.handleRefs && this.isExpectingRef) { value = this.makeString(s); } else { - const format = inferTransformedStringTypeKindForString(s, this.dateTimeRecognizer); + const format = inferTransformedStringTypeKindForString( + s, + this.dateTimeRecognizer, + ); if (format !== undefined) { - if (defined(transformedStringTypeTargetTypeKindsMap.get(format)).attributesProducer !== undefined) { - value = makeValue(Tag.TransformedString, this.internString(s)); + if ( + defined(transformedStringTypeTargetTypeKindsMap.get(format)) + .attributesProducer !== undefined + ) { + value = makeValue( + Tag.TransformedString, + this.internString(s), + ); } else { - value = makeValue(Tag.StringFormat, this.internString(format)); + value = makeValue( + Tag.StringFormat, + this.internString(format), + ); } } else if (s.length <= 64) { value = this.makeString(s); @@ -173,6 +213,7 @@ export abstract class CompressedJSON { value = makeValue(Tag.UninternedString, 0); } } + this.commitValue(value); } @@ -181,7 +222,11 @@ export abstract class CompressedJSON { if (value === undefined) { return panic("Finished without root document"); } - assert(this._ctx === undefined && this._contextStack.length === 0, "Finished with contexts present"); + + assert( + this._ctx === undefined && this._contextStack.length === 0, + "Finished with contexts present", + ); this._rootValue = undefined; return value; } @@ -190,11 +235,12 @@ export abstract class CompressedJSON { if (this._ctx !== undefined) { this._contextStack.push(this._ctx); } + this._ctx = { currentObject: undefined, currentArray: undefined, currentKey: undefined, - currentNumberIsDouble: false + currentNumberIsDouble: false, }; } @@ -213,6 +259,7 @@ export abstract class CompressedJSON { if (obj === undefined) { return panic("Object ended but not started"); } + this.popContext(); this.commitValue(this.internObject(obj)); } @@ -227,6 +274,7 @@ export abstract class CompressedJSON { if (arr === undefined) { return panic("Array ended but not started"); } + this.popContext(); this.commitValue(this.internArray(arr)); } @@ -236,19 +284,24 @@ export abstract class CompressedJSON { this._ctx = this._contextStack.pop(); } - equals(other: any): boolean { + public equals(other: CompressedJSON): boolean { return this === other; } - hashCode(): number { + public hashCode(): number { let hashAccumulator = hashCodeInit; for (const s of this._strings) { hashAccumulator = addHashCode(hashAccumulator, hashString(s)); } - for (const s of Object.getOwnPropertyNames(this._stringIndexes).sort()) { + for (const s of Object.getOwnPropertyNames( + this._stringIndexes, + ).sort()) { hashAccumulator = addHashCode(hashAccumulator, hashString(s)); - hashAccumulator = addHashCode(hashAccumulator, this._stringIndexes[s]); + hashAccumulator = addHashCode( + hashAccumulator, + this._stringIndexes[s], + ); } for (const o of this._objects) { @@ -256,6 +309,7 @@ export abstract class CompressedJSON { hashAccumulator = addHashCode(hashAccumulator, v); } } + for (const o of this._arrays) { for (const v of o) { hashAccumulator = addHashCode(hashAccumulator, v); @@ -267,11 +321,11 @@ export abstract class CompressedJSON { } export class CompressedJSONFromString extends CompressedJSON { - async parse(input: string): Promise { + public async parse(input: string): Promise { return this.parseSync(input); } - parseSync(input: string): Value { + public parseSync(input: string): Value { const json = JSON.parse(input); this.process(json); return this.finish(); @@ -286,20 +340,24 @@ export class CompressedJSONFromString extends CompressedJSON { this.commitString(json); } else if (typeof json === "number") { const isDouble = - json !== Math.floor(json) || json < Number.MIN_SAFE_INTEGER || json > Number.MAX_SAFE_INTEGER; + json !== Math.floor(json) || + json < Number.MIN_SAFE_INTEGER || + json > Number.MAX_SAFE_INTEGER; this.commitNumber(isDouble); } else if (Array.isArray(json)) { this.pushArrayContext(); for (const v of json) { this.process(v); } + this.finishArray(); } else if (typeof json === "object") { this.pushObjectContext(); for (const key of Object.getOwnPropertyNames(json)) { this.setPropertyKey(key); - this.process((json as any)[key]); + this.process(json[key as keyof typeof json]); } + this.finishObject(); } else { return panic("Invalid JSON object"); diff --git a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts index 08c6e0526..ab0c6afa0 100644 --- a/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/FetchingJSONSchemaStore.ts @@ -1,14 +1,19 @@ -import { JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; -import { parseJSON } from ".."; +import { parseJSON } from "../support/Support"; + import { readFromFileOrURL } from "./io/NodeIO"; +import { type JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; export class FetchingJSONSchemaStore extends JSONSchemaStore { - constructor(private readonly _httpHeaders?: string[]) { + public constructor(private readonly _httpHeaders?: string[]) { super(); } - async fetch(address: string): Promise { + public async fetch(address: string): Promise { // console.log(`Fetching ${address}`); - return parseJSON(await readFromFileOrURL(address, this._httpHeaders), "JSON Schema", address); + return parseJSON( + await readFromFileOrURL(address, this._httpHeaders), + "JSON Schema", + address, + ); } } diff --git a/packages/quicktype-core/src/input/Inference.ts b/packages/quicktype-core/src/input/Inference.ts index 9fdcea588..4c3154623 100644 --- a/packages/quicktype-core/src/input/Inference.ts +++ b/packages/quicktype-core/src/input/Inference.ts @@ -1,30 +1,48 @@ -import { Value, Tag, valueTag, CompressedJSON } from "./CompressedJSON"; -import { assertNever, defined, panic, assert } from "../support/Support"; -import { TypeBuilder } from "../TypeBuilder"; -import { UnionBuilder, UnionAccumulator } from "../UnionBuilder"; import { - ClassProperty, - transformedStringTypeTargetTypeKindsMap, - UnionType, + StringTypes, + inferTransformedStringTypeKindForString, +} from "../attributes/StringTypes"; +import { + type TypeAttributes, + emptyTypeAttributes, +} from "../attributes/TypeAttributes"; +import { messageError } from "../Messages"; +import { assert, assertNever, defined, panic } from "../support/Support"; +import { + ArrayType, + type ClassProperty, ClassType, MapType, - ArrayType + UnionType, + transformedStringTypeTargetTypeKindsMap, } from "../Type"; -import { TypeAttributes, emptyTypeAttributes } from "../attributes/TypeAttributes"; -import { StringTypes, inferTransformedStringTypeKindForString } from "../attributes/StringTypes"; -import { TypeRef, derefTypeRef } from "../TypeGraph"; -import { messageError } from "../Messages"; -import { nullableFromUnion } from "../TypeUtils"; +import type { TypeBuilder } from "../Type/TypeBuilder"; +import { type TypeRef, derefTypeRef } from "../Type/TypeRef"; +import { nullableFromUnion } from "../Type/TypeUtils"; +import { UnionAccumulator, UnionBuilder } from "../UnionBuilder"; + +import { + type CompressedJSON, + Tag, + type Value, + valueTag, +} from "./CompressedJSON"; // This should be the recursive type // Value[] | NestedValueArray[] // but TypeScript doesn't support that. +// FIXME: reactor this +// eslint-disable-next-line @typescript-eslint/no-explicit-any export type NestedValueArray = any; -function forEachArrayInNestedValueArray(va: NestedValueArray, f: (va: Value[]) => void): void { +function forEachArrayInNestedValueArray( + va: NestedValueArray, + f: (va: Value[]) => void, +): void { if (va.length === 0) { return; } + if (Array.isArray(va[0])) { for (const x of va) { forEachArrayInNestedValueArray(x, f); @@ -34,19 +52,26 @@ function forEachArrayInNestedValueArray(va: NestedValueArray, f: (va: Value[]) = } } -function forEachValueInNestedValueArray(va: NestedValueArray, f: (v: Value) => void): void { - forEachArrayInNestedValueArray(va, a => { +function forEachValueInNestedValueArray( + va: NestedValueArray, + f: (v: Value) => void, +): void { + forEachArrayInNestedValueArray(va, (a) => { for (const x of a) { f(x); } }); } -class InferenceUnionBuilder extends UnionBuilder { - constructor( +class InferenceUnionBuilder extends UnionBuilder< + TypeBuilder, + NestedValueArray, + NestedValueArray +> { + public constructor( typeBuilder: TypeBuilder, private readonly _typeInference: TypeInference, - private readonly _fixed: boolean + private readonly _fixed: boolean, ) { super(typeBuilder); } @@ -54,19 +79,29 @@ class InferenceUnionBuilder extends UnionBuilder; export class TypeInference { - private _refIntersections: [TypeRef, string[]][] | undefined; + private _refIntersections: Array<[TypeRef, string[]]> | undefined; - constructor( + public constructor( private readonly _cjson: CompressedJSON, private readonly _typeBuilder: TypeBuilder, private readonly _inferMaps: boolean, - private readonly _inferEnums: boolean + private readonly _inferEnums: boolean, ) {} - addValuesToAccumulator(valueArray: NestedValueArray, accumulator: Accumulator): void { - forEachValueInNestedValueArray(valueArray, value => { + private addValuesToAccumulator( + valueArray: NestedValueArray, + accumulator: Accumulator, + ): void { + forEachValueInNestedValueArray(valueArray, (value) => { const t = valueTag(value); switch (t) { case Tag.Null: @@ -108,65 +146,105 @@ export class TypeInference { if (this._inferEnums) { const s = this._cjson.getStringForValue(value); if (canBeEnumCase(s)) { - accumulator.addStringCase(s, 1, emptyTypeAttributes); + accumulator.addStringCase( + s, + 1, + emptyTypeAttributes, + ); } else { - accumulator.addStringType("string", emptyTypeAttributes); + accumulator.addStringType( + "string", + emptyTypeAttributes, + ); } } else { - accumulator.addStringType("string", emptyTypeAttributes); + accumulator.addStringType( + "string", + emptyTypeAttributes, + ); } + break; case Tag.UninternedString: accumulator.addStringType("string", emptyTypeAttributes); break; case Tag.Object: - accumulator.addObject(this._cjson.getObjectForValue(value), emptyTypeAttributes); + accumulator.addObject( + this._cjson.getObjectForValue(value), + emptyTypeAttributes, + ); break; case Tag.Array: - accumulator.addArray(this._cjson.getArrayForValue(value), emptyTypeAttributes); + accumulator.addArray( + this._cjson.getArrayForValue(value), + emptyTypeAttributes, + ); break; case Tag.StringFormat: { const kind = this._cjson.getStringFormatTypeKind(value); accumulator.addStringType( "string", emptyTypeAttributes, - new StringTypes(new Map(), new Set([kind])) + new StringTypes(new Map(), new Set([kind])), ); break; } + case Tag.TransformedString: { const s = this._cjson.getStringForValue(value); - const kind = inferTransformedStringTypeKindForString(s, this._cjson.dateTimeRecognizer); + const kind = inferTransformedStringTypeKindForString( + s, + this._cjson.dateTimeRecognizer, + ); if (kind === undefined) { return panic("TransformedString does not have a kind"); } - const producer = defined(transformedStringTypeTargetTypeKindsMap.get(kind)).attributesProducer; + + const producer = defined( + transformedStringTypeTargetTypeKindsMap.get(kind), + ).attributesProducer; if (producer === undefined) { - return panic("TransformedString does not have attribute producer"); + return panic( + "TransformedString does not have attribute producer", + ); } - accumulator.addStringType("string", producer(s), new StringTypes(new Map(), new Set([kind]))); + + accumulator.addStringType( + "string", + producer(s), + new StringTypes(new Map(), new Set([kind])), + ); break; } + default: return assertNever(t); } }); } - inferType( + public inferType( typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const accumulator = this.accumulatorForArray(valueArray); - return this.makeTypeFromAccumulator(accumulator, typeAttributes, fixed, forwardingRef); + return this.makeTypeFromAccumulator( + accumulator, + typeAttributes, + fixed, + forwardingRef, + ); } private resolveRef(ref: string, topLevel: TypeRef): TypeRef { if (!ref.startsWith("#/")) { - return messageError("InferenceJSONReferenceNotRooted", { reference: ref }); + return messageError("InferenceJSONReferenceNotRooted", { + reference: ref, + }); } + const parts = ref.split("/").slice(1); const graph = this._typeBuilder.typeGraph; let tref = topLevel; @@ -176,102 +254,164 @@ export class TypeInference { const nullable = nullableFromUnion(t); if (nullable === null) { // FIXME: handle unions - return messageError("InferenceJSONReferenceToUnion", { reference: ref }); + return messageError("InferenceJSONReferenceToUnion", { + reference: ref, + }); } + t = nullable; } + if (t instanceof ClassType) { const cp = t.getProperties().get(part); if (cp === undefined) { - return messageError("InferenceJSONReferenceWrongProperty", { reference: ref }); + return messageError("InferenceJSONReferenceWrongProperty", { + reference: ref, + }); } + tref = cp.typeRef; } else if (t instanceof MapType) { tref = t.values.typeRef; } else if (t instanceof ArrayType) { - if (part.match("^[0-9]+$") === null) { - return messageError("InferenceJSONReferenceInvalidArrayIndex", { reference: ref }); + if (/^[0-9]+$/.exec(part) === null) { + return messageError( + "InferenceJSONReferenceInvalidArrayIndex", + { reference: ref }, + ); } + tref = t.items.typeRef; } else { - return messageError("InferenceJSONReferenceWrongProperty", { reference: ref }); + return messageError("InferenceJSONReferenceWrongProperty", { + reference: ref, + }); } } + return tref; } - inferTopLevelType(typeAttributes: TypeAttributes, valueArray: NestedValueArray, fixed: boolean): TypeRef { - assert(this._refIntersections === undefined, "Didn't reset ref intersections - nested invocations?"); + public inferTopLevelType( + typeAttributes: TypeAttributes, + valueArray: NestedValueArray, + fixed: boolean, + ): TypeRef { + assert( + this._refIntersections === undefined, + "Didn't reset ref intersections - nested invocations?", + ); if (this._cjson.handleRefs) { this._refIntersections = []; } + const topLevel = this.inferType(typeAttributes, valueArray, fixed); if (this._cjson.handleRefs) { for (const [tref, refs] of defined(this._refIntersections)) { - const resolved = refs.map(r => this.resolveRef(r, topLevel)); - this._typeBuilder.setSetOperationMembers(tref, new Set(resolved)); + const resolved = refs.map((r) => this.resolveRef(r, topLevel)); + this._typeBuilder.setSetOperationMembers( + tref, + new Set(resolved), + ); } this._refIntersections = undefined; } + return topLevel; } - accumulatorForArray(valueArray: NestedValueArray): Accumulator { - const accumulator = new UnionAccumulator(true); + private accumulatorForArray(valueArray: NestedValueArray): Accumulator { + const accumulator = new UnionAccumulator< + NestedValueArray, + NestedValueArray + >(true); this.addValuesToAccumulator(valueArray, accumulator); return accumulator; } - makeTypeFromAccumulator( + private makeTypeFromAccumulator( accumulator: Accumulator, typeAttributes: TypeAttributes, fixed: boolean, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { - const unionBuilder = new InferenceUnionBuilder(this._typeBuilder, this, fixed); - return unionBuilder.buildUnion(accumulator, false, typeAttributes, forwardingRef); + const unionBuilder = new InferenceUnionBuilder( + this._typeBuilder, + this, + fixed, + ); + return unionBuilder.buildUnion( + accumulator, + false, + typeAttributes, + forwardingRef, + ); } - inferClassType( + public inferClassType( typeAttributes: TypeAttributes, objects: NestedValueArray, fixed: boolean, - forwardingRef?: TypeRef + forwardingRef?: TypeRef, ): TypeRef { const propertyNames: string[] = []; const propertyValues: { [name: string]: Value[] } = {}; - forEachArrayInNestedValueArray(objects, arr => { + forEachArrayInNestedValueArray(objects, (arr) => { for (let i = 0; i < arr.length; i += 2) { const key = this._cjson.getStringForValue(arr[i]); const value = arr[i + 1]; - if (!Object.prototype.hasOwnProperty.call(propertyValues, key)) { + if ( + !Object.prototype.hasOwnProperty.call(propertyValues, key) + ) { propertyNames.push(key); propertyValues[key] = []; } + propertyValues[key].push(value); } }); - if (this._cjson.handleRefs && propertyNames.length === 1 && propertyNames[0] === "$ref") { - const values = propertyValues["$ref"]; - if (values.every(v => valueTag(v) === Tag.InternedString)) { - const allRefs = values.map(v => this._cjson.getStringForValue(v)); + if ( + this._cjson.handleRefs && + propertyNames.length === 1 && + propertyNames[0] === "$ref" + ) { + const values = propertyValues.$ref; + if (values.every((v) => valueTag(v) === Tag.InternedString)) { + const allRefs = values.map((v) => + this._cjson.getStringForValue(v), + ); // FIXME: Add is-ref attribute - const tref = this._typeBuilder.getUniqueIntersectionType(typeAttributes, undefined); + const tref = this._typeBuilder.getUniqueIntersectionType( + typeAttributes, + undefined, + ); defined(this._refIntersections).push([tref, allRefs]); return tref; } } if (this._inferMaps && propertyNames.length > 500) { - const accumulator = new UnionAccumulator(true); + const accumulator = new UnionAccumulator< + NestedValueArray, + NestedValueArray + >(true); for (const key of propertyNames) { this.addValuesToAccumulator(propertyValues[key], accumulator); } - const values = this.makeTypeFromAccumulator(accumulator, emptyTypeAttributes, fixed); - return this._typeBuilder.getMapType(typeAttributes, values, forwardingRef); + + const values = this.makeTypeFromAccumulator( + accumulator, + emptyTypeAttributes, + fixed, + ); + return this._typeBuilder.getMapType( + typeAttributes, + values, + forwardingRef, + ); } const properties = new Map(); @@ -279,13 +419,25 @@ export class TypeInference { const values = propertyValues[key]; const t = this.inferType(emptyTypeAttributes, values, false); const isOptional = values.length < objects.length; - properties.set(key, this._typeBuilder.makeClassProperty(t, isOptional)); + properties.set( + key, + this._typeBuilder.makeClassProperty(t, isOptional), + ); } if (fixed) { - return this._typeBuilder.getUniqueClassType(typeAttributes, true, properties, forwardingRef); - } else { - return this._typeBuilder.getClassType(typeAttributes, properties, forwardingRef); + return this._typeBuilder.getUniqueClassType( + typeAttributes, + true, + properties, + forwardingRef, + ); } + + return this._typeBuilder.getClassType( + typeAttributes, + properties, + forwardingRef, + ); } } diff --git a/packages/quicktype-core/src/input/Inputs.ts b/packages/quicktype-core/src/input/Inputs.ts index 3baefd9c5..080924332 100644 --- a/packages/quicktype-core/src/input/Inputs.ts +++ b/packages/quicktype-core/src/input/Inputs.ts @@ -1,67 +1,88 @@ -import { iterableFirst, iterableFind, iterableSome, setFilterMap, withDefault, arrayMapSync } from "collection-utils"; +import { + arrayMapSync, + iterableFind, + iterableFirst, + iterableSome, + setFilterMap, + withDefault, +} from "collection-utils"; -import { Value, CompressedJSON, CompressedJSONFromString } from "./CompressedJSON"; -import { panic, errorMessage, defined } from "../support/Support"; -import { messageError } from "../Messages"; -import { TypeBuilder } from "../TypeBuilder"; -import { makeNamesTypeAttributes } from "../attributes/TypeNames"; import { descriptionTypeAttributeKind } from "../attributes/Description"; -import { TypeInference } from "./Inference"; -import { TargetLanguage } from "../TargetLanguage"; -import { RunContext } from "../Run"; +import { makeNamesTypeAttributes } from "../attributes/TypeNames"; import { languageNamed } from "../language/All"; +import { messageError } from "../Messages"; +import type { RunContext } from "../Run"; +import { defined, errorMessage, panic } from "../support/Support"; +import type { TargetLanguage } from "../TargetLanguage"; +import type { TypeBuilder } from "../Type/TypeBuilder"; +import type { LanguageName } from "../types"; -export interface Input { - readonly kind: string; - readonly needIR: boolean; - readonly needSchemaProcessing: boolean; - - addSource(source: T): Promise; - addSourceSync(source: T): void; - - singleStringSchemaSource(): string | undefined; +import { + type CompressedJSON, + CompressedJSONFromString, + type Value, +} from "./CompressedJSON"; +import { TypeInference } from "./Inference"; - addTypes( +export interface Input { + addSource: (source: T) => Promise; + addSourceSync: (source: T) => void; + addTypes: ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean - ): Promise; - addTypesSync( + fixedTopLevels: boolean, + ) => Promise; + + addTypesSync: ( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean - ): void; + fixedTopLevels: boolean, + ) => void; + readonly kind: string; + + readonly needIR: boolean; + + readonly needSchemaProcessing: boolean; + singleStringSchemaSource: () => string | undefined; } -type JSONTopLevel = { samples: Value[]; description: string | undefined }; +interface JSONTopLevel { + description: string | undefined; + samples: Value[]; +} export interface JSONSourceData { + description?: string; name: string; samples: T[]; - description?: string; } -function messageParseError(name: string, description: string | undefined, e: unknown): never { +function messageParseError( + name: string, + description: string | undefined, + e: unknown, +): never { return messageError("MiscJSONParseError", { description: withDefault(description, "input"), address: name, - message: errorMessage(e) + message: errorMessage(e), }); } export class JSONInput implements Input> { - readonly kind: string = "json"; - readonly needIR: boolean = true; - readonly needSchemaProcessing: boolean = false; + public readonly kind: string = "json"; + + public readonly needIR: boolean = true; + + public readonly needSchemaProcessing: boolean = false; private readonly _topLevels: Map = new Map(); - /* tslint:disable:no-unused-variable */ - constructor(private readonly _compressedJSON: CompressedJSON) {} + public constructor(private readonly _compressedJSON: CompressedJSON) {} private addSample(topLevelName: string, sample: Value): void { let topLevel = this._topLevels.get(topLevelName); @@ -69,18 +90,26 @@ export class JSONInput implements Input> { topLevel = { samples: [], description: undefined }; this._topLevels.set(topLevelName, topLevel); } + topLevel.samples.push(sample); } private setDescription(topLevelName: string, description: string): void { - let topLevel = this._topLevels.get(topLevelName); + const topLevel = this._topLevels.get(topLevelName); if (topLevel === undefined) { - return panic("Trying to set description for a top-level that doesn't exist"); + panic( + "Trying to set description for a top-level that doesn't exist", + ); } + topLevel.description = description; } - private addSamples(name: string, values: Value[], description: string | undefined): void { + private addSamples( + name: string, + values: Value[], + description: string | undefined, + ): void { for (const value of values) { this.addSample(name, value); if (description !== undefined) { @@ -89,54 +118,76 @@ export class JSONInput implements Input> { } } - async addSource(source: JSONSourceData): Promise { + public async addSource(source: JSONSourceData): Promise { const { name, samples, description } = source; try { - const values = await arrayMapSync(samples, async s => await this._compressedJSON.parse(s)); + const values = await arrayMapSync( + samples, + async (s) => await this._compressedJSON.parse(s), + ); this.addSamples(name, values, description); } catch (e) { return messageParseError(name, description, e); } } - addSourceSync(source: JSONSourceData): void { + public addSourceSync(source: JSONSourceData): void { const { name, samples, description } = source; try { - const values = samples.map(s => this._compressedJSON.parseSync(s)); + const values = samples.map((s) => + this._compressedJSON.parseSync(s), + ); this.addSamples(name, values, description); } catch (e) { - return messageParseError(name, description, e); + messageParseError(name, description, e); } } - singleStringSchemaSource(): undefined { + public singleStringSchemaSource(): undefined { return undefined; } - async addTypes( + public async addTypes( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): Promise { - return this.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); + this.addTypesSync( + ctx, + typeBuilder, + inferMaps, + inferEnums, + fixedTopLevels, + ); } - addTypesSync( + public addTypesSync( _ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): void { - const inference = new TypeInference(this._compressedJSON, typeBuilder, inferMaps, inferEnums); + const inference = new TypeInference( + this._compressedJSON, + typeBuilder, + inferMaps, + inferEnums, + ); for (const [name, { samples, description }] of this._topLevels) { - const tref = inference.inferTopLevelType(makeNamesTypeAttributes(name, false), samples, fixedTopLevels); + const tref = inference.inferTopLevelType( + makeNamesTypeAttributes(name, false), + samples, + fixedTopLevels, + ); typeBuilder.addTopLevel(name, tref); if (description !== undefined) { - const attributes = descriptionTypeAttributeKind.makeAttributes(new Set([description])); + const attributes = descriptionTypeAttributeKind.makeAttributes( + new Set([description]), + ); typeBuilder.addAttributes(tref, attributes); } } @@ -144,81 +195,118 @@ export class JSONInput implements Input> { } export function jsonInputForTargetLanguage( - targetLanguage: string | TargetLanguage, + targetLanguage: LanguageName | TargetLanguage, languages?: TargetLanguage[], - handleJSONRefs = false + handleJSONRefs = false, ): JSONInput { if (typeof targetLanguage === "string") { targetLanguage = defined(languageNamed(targetLanguage, languages)); } - const compressedJSON = new CompressedJSONFromString(targetLanguage.dateTimeRecognizer, handleJSONRefs); + + const compressedJSON = new CompressedJSONFromString( + targetLanguage.dateTimeRecognizer, + handleJSONRefs, + ); return new JSONInput(compressedJSON); } export class InputData { // FIXME: Make into a Map, indexed by kind. + // biome-ignore lint/suspicious/noExplicitAny: private _inputs: Set> = new Set(); - addInput(input: Input): void { + public addInput(input: Input): void { this._inputs = this._inputs.add(input); } - private getOrAddInput(kind: string, makeInput: () => Input): Input { - let input: Input | undefined = iterableFind(this._inputs, i => i.kind === kind); + private getOrAddInput( + kind: string, + makeInput: () => Input, + ): Input { + let input: Input | undefined = iterableFind( + this._inputs, + (i) => i.kind === kind, + ); if (input === undefined) { input = makeInput(); this.addInput(input); } + return input; } - async addSource(kind: string, source: T, makeInput: () => Input): Promise { + public async addSource( + kind: string, + source: T, + makeInput: () => Input, + ): Promise { const input = this.getOrAddInput(kind, makeInput); await input.addSource(source); } - addSourceSync(kind: string, source: T, makeInput: () => Input): void { + public addSourceSync( + kind: string, + source: T, + makeInput: () => Input, + ): void { const input = this.getOrAddInput(kind, makeInput); input.addSourceSync(source); } - async addTypes( + public async addTypes( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): Promise { for (const input of this._inputs) { - await input.addTypes(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); + await input.addTypes( + ctx, + typeBuilder, + inferMaps, + inferEnums, + fixedTopLevels, + ); } } - addTypesSync( + public addTypesSync( ctx: RunContext, typeBuilder: TypeBuilder, inferMaps: boolean, inferEnums: boolean, - fixedTopLevels: boolean + fixedTopLevels: boolean, ): void { for (const input of this._inputs) { - input.addTypesSync(ctx, typeBuilder, inferMaps, inferEnums, fixedTopLevels); + input.addTypesSync( + ctx, + typeBuilder, + inferMaps, + inferEnums, + fixedTopLevels, + ); } } - get needIR(): boolean { - return iterableSome(this._inputs, i => i.needIR); + public get needIR(): boolean { + return iterableSome(this._inputs, (i) => i.needIR); } - get needSchemaProcessing(): boolean { - return iterableSome(this._inputs, i => i.needSchemaProcessing); + public get needSchemaProcessing(): boolean { + return iterableSome(this._inputs, (i) => i.needSchemaProcessing); } - singleStringSchemaSource(): string | undefined { - const schemaStrings = setFilterMap(this._inputs, i => i.singleStringSchemaSource()); + public singleStringSchemaSource(): string | undefined { + const schemaStrings = setFilterMap(this._inputs, (i) => + i.singleStringSchemaSource(), + ); if (schemaStrings.size > 1) { - return panic("We have more than one input with a string schema source"); + return panic( + "We have more than one input with a string schema source", + ); } + return iterableFirst(schemaStrings); } } diff --git a/packages/quicktype-core/src/input/JSONSchemaInput.ts b/packages/quicktype-core/src/input/JSONSchemaInput.ts index 88142e084..6907c0e48 100644 --- a/packages/quicktype-core/src/input/JSONSchemaInput.ts +++ b/packages/quicktype-core/src/input/JSONSchemaInput.ts @@ -1,73 +1,71 @@ -import URI from "urijs"; import { - setFilter, EqualityMap, - mapMap, - mapFromObject, - setSubtract, - mapFromIterable, - iterableFind, - mapSortBy, - mapMapSync, - mapMergeInto, - arrayMapSync, - arrayLast, + addHashCode, arrayGetFromEnd, - hashCodeOf, - hasOwnProperty, + arrayLast, + arrayMapSync, definedMap, - addHashCode, + // biome-ignore lint/suspicious/noShadowRestrictedNames: + hasOwnProperty, + hashCodeOf, + hashString, + iterableFind, iterableFirst, - hashString + mapFromIterable, + mapFromObject, + mapMap, + mapMapSync, + mapMergeInto, + mapSortBy, + setFilter, + setSubtract, } from "collection-utils"; +import URI from "urijs"; +import { accessorNamesAttributeProducer } from "../attributes/AccessorNames"; import { - PrimitiveTypeKind, - TransformedStringTypeKind, - transformedStringTypeTargetTypeKindsMap, - isNumberTypeKind -} from "../Type"; -import { panic, assertNever, StringMap, assert, defined, parseJSON } from "../support/Support"; -import { TypeBuilder } from "../TypeBuilder"; -import { TypeNames } from "../attributes/TypeNames"; -import { makeNamesTypeAttributes, modifyTypeNames, singularizeTypeNames } from "../attributes/TypeNames"; + minMaxAttributeProducer, + minMaxLengthAttributeProducer, + patternAttributeProducer, +} from "../attributes/Constraints"; +import { descriptionAttributeProducer } from "../attributes/Description"; +import { enumValuesAttributeProducer } from "../attributes/EnumValues"; +import { StringTypes } from "../attributes/StringTypes"; import { - TypeAttributes, - makeTypeAttributesInferred, + type TypeAttributes, + combineTypeAttributes, emptyTypeAttributes, - combineTypeAttributes + makeTypeAttributesInferred, } from "../attributes/TypeAttributes"; -import { JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; -import { messageAssert, messageError } from "../Messages"; -import { StringTypes } from "../attributes/StringTypes"; - -import { TypeRef } from "../TypeGraph"; -import { type RunContext } from "../Run"; -import { type Input } from "./Inputs"; - -// There's a cyclic import here. Ignoring now because it requires a large refactor. -// skipcq: JS-E1008 -import { descriptionAttributeProducer } from "../attributes/Description"; - -import { accessorNamesAttributeProducer } from "../attributes/AccessorNames"; -import { enumValuesAttributeProducer } from "../attributes/EnumValues"; -import { minMaxAttributeProducer } from "../attributes/Constraints"; -import { minMaxLengthAttributeProducer } from "../attributes/Constraints"; -import { patternAttributeProducer } from "../attributes/Constraints"; +import { + TypeNames, + makeNamesTypeAttributes, + modifyTypeNames, + singularizeTypeNames, +} from "../attributes/TypeNames"; import { uriSchemaAttributesProducer } from "../attributes/URIAttributes"; +import { messageAssert, messageError } from "../Messages"; +import type { RunContext } from "../Run"; +import { + type StringMap, + assert, + assertNever, + defined, + panic, + parseJSON, +} from "../support/Support"; +import { + type PrimitiveTypeKind, + type TransformedStringTypeKind, + isNumberTypeKind, + transformedStringTypeTargetTypeKindsMap, +} from "../Type"; +import type { TypeBuilder } from "../Type/TypeBuilder"; +import type { TypeRef } from "../Type/TypeRef"; -export enum PathElementKind { - Root, - KeyOrIndex, - Type, - Object -} - -export type PathElement = - | { kind: PathElementKind.Root } - | { kind: PathElementKind.KeyOrIndex; key: string } - | { kind: PathElementKind.Type; index: number } - | { kind: PathElementKind.Object }; +import type { Input } from "./Inputs"; +import { type JSONSchema, JSONSchemaStore } from "./JSONSchemaStore"; +import { type PathElement, PathElementKind } from "./PathElement"; function keyOrIndex(pe: PathElement): string | undefined { if (pe.kind !== PathElementKind.KeyOrIndex) return undefined; @@ -76,43 +74,67 @@ function keyOrIndex(pe: PathElement): string | undefined { function pathElementEquals(a: PathElement, b: PathElement): boolean { if (a.kind !== b.kind) return false; - switch (a.kind) { - case PathElementKind.Type: - return a.index === (b as any).index; - case PathElementKind.KeyOrIndex: - return a.key === (b as any).key; - default: - return true; + + if (a.kind === PathElementKind.Type && b.kind === PathElementKind.Type) { + return a.index === b.index; + } + + if ( + a.kind === PathElementKind.KeyOrIndex && + b.kind === PathElementKind.KeyOrIndex + ) { + return a.key === b.key; } + + return true; } function withRef(refOrLoc: Ref | (() => Ref) | Location): { ref: Ref }; -function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): T & { ref: Ref }; -function withRef(refOrLoc: Ref | (() => Ref) | Location, props?: T): any { +function withRef( + refOrLoc: Ref | (() => Ref) | Location, + props?: T, +): T & { ref: Ref }; +function withRef( + refOrLoc: Ref | (() => Ref) | Location, + props?: T, +): unknown { const ref = - typeof refOrLoc === "function" ? refOrLoc() : refOrLoc instanceof Ref ? refOrLoc : refOrLoc.canonicalRef; - return Object.assign({ ref }, props === undefined ? {} : props); + typeof refOrLoc === "function" + ? refOrLoc() + : refOrLoc instanceof Ref + ? refOrLoc + : refOrLoc.canonicalRef; + return Object.assign({ ref }, props ?? {}); } -function checkJSONSchemaObject(x: any, refOrLoc: Ref | (() => Ref)): StringMap { +function checkJSONSchemaObject( + x: unknown, + refOrLoc: Ref | (() => Ref), +): StringMap { if (Array.isArray(x)) { return messageError("SchemaArrayIsInvalidSchema", withRef(refOrLoc)); } + if (x === null) { return messageError("SchemaNullIsInvalidSchema", withRef(refOrLoc)); } + if (typeof x !== "object") { - return messageError("SchemaInvalidJSONSchemaType", withRef(refOrLoc, { type: typeof x })); + return messageError( + "SchemaInvalidJSONSchemaType", + withRef(refOrLoc, { type: typeof x }), + ); } + return x; } -function checkJSONSchema(x: any, refOrLoc: Ref | (() => Ref)): JSONSchema { +function checkJSONSchema(x: unknown, refOrLoc: Ref | (() => Ref)): JSONSchema { if (typeof x === "boolean") return x; return checkJSONSchemaObject(x, refOrLoc); } -const numberRegexp = new RegExp("^[0-9]+$"); +const numberRegexp = /^[0-9]+$/; function normalizeURI(uri: string | URI): URI { // FIXME: This is overly complicated and a bit shady. The problem is @@ -123,16 +145,17 @@ function normalizeURI(uri: string | URI): URI { if (typeof uri === "string") { uri = new URI(uri); } + return new URI(URI.decode(uri.clone().normalize().toString())); } export class Ref { - static root(address: string | undefined): Ref { - const uri = definedMap(address, a => new URI(a)); + public static root(address: string | undefined): Ref { + const uri = definedMap(address, (a) => new URI(a)); return new Ref(uri, []); } - private static parsePath(path: string): ReadonlyArray { + private static parsePath(path: string): readonly PathElement[] { const elements: PathElement[] = []; if (path.startsWith("/")) { @@ -142,14 +165,15 @@ export class Ref { if (path !== "") { const parts = path.split("/"); - for (let i = 0; i < parts.length; i++) { - elements.push({ kind: PathElementKind.KeyOrIndex, key: parts[i] }); - } + parts.forEach((part) => + elements.push({ kind: PathElementKind.KeyOrIndex, key: part }), + ); } + return elements; } - static parseURI(uri: URI, destroyURI = false): Ref { + public static parseURI(uri: URI, destroyURI = false): Ref { if (!destroyURI) { uri = uri.clone(); } @@ -159,38 +183,44 @@ export class Ref { if ((uri.host() !== "" || uri.filename() !== "") && path === "") { path = "/"; } + const elements = Ref.parsePath(path); return new Ref(uri, elements); } - static parse(ref: string): Ref { + public static parse(ref: string): Ref { return Ref.parseURI(new URI(ref), true); } public addressURI: URI | undefined; - constructor( + public constructor( addressURI: URI | undefined, - readonly path: ReadonlyArray + public readonly path: readonly PathElement[], ) { if (addressURI !== undefined) { - assert(addressURI.fragment() === "", `Ref URI with fragment is not allowed: ${addressURI.toString()}`); + assert( + addressURI.fragment() === "", + `Ref URI with fragment is not allowed: ${addressURI.toString()}`, + ); this.addressURI = normalizeURI(addressURI); } else { this.addressURI = undefined; } } - get hasAddress(): boolean { + public get hasAddress(): boolean { return this.addressURI !== undefined; } - get address(): string { + public get address(): string { return defined(this.addressURI).toString(); } - get isRoot(): boolean { - return this.path.length === 1 && this.path[0].kind === PathElementKind.Root; + public get isRoot(): boolean { + return ( + this.path.length === 1 && this.path[0].kind === PathElementKind.Root + ); } private pushElement(pe: PathElement): Ref { @@ -199,44 +229,58 @@ export class Ref { return new Ref(this.addressURI, newPath); } - push(...keys: string[]): Ref { + public push(...keys: string[]): Ref { + // eslint-disable-next-line @typescript-eslint/no-this-alias let ref: Ref = this; for (const key of keys) { ref = ref.pushElement({ kind: PathElementKind.KeyOrIndex, key }); } + return ref; } - pushObject(): Ref { + public pushObject(): Ref { return this.pushElement({ kind: PathElementKind.Object }); } - pushType(index: number): Ref { + public pushType(index: number): Ref { return this.pushElement({ kind: PathElementKind.Type, index }); } - resolveAgainst(base: Ref | undefined): Ref { + public resolveAgainst(base: Ref | undefined): Ref { let addressURI = this.addressURI; - if (base !== undefined && base.addressURI !== undefined) { - addressURI = addressURI === undefined ? base.addressURI : addressURI.absoluteTo(base.addressURI); + if (base?.addressURI !== undefined) { + addressURI = + addressURI === undefined + ? base.addressURI + : addressURI.absoluteTo(base.addressURI); } + return new Ref(addressURI, this.path); } - get name(): string { + public get name(): string { const path = Array.from(this.path); for (;;) { const e = path.pop(); if (e === undefined || e.kind === PathElementKind.Root) { - let name = this.addressURI !== undefined ? this.addressURI.filename() : ""; - const suffix = this.addressURI !== undefined ? this.addressURI.suffix() : ""; + let name = + this.addressURI !== undefined + ? this.addressURI.filename() + : ""; + const suffix = + this.addressURI !== undefined + ? this.addressURI.suffix() + : ""; if (name.length > suffix.length + 1) { name = name.slice(0, name.length - suffix.length - 1); } + if (name === "") { return "Something"; } + return name; } @@ -245,24 +289,28 @@ export class Ref { if (numberRegexp.test(e.key)) { return e.key; } + break; case PathElementKind.Type: case PathElementKind.Object: - return panic("We shouldn't try to get the name of Type or Object refs"); + return panic( + "We shouldn't try to get the name of Type or Object refs", + ); default: return assertNever(e); } } } - get definitionName(): string | undefined { + public get definitionName(): string | undefined { const pe = arrayGetFromEnd(this.path, 2); if (pe === undefined) return undefined; - if (keyOrIndex(pe) === "definitions") return keyOrIndex(defined(arrayLast(this.path))); + if (keyOrIndex(pe) === "definitions") + return keyOrIndex(defined(arrayLast(this.path))); return undefined; } - toString(): string { + public toString(): string { function elementToString(e: PathElement): string { switch (e.kind) { case PathElementKind.Root: @@ -277,16 +325,23 @@ export class Ref { return assertNever(e); } } - const address = this.addressURI === undefined ? "" : this.addressURI.toString(); - return address + "#" + this.path.map(elementToString).join("/"); + + const address = + this.addressURI === undefined ? "" : this.addressURI.toString(); + return `${address}#${this.path.map(elementToString).join("/")}`; } - private lookup(local: any, path: ReadonlyArray, root: JSONSchema): JSONSchema { - const refMaker = () => new Ref(this.addressURI, path); + private lookup( + local: unknown, + path: readonly PathElement[], + root: JSONSchema, + ): JSONSchema { + const refMaker = (): Ref => new Ref(this.addressURI, path); const first = path[0]; if (first === undefined) { return checkJSONSchema(local, refMaker); } + const rest = path.slice(1); switch (first.kind) { case PathElementKind.Root: @@ -295,19 +350,36 @@ export class Ref { const key = first.key; if (Array.isArray(local)) { if (!/^\d+$/.test(key)) { - return messageError("SchemaCannotIndexArrayWithNonNumber", withRef(refMaker, { actual: key })); + return messageError( + "SchemaCannotIndexArrayWithNonNumber", + withRef(refMaker, { actual: key }), + ); } - const index = parseInt(first.key, 10); + + const index = Number.parseInt(first.key, 10); if (index >= local.length) { - return messageError("SchemaIndexNotInArray", withRef(refMaker, { index })); + return messageError( + "SchemaIndexNotInArray", + withRef(refMaker, { index }), + ); } + return this.lookup(local[index], rest, root); - } else { - if (!hasOwnProperty(local, key)) { - return messageError("SchemaKeyNotInObject", withRef(refMaker, { key })); - } - return this.lookup(checkJSONSchemaObject(local, refMaker)[first.key], rest, root); } + + if (!hasOwnProperty(local, key)) { + return messageError( + "SchemaKeyNotInObject", + withRef(refMaker, { key }), + ); + } + + return this.lookup( + checkJSONSchemaObject(local, refMaker)[first.key], + rest, + root, + ); + case PathElementKind.Type: return panic('Cannot look up path that indexes "type"'); case PathElementKind.Object: @@ -317,27 +389,33 @@ export class Ref { } } - lookupRef(root: JSONSchema): JSONSchema { + public lookupRef(root: JSONSchema): JSONSchema { return this.lookup(root, this.path, root); } - equals(other: any): boolean { + public equals(other: R): boolean { if (!(other instanceof Ref)) return false; if (this.addressURI !== undefined && other.addressURI !== undefined) { if (!this.addressURI.equals(other.addressURI)) return false; } else { - if ((this.addressURI === undefined) !== (other.addressURI === undefined)) return false; + if ( + (this.addressURI === undefined) !== + (other.addressURI === undefined) + ) + return false; } + const l = this.path.length; if (l !== other.path.length) return false; for (let i = 0; i < l; i++) { if (!pathElementEquals(this.path[i], other.path[i])) return false; } + return true; } - hashCode(): number { - let acc = hashCodeOf(definedMap(this.addressURI, u => u.toString())); + public hashCode(): number { + let acc = hashCodeOf(definedMap(this.addressURI, (u) => u.toString())); for (const pe of this.path) { acc = addHashCode(acc, pe.kind); switch (pe.kind) { @@ -351,105 +429,145 @@ export class Ref { break; } } + return acc; } } class Location { public readonly canonicalRef: Ref; + public readonly virtualRef: Ref; - constructor( + public constructor( canonicalRef: Ref, virtualRef?: Ref, - readonly haveID: boolean = false + public readonly haveID: boolean = false, ) { this.canonicalRef = canonicalRef; - this.virtualRef = virtualRef !== undefined ? virtualRef : canonicalRef; + this.virtualRef = virtualRef ?? canonicalRef; } - updateWithID(id: any) { + public updateWithID(id: string | unknown): Location { if (typeof id !== "string") return this; const parsed = Ref.parse(id); - const virtual = this.haveID ? parsed.resolveAgainst(this.virtualRef) : parsed; + const virtual = this.haveID + ? parsed.resolveAgainst(this.virtualRef) + : parsed; if (!this.haveID) { - messageAssert(virtual.hasAddress, "SchemaIDMustHaveAddress", withRef(this, { id })); + messageAssert( + virtual.hasAddress, + "SchemaIDMustHaveAddress", + withRef(this, { id }), + ); } + return new Location(this.canonicalRef, virtual, true); } - push(...keys: string[]): Location { - return new Location(this.canonicalRef.push(...keys), this.virtualRef.push(...keys), this.haveID); + public push(...keys: string[]): Location { + return new Location( + this.canonicalRef.push(...keys), + this.virtualRef.push(...keys), + this.haveID, + ); } - pushObject(): Location { - return new Location(this.canonicalRef.pushObject(), this.virtualRef.pushObject(), this.haveID); + public pushObject(): Location { + return new Location( + this.canonicalRef.pushObject(), + this.virtualRef.pushObject(), + this.haveID, + ); } - pushType(index: number): Location { - return new Location(this.canonicalRef.pushType(index), this.virtualRef.pushType(index), this.haveID); + public pushType(index: number): Location { + return new Location( + this.canonicalRef.pushType(index), + this.virtualRef.pushType(index), + this.haveID, + ); } - toString(): string { + public toString(): string { return `${this.virtualRef.toString()} (${this.canonicalRef.toString()})`; } } class Canonizer { private readonly _map = new EqualityMap(); + private readonly _schemaAddressesAdded = new Set(); - constructor(private readonly _ctx: RunContext) {} + public constructor(private readonly _ctx: RunContext) {} - private addIDs(schema: any, loc: Location) { + private addIDs(schema: unknown, loc: Location): void { if (schema === null) return; if (Array.isArray(schema)) { for (let i = 0; i < schema.length; i++) { this.addIDs(schema[i], loc.push(i.toString())); } + return; } + if (typeof schema !== "object") { return; } + const locWithoutID = loc; - const maybeID = schema["$id"]; + const maybeID = "$id" in schema ? schema.$id : undefined; if (typeof maybeID === "string") { loc = loc.updateWithID(maybeID); } + if (loc.haveID) { if (this._ctx.debugPrintSchemaResolving) { console.log(`adding mapping ${loc.toString()}`); } + this._map.set(loc.virtualRef, locWithoutID); } + for (const property of Object.getOwnPropertyNames(schema)) { - this.addIDs(schema[property], loc.push(property)); + this.addIDs( + schema[property as keyof typeof schema], + loc.push(property), + ); } } - addSchema(schema: any, address: string): boolean { + public addSchema(schema: unknown, address: string): boolean { if (this._schemaAddressesAdded.has(address)) return false; - this.addIDs(schema, new Location(Ref.root(address), Ref.root(undefined))); + this.addIDs( + schema, + new Location(Ref.root(address), Ref.root(undefined)), + ); this._schemaAddressesAdded.add(address); return true; } // Returns: Canonical ref - canonize(base: Location, ref: Ref): Location { + public canonize(base: Location, ref: Ref): Location { const virtual = ref.resolveAgainst(base.virtualRef); const loc = this._map.get(virtual); if (loc !== undefined) { return loc; } + const canonicalRef = - virtual.addressURI === undefined ? new Ref(base.canonicalRef.addressURI, virtual.path) : virtual; + virtual.addressURI === undefined + ? new Ref(base.canonicalRef.addressURI, virtual.path) + : virtual; return new Location(canonicalRef, new Ref(undefined, virtual.path)); } } -function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { +function checkTypeList( + typeOrTypes: string | string[], + loc: Location, +): ReadonlySet { let set: Set; if (typeof typeOrTypes === "string") { set = new Set([typeOrTypes]); @@ -457,32 +575,61 @@ function checkTypeList(typeOrTypes: any, loc: Location): ReadonlySet { const arr: string[] = []; for (const t of typeOrTypes) { if (typeof t !== "string") { - return messageError("SchemaTypeElementMustBeString", withRef(loc, { element: t })); + return messageError( + "SchemaTypeElementMustBeString", + withRef(loc, { element: t }), + ); } + arr.push(t); } + set = new Set(arr); } else { - return messageError("SchemaTypeMustBeStringOrStringArray", withRef(loc, { actual: typeOrTypes })); + return messageError( + "SchemaTypeMustBeStringOrStringArray", + withRef(loc, { actual: typeOrTypes }), + ); } + messageAssert(set.size > 0, "SchemaNoTypeSpecified", withRef(loc)); - const validTypes = ["null", "boolean", "object", "array", "number", "string", "integer"]; - const maybeInvalid = iterableFind(set, s => validTypes.indexOf(s) < 0); + const validTypes = [ + "null", + "boolean", + "object", + "array", + "number", + "string", + "integer", + ]; + const maybeInvalid = iterableFind(set, (s) => !validTypes.includes(s)); if (maybeInvalid !== undefined) { - return messageError("SchemaInvalidType", withRef(loc, { type: maybeInvalid })); + return messageError( + "SchemaInvalidType", + withRef(loc, { type: maybeInvalid }), + ); } + return set; } -function checkRequiredArray(arr: any, loc: Location): string[] { +function checkRequiredArray(arr: string[], loc: Location): string[] { if (!Array.isArray(arr)) { - return messageError("SchemaRequiredMustBeStringOrStringArray", withRef(loc, { actual: arr })); + return messageError( + "SchemaRequiredMustBeStringOrStringArray", + withRef(loc, { actual: arr }), + ); } + for (const e of arr) { if (typeof e !== "string") { - return messageError("SchemaRequiredElementMustBeString", withRef(loc, { element: e })); + return messageError( + "SchemaRequiredElementMustBeString", + withRef(loc, { element: e }), + ); } } + return arr; } @@ -493,31 +640,35 @@ export const schemaTypeDict = { integer: true, number: true, array: true, - object: true + object: true, }; export type JSONSchemaType = keyof typeof schemaTypeDict; -const schemaTypes = Object.getOwnPropertyNames(schemaTypeDict) as JSONSchemaType[]; +const schemaTypes = Object.getOwnPropertyNames( + schemaTypeDict, +) as JSONSchemaType[]; -export type JSONSchemaAttributes = { - forType?: TypeAttributes; - forUnion?: TypeAttributes; - forObject?: TypeAttributes; +export interface JSONSchemaAttributes { + forCases?: TypeAttributes[]; forNumber?: TypeAttributes; + forObject?: TypeAttributes; forString?: TypeAttributes; - forCases?: TypeAttributes[]; -}; + forType?: TypeAttributes; + forUnion?: TypeAttributes; +} export type JSONSchemaAttributeProducer = ( schema: JSONSchema, canonicalRef: Ref, types: Set, - unionCases: JSONSchema[] | undefined + unionCases: JSONSchema[] | undefined, ) => JSONSchemaAttributes | undefined; -function typeKindForJSONSchemaFormat(format: string): TransformedStringTypeKind | undefined { +function typeKindForJSONSchemaFormat( + format: string, +): TransformedStringTypeKind | undefined { const target = iterableFind( transformedStringTypeTargetTypeKindsMap, - ([_, { jsonSchema }]) => jsonSchema === format + ([_, { jsonSchema }]) => jsonSchema === format, ); if (target === undefined) return undefined; return target[0] as TransformedStringTypeKind; @@ -526,22 +677,25 @@ function typeKindForJSONSchemaFormat(format: string): TransformedStringTypeKind function schemaFetchError(base: Location | undefined, address: string): never { if (base === undefined) { return messageError("SchemaFetchErrorTopLevel", { address }); - } else { - return messageError("SchemaFetchError", { address, base: base.canonicalRef }); } + + return messageError("SchemaFetchError", { + address, + base: base.canonicalRef, + }); } class Resolver { - constructor( + public constructor( private readonly _ctx: RunContext, private readonly _store: JSONSchemaStore, - private readonly _canonizer: Canonizer + private readonly _canonizer: Canonizer, ) {} private async tryResolveVirtualRef( fetchBase: Location, lookupBase: Location, - virtualRef: Ref + virtualRef: Ref, ): Promise<[JSONSchema | undefined, Location]> { let didAdd = false; // If we are resolving into a schema file that we haven't seen yet then @@ -551,13 +705,19 @@ class Resolver { for (;;) { const loc = this._canonizer.canonize(fetchBase, virtualRef); const canonical = loc.canonicalRef; - assert(canonical.hasAddress, "Canonical ref can't be resolved without an address"); + assert( + canonical.hasAddress, + "Canonical ref can't be resolved without an address", + ); const address = canonical.address; - let schema = + const schema = canonical.addressURI === undefined ? undefined - : await this._store.get(address, this._ctx.debugPrintSchemaResolving); + : await this._store.get( + address, + this._ctx.debugPrintSchemaResolving, + ); if (schema === undefined) { return [undefined, loc]; } @@ -566,22 +726,34 @@ class Resolver { assert(!didAdd, "We can't add a schema twice"); didAdd = true; } else { - let lookupLoc = this._canonizer.canonize(lookupBase, virtualRef); + let lookupLoc = this._canonizer.canonize( + lookupBase, + virtualRef, + ); if (fetchBase !== undefined) { lookupLoc = new Location( - new Ref(loc.canonicalRef.addressURI, lookupLoc.canonicalRef.path), + new Ref( + loc.canonicalRef.addressURI, + lookupLoc.canonicalRef.path, + ), lookupLoc.virtualRef, - lookupLoc.haveID + lookupLoc.haveID, ); } + return [lookupLoc.canonicalRef.lookupRef(schema), lookupLoc]; } } } - async resolveVirtualRef(base: Location, virtualRef: Ref): Promise<[JSONSchema, Location]> { + public async resolveVirtualRef( + base: Location, + virtualRef: Ref, + ): Promise<[JSONSchema, Location]> { if (this._ctx.debugPrintSchemaResolving) { - console.log(`resolving ${virtualRef.toString()} relative to ${base.toString()}`); + console.log( + `resolving ${virtualRef.toString()} relative to ${base.toString()}`, + ); } // Try with the virtual base first. If that doesn't work, use the @@ -592,13 +764,14 @@ class Resolver { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolved to ${result[1].toString()}`); } + return [schema, result[1]]; } const altBase = new Location( base.canonicalRef, new Ref(base.canonicalRef.addressURI, base.virtualRef.path), - base.haveID + base.haveID, ); result = await this.tryResolveVirtualRef(altBase, base, virtualRef); schema = result[0]; @@ -606,14 +779,18 @@ class Resolver { if (this._ctx.debugPrintSchemaResolving) { console.log(`resolved to ${result[1].toString()}`); } + return [schema, result[1]]; } return schemaFetchError(base, virtualRef.address); } - async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> { - return await this.resolveVirtualRef(new Location(new Ref(ref.addressURI, [])), new Ref(undefined, ref.path)); + public async resolveTopLevelRef(ref: Ref): Promise<[JSONSchema, Location]> { + return await this.resolveVirtualRef( + new Location(new Ref(ref.addressURI, [])), + new Ref(undefined, ref.path), + ); } } @@ -621,15 +798,19 @@ async function addTypesInSchema( resolver: Resolver, typeBuilder: TypeBuilder, references: ReadonlyMap, - attributeProducers: JSONSchemaAttributeProducer[] + attributeProducers: JSONSchemaAttributeProducer[], ): Promise { - let typeForCanonicalRef = new EqualityMap(); + const typeForCanonicalRef = new EqualityMap(); function setTypeForLocation(loc: Location, t: TypeRef): void { const maybeRef = typeForCanonicalRef.get(loc.canonicalRef); if (maybeRef !== undefined) { - assert(maybeRef === t, "Trying to set path again to different type"); + assert( + maybeRef === t, + "Trying to set path again to different type", + ); } + typeForCanonicalRef.set(loc.canonicalRef, t); } @@ -638,114 +819,159 @@ async function addTypesInSchema( attributes: TypeAttributes, properties: StringMap, requiredArray: string[], - additionalProperties: any, - sortKey: (k: string) => number | string = (k: string) => k.toLowerCase() + additionalProperties: unknown, + sortKey: (k: string) => number | string = (k: string): string => + k.toLowerCase(), ): Promise { const required = new Set(requiredArray); - const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) => sortKey(k)); - const props = await mapMapSync(propertiesMap, async (propSchema, propName) => { - const propLoc = loc.push("properties", propName); - const t = await toType( - checkJSONSchema(propSchema, propLoc.canonicalRef), - propLoc, - makeNamesTypeAttributes(propName, true) - ); - const isOptional = !required.has(propName); - return typeBuilder.makeClassProperty(t, isOptional); - }); + const propertiesMap = mapSortBy(mapFromObject(properties), (_, k) => + sortKey(k), + ); + const props = await mapMapSync( + propertiesMap, + async (propSchema, propName) => { + const propLoc = loc.push("properties", propName); + const t = await toType( + checkJSONSchema(propSchema, propLoc.canonicalRef), + propLoc, + makeNamesTypeAttributes(propName, true), + ); + const isOptional = !required.has(propName); + return typeBuilder.makeClassProperty(t, isOptional); + }, + ); let additionalPropertiesType: TypeRef | undefined; - if (additionalProperties === undefined || additionalProperties === true) { + if ( + additionalProperties === undefined || + additionalProperties === true + ) { additionalPropertiesType = typeBuilder.getPrimitiveType("any"); } else if (additionalProperties === false) { additionalPropertiesType = undefined; } else { const additionalLoc = loc.push("additionalProperties"); additionalPropertiesType = await toType( - checkJSONSchema(additionalProperties, additionalLoc.canonicalRef), + checkJSONSchema( + additionalProperties, + additionalLoc.canonicalRef, + ), additionalLoc, - singularizeTypeNames(attributes) + singularizeTypeNames(attributes), ); } + const additionalRequired = setSubtract(required, props.keys()); if (additionalRequired.size > 0) { const t = additionalPropertiesType; if (t === undefined) { - return messageError("SchemaAdditionalTypesForbidRequired", withRef(loc)); + return messageError( + "SchemaAdditionalTypesForbidRequired", + withRef(loc), + ); } - const additionalProps = mapFromIterable(additionalRequired, _name => - typeBuilder.makeClassProperty(t, false) + const additionalProps = mapFromIterable( + additionalRequired, + (_name) => typeBuilder.makeClassProperty(t, false), ); mapMergeInto(props, additionalProps); } - return typeBuilder.getUniqueObjectType(attributes, props, additionalPropertiesType); + + return typeBuilder.getUniqueObjectType( + attributes, + props, + additionalPropertiesType, + ); } - async function convertToType(schema: StringMap, loc: Location, typeAttributes: TypeAttributes): Promise { + async function convertToType( + schema: StringMap, + loc: Location, + typeAttributes: TypeAttributes, + ): Promise { const enumArray = Array.isArray(schema.enum) ? schema.enum : undefined; const isConst = schema.const !== undefined; - const typeSet = definedMap(schema.type, t => checkTypeList(t, loc)); + const typeSet = definedMap(schema.type, (t) => checkTypeList(t, loc)); function isTypeIncluded(name: JSONSchemaType): boolean { if (typeSet !== undefined && !typeSet.has(name)) { return false; } + if (enumArray !== undefined) { - let predicate: (x: any) => boolean; + let predicate: (x: unknown) => boolean; switch (name) { case "null": - predicate = (x: any) => x === null; + predicate = (x): x is null => x === null; break; case "integer": - predicate = (x: any) => typeof x === "number" && x === Math.floor(x); + predicate = (x): x is number => + typeof x === "number" && x === Math.floor(x); break; default: - predicate = (x: any) => typeof x === name; + predicate = (x): x is typeof name => typeof x === name; break; } return enumArray.find(predicate) !== undefined; } + if (isConst) { return name === (schema.type ?? typeof schema.const); } + return true; } const includedTypes = setFilter(schemaTypes, isTypeIncluded); - let producedAttributesForNoCases: JSONSchemaAttributes[] | undefined = undefined; + let producedAttributesForNoCases: JSONSchemaAttributes[] | undefined = + undefined; function forEachProducedAttribute( cases: JSONSchema[] | undefined, - f: (attributes: JSONSchemaAttributes) => void + f: (attributes: JSONSchemaAttributes) => void, ): void { let attributes: JSONSchemaAttributes[]; - if (cases === undefined && producedAttributesForNoCases !== undefined) { + if ( + cases === undefined && + producedAttributesForNoCases !== undefined + ) { attributes = producedAttributesForNoCases; } else { attributes = []; for (const producer of attributeProducers) { - const newAttributes = producer(schema, loc.canonicalRef, includedTypes, cases); + const newAttributes = producer( + schema, + loc.canonicalRef, + includedTypes, + cases, + ); if (newAttributes === undefined) continue; attributes.push(newAttributes); } + if (cases === undefined) { producedAttributesForNoCases = attributes; } } + for (const a of attributes) { f(a); } } function combineProducedAttributes( - f: (attributes: JSONSchemaAttributes) => TypeAttributes | undefined + f: (attributes: JSONSchemaAttributes) => TypeAttributes | undefined, ): TypeAttributes { let result = emptyTypeAttributes; - forEachProducedAttribute(undefined, attr => { + forEachProducedAttribute(undefined, (attr) => { const maybeAttributes = f(attr); if (maybeAttributes === undefined) return; - result = combineTypeAttributes("union", result, maybeAttributes); + result = combineTypeAttributes( + "union", + result, + maybeAttributes, + ); }); return result; } @@ -755,30 +981,39 @@ async function addTypesInSchema( attributes = combineTypeAttributes( "union", attributes, - combineProducedAttributes(({ forType, forUnion, forCases }) => { - assert( - forUnion === undefined && forCases === undefined, - "We can't have attributes for unions and cases if we don't have a union" - ); - return forType; - }) + combineProducedAttributes( + ({ forType, forUnion, forCases }) => { + assert( + forUnion === undefined && + forCases === undefined, + "We can't have attributes for unions and cases if we don't have a union", + ); + return forType; + }, + ), ); } - return modifyTypeNames(attributes, maybeTypeNames => { + + return modifyTypeNames(attributes, (maybeTypeNames) => { const typeNames = defined(maybeTypeNames); if (!typeNames.areInferred) { return typeNames; } + let title = schema.title; if (typeof title !== "string") { title = loc.canonicalRef.definitionName; } if (typeof title === "string") { - return TypeNames.make(new Set([title]), new Set(), schema.$ref !== undefined); - } else { - return typeNames.makeInferred(); + return TypeNames.make( + new Set([title]), + new Set(), + schema.$ref !== undefined, + ); } + + return typeNames.makeInferred(); }); } @@ -788,10 +1023,13 @@ async function addTypesInSchema( function makeStringType(attributes: TypeAttributes): TypeRef { const kind = typeKindForJSONSchemaFormat(schema.format); if (kind === undefined) { - return typeBuilder.getStringType(attributes, StringTypes.unrestricted); - } else { - return typeBuilder.getPrimitiveType(kind, attributes); + return typeBuilder.getStringType( + attributes, + StringTypes.unrestricted, + ); } + + return typeBuilder.getPrimitiveType(kind, attributes); } async function makeArrayType(): Promise { @@ -802,24 +1040,42 @@ async function addTypesInSchema( const itemsLoc = loc.push("items"); const itemTypes = await arrayMapSync(items, async (item, i) => { const itemLoc = itemsLoc.push(i.toString()); - return await toType(checkJSONSchema(item, itemLoc.canonicalRef), itemLoc, singularAttributes); + return await toType( + checkJSONSchema(item, itemLoc.canonicalRef), + itemLoc, + singularAttributes, + ); }); - itemType = typeBuilder.getUnionType(emptyTypeAttributes, new Set(itemTypes)); + itemType = typeBuilder.getUnionType( + emptyTypeAttributes, + new Set(itemTypes), + ); } else if (typeof items === "object") { const itemsLoc = loc.push("items"); - itemType = await toType(checkJSONSchema(items, itemsLoc.canonicalRef), itemsLoc, singularAttributes); - } else if (items !== undefined) { - return messageError("SchemaArrayItemsMustBeStringOrArray", withRef(loc, { actual: items })); + itemType = await toType( + checkJSONSchema(items, itemsLoc.canonicalRef), + itemsLoc, + singularAttributes, + ); + } else if (items !== undefined && items !== true) { + return messageError( + "SchemaArrayItemsMustBeStringOrArray", + withRef(loc, { actual: items }), + ); } else { itemType = typeBuilder.getPrimitiveType("any"); } + typeBuilder.addAttributes(itemType, singularAttributes); return typeBuilder.getArrayType(emptyTypeAttributes, itemType); } async function makeObjectType(): Promise { let required: string[]; - if (schema.required === undefined || typeof schema.required === "boolean") { + if ( + schema.required === undefined || + typeof schema.required === "boolean" + ) { required = []; } else { required = Array.from(checkRequiredArray(schema.required, loc)); @@ -829,12 +1085,15 @@ async function addTypesInSchema( if (schema.properties === undefined) { properties = {}; } else { - properties = checkJSONSchemaObject(schema.properties, loc.canonicalRef); + properties = checkJSONSchemaObject( + schema.properties, + loc.canonicalRef, + ); } // In Schema Draft 3, `required` is `true` on a property that's required. for (const p of Object.getOwnPropertyNames(properties)) { - if (properties[p].required === true && required.indexOf(p) < 0) { + if (properties[p].required === true && !required.includes(p)) { required.push(p); } } @@ -853,71 +1112,116 @@ async function addTypesInSchema( const objectAttributes = combineTypeAttributes( "union", inferredAttributes, - combineProducedAttributes(({ forObject }) => forObject) + combineProducedAttributes(({ forObject }) => forObject), ); - const order = schema.quicktypePropertyOrder ? schema.quicktypePropertyOrder : []; - const orderKey = (propertyName: string) => { + const order = schema.quicktypePropertyOrder + ? schema.quicktypePropertyOrder + : []; + const orderKey = (propertyName: string): string => { // use the index of the order array const index = order.indexOf(propertyName); // if no index then use the property name return index !== -1 ? index : propertyName.toLowerCase(); }; - return await makeObject(loc, objectAttributes, properties, required, additionalProperties, orderKey); + return await makeObject( + loc, + objectAttributes, + properties, + required, + additionalProperties, + orderKey, + ); } - async function makeTypesFromCases(cases: any, kind: string): Promise { + async function makeTypesFromCases( + cases: unknown[], + kind: string, + ): Promise { const kindLoc = loc.push(kind); if (!Array.isArray(cases)) { - return messageError("SchemaSetOperationCasesIsNotArray", withRef(kindLoc, { operation: kind, cases })); + return messageError( + "SchemaSetOperationCasesIsNotArray", + withRef(kindLoc, { operation: kind, cases }), + ); } - // FIXME: This cast shouldn't be necessary, but TypeScript forces our hand. + return await arrayMapSync(cases, async (t, index) => { const caseLoc = kindLoc.push(index.toString()); return await toType( checkJSONSchema(t, caseLoc.canonicalRef), caseLoc, - makeTypeAttributesInferred(typeAttributes) + makeTypeAttributesInferred(typeAttributes), ); }); } - const intersectionType = typeBuilder.getUniqueIntersectionType(typeAttributes, undefined); + const intersectionType = typeBuilder.getUniqueIntersectionType( + typeAttributes, + undefined, + ); setTypeForLocation(loc, intersectionType); - async function convertOneOrAnyOf(cases: any, kind: string): Promise { + async function convertOneOrAnyOf( + cases: unknown[], + kind: string, + ): Promise { const typeRefs = await makeTypesFromCases(cases, kind); let unionAttributes = makeTypeAttributesInferred(typeAttributes); if (kind === "oneOf") { - forEachProducedAttribute(cases as JSONSchema[], ({ forType, forUnion, forCases }) => { - if (forType !== undefined) { - typeBuilder.addAttributes(intersectionType, forType); - } - if (forUnion !== undefined) { - unionAttributes = combineTypeAttributes("union", unionAttributes, forUnion); - } - if (forCases !== undefined) { - assert( - forCases.length === typeRefs.length, - "Number of case attributes doesn't match number of cases" - ); - for (let i = 0; i < typeRefs.length; i++) { - typeBuilder.addAttributes(typeRefs[i], forCases[i]); + forEachProducedAttribute( + cases as JSONSchema[], + ({ forType, forUnion, forCases }) => { + if (forType !== undefined) { + typeBuilder.addAttributes( + intersectionType, + forType, + ); } - } - }); + + if (forUnion !== undefined) { + unionAttributes = combineTypeAttributes( + "union", + unionAttributes, + forUnion, + ); + } + + if (forCases !== undefined) { + assert( + forCases.length === typeRefs.length, + "Number of case attributes doesn't match number of cases", + ); + for (let i = 0; i < typeRefs.length; i++) { + typeBuilder.addAttributes( + typeRefs[i], + forCases[i], + ); + } + } + }, + ); } - const unionType = typeBuilder.getUniqueUnionType(unionAttributes, undefined); + + const unionType = typeBuilder.getUniqueUnionType( + unionAttributes, + undefined, + ); typeBuilder.setSetOperationMembers(unionType, new Set(typeRefs)); return unionType; } - const includeObject = enumArray === undefined && !isConst && (typeSet === undefined || typeSet.has("object")); - const includeArray = enumArray === undefined && !isConst && (typeSet === undefined || typeSet.has("array")); + const includeObject = + enumArray === undefined && + !isConst && + (typeSet === undefined || typeSet.has("object")); + const includeArray = + enumArray === undefined && + !isConst && + (typeSet === undefined || typeSet.has("array")); const needStringEnum = includedTypes.has("string") && - enumArray !== undefined && - enumArray.find((x: any) => typeof x === "string") !== undefined; + enumArray?.find((x) => typeof x === "string") !== undefined; const needUnion = typeSet !== undefined || schema.properties !== undefined || @@ -932,31 +1236,40 @@ async function addTypesInSchema( if (needUnion) { const unionTypes: TypeRef[] = []; - const numberAttributes = combineProducedAttributes(({ forNumber }) => forNumber); + const numberAttributes = combineProducedAttributes( + ({ forNumber }) => forNumber, + ); for (const [name, kind] of [ ["null", "null"], ["number", "double"], ["integer", "integer"], - ["boolean", "bool"] - ] as [JSONSchemaType, PrimitiveTypeKind][]) { + ["boolean", "bool"], + ] as Array<[JSONSchemaType, PrimitiveTypeKind]>) { if (!includedTypes.has(name)) continue; - const attributes = isNumberTypeKind(kind) ? numberAttributes : undefined; + const attributes = isNumberTypeKind(kind) + ? numberAttributes + : undefined; unionTypes.push(typeBuilder.getPrimitiveType(kind, attributes)); } const stringAttributes = combineTypeAttributes( "union", inferredAttributes, - combineProducedAttributes(({ forString }) => forString) + combineProducedAttributes(({ forString }) => forString), ); if (needStringEnum || isConst) { const cases = isConst ? [schema.const] - : ((enumArray as any[]).filter(x => typeof x === "string") as string[]); - unionTypes.push(typeBuilder.getStringType(stringAttributes, StringTypes.fromCases(cases))); + : (enumArray?.filter((x) => typeof x === "string") ?? []); + unionTypes.push( + typeBuilder.getStringType( + stringAttributes, + StringTypes.fromCases(cases), + ), + ); } else if (includedTypes.has("string")) { unionTypes.push(makeStringType(stringAttributes)); } @@ -964,22 +1277,39 @@ async function addTypesInSchema( if (includeArray) { unionTypes.push(await makeArrayType()); } + if (includeObject) { unionTypes.push(await makeObjectType()); } - types.push(typeBuilder.getUniqueUnionType(inferredAttributes, new Set(unionTypes))); + types.push( + typeBuilder.getUniqueUnionType( + inferredAttributes, + new Set(unionTypes), + ), + ); } if (schema.$ref !== undefined) { if (typeof schema.$ref !== "string") { - return messageError("SchemaRefMustBeString", withRef(loc, { actual: typeof schema.$ref })); + return messageError( + "SchemaRefMustBeString", + withRef(loc, { actual: typeof schema.$ref }), + ); } + const virtualRef = Ref.parse(schema.$ref); - const [target, newLoc] = await resolver.resolveVirtualRef(loc, virtualRef); - const attributes = modifyTypeNames(typeAttributes, tn => { + const [target, newLoc] = await resolver.resolveVirtualRef( + loc, + virtualRef, + ); + const attributes = modifyTypeNames(typeAttributes, (tn) => { if (!defined(tn).areInferred) return tn; - return TypeNames.make(new Set([newLoc.canonicalRef.name]), new Set(), true); + return TypeNames.make( + new Set([newLoc.canonicalRef.name]), + new Set(), + true, + ); }); types.push(await toType(target, newLoc, attributes)); } @@ -987,9 +1317,11 @@ async function addTypesInSchema( if (schema.allOf !== undefined) { types.push(...(await makeTypesFromCases(schema.allOf, "allOf"))); } + if (schema.oneOf !== undefined) { types.push(await convertOneOrAnyOf(schema.oneOf, "oneOf")); } + if (schema.anyOf !== undefined) { types.push(await convertOneOrAnyOf(schema.anyOf, "anyOf")); } @@ -998,7 +1330,11 @@ async function addTypesInSchema( return intersectionType; } - async function toType(schema: JSONSchema, loc: Location, typeAttributes: TypeAttributes): Promise { + async function toType( + schema: JSONSchema, + loc: Location, + typeAttributes: TypeAttributes, + ): Promise { const maybeType = typeForCanonicalRef.get(loc.canonicalRef); if (maybeType !== undefined) { return maybeType; @@ -1008,10 +1344,14 @@ async function addTypesInSchema( if (typeof schema === "boolean") { // FIXME: Empty union. We'd have to check that it's supported everywhere, // in particular in union flattening. - messageAssert(schema === true, "SchemaFalseNotSupported", withRef(loc)); + messageAssert( + schema === true, + "SchemaFalseNotSupported", + withRef(loc), + ); result = typeBuilder.getPrimitiveType("any"); } else { - loc = loc.updateWithID(schema["$id"]); + loc = loc.updateWithID(schema.$id); result = await convertToType(schema, loc, typeAttributes); } @@ -1021,7 +1361,11 @@ async function addTypesInSchema( for (const [topLevelName, topLevelRef] of references) { const [target, loc] = await resolver.resolveTopLevelRef(topLevelRef); - const t = await toType(target, loc, makeNamesTypeAttributes(topLevelName, false)); + const t = await toType( + target, + loc, + makeNamesTypeAttributes(topLevelName, false), + ); typeBuilder.addTopLevel(topLevelName, t); } } @@ -1037,6 +1381,7 @@ function removeExtension(fn: string): string { } } } + return fn; } @@ -1048,27 +1393,33 @@ function nameFromURI(uri: URI): string | undefined { if (components[len - 1] !== "") { return removeExtension(components[len - 1]); } + if (len > 1 && components[len - 2] !== "") { return removeExtension(components[len - 2]); } } + const filename = uri.filename(); if (filename !== "") { return removeExtension(filename); } - return messageError("DriverCannotInferNameForSchema", { uri: uri.toString() }); + + return messageError("DriverCannotInferNameForSchema", { + uri: uri.toString(), + }); } async function refsInSchemaForURI( resolver: Resolver, uri: URI, - defaultName: string + defaultName: string, ): Promise | [string, Ref]> { const fragment = uri.fragment(); let propertiesAreTypes = fragment.endsWith("/"); if (propertiesAreTypes) { uri = uri.clone().fragment(fragment.slice(0, -1)); } + const ref = Ref.parseURI(uri); if (ref.isRoot) { propertiesAreTypes = false; @@ -1078,65 +1429,76 @@ async function refsInSchemaForURI( if (propertiesAreTypes) { if (typeof schema !== "object") { - return messageError("SchemaCannotGetTypesFromBoolean", { ref: ref.toString() }); + return messageError("SchemaCannotGetTypesFromBoolean", { + ref: ref.toString(), + }); } + return mapMap(mapFromObject(schema), (_, name) => ref.push(name)); + } + + let name: string; + if (typeof schema === "object" && typeof schema.title === "string") { + name = schema.title; } else { - let name: string; - if (typeof schema === "object" && typeof schema.title === "string") { - name = schema.title; - } else { - const maybeName = nameFromURI(uri); - name = maybeName !== undefined ? maybeName : defaultName; - } - return [name, ref]; + const maybeName = nameFromURI(uri); + name = maybeName ?? defaultName; } + + return [name, ref]; } class InputJSONSchemaStore extends JSONSchemaStore { - constructor( + public constructor( private readonly _inputs: Map, - private readonly _delegate?: JSONSchemaStore + private readonly _delegate?: JSONSchemaStore, ) { super(); } - async fetch(address: string): Promise { + public async fetch(address: string): Promise { const maybeInput = this._inputs.get(address); if (maybeInput !== undefined) { - return checkJSONSchema(parseJSON(maybeInput, "JSON Schema", address), () => Ref.root(address)); + return checkJSONSchema( + parseJSON(maybeInput, "JSON Schema", address), + () => Ref.root(address), + ); } + if (this._delegate === undefined) { return panic(`Schema URI ${address} requested, but no store given`); } + return await this._delegate.fetch(address); } } export interface JSONSchemaSourceData { + isConverted?: boolean; name: string; - uris?: string[]; schema?: string; - isConverted?: boolean; + uris?: string[]; } export class JSONSchemaInput implements Input { - readonly kind: string = "schema"; - readonly needSchemaProcessing: boolean = true; + public readonly kind: string = "schema"; + + public readonly needSchemaProcessing: boolean = true; private readonly _attributeProducers: JSONSchemaAttributeProducer[]; private readonly _schemaInputs: Map = new Map(); - private _schemaSources: [URI, JSONSchemaSourceData][] = []; + + private _schemaSources: Array<[URI, JSONSchemaSourceData]> = []; private readonly _topLevels: Map = new Map(); private _needIR = false; - constructor( + public constructor( private _schemaStore: JSONSchemaStore | undefined, additionalAttributeProducers: JSONSchemaAttributeProducer[] = [], - private readonly _additionalSchemaAddresses: ReadonlyArray = [] + private readonly _additionalSchemaAddresses: readonly string[] = [], ) { this._attributeProducers = [ descriptionAttributeProducer, @@ -1145,19 +1507,22 @@ export class JSONSchemaInput implements Input { uriSchemaAttributesProducer, minMaxAttributeProducer, minMaxLengthAttributeProducer, - patternAttributeProducer + patternAttributeProducer, ].concat(additionalAttributeProducers); } - get needIR(): boolean { + public get needIR(): boolean { return this._needIR; } - addTopLevel(name: string, ref: Ref): void { + public addTopLevel(name: string, ref: Ref): void { this._topLevels.set(name, ref); } - async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { + public async addTypes( + ctx: RunContext, + typeBuilder: TypeBuilder, + ): Promise { if (this._schemaSources.length === 0) return; let maybeSchemaStore = this._schemaStore; @@ -1166,32 +1531,52 @@ export class JSONSchemaInput implements Input { return panic("Must have a schema store to process JSON Schema"); } } else { - maybeSchemaStore = this._schemaStore = new InputJSONSchemaStore(this._schemaInputs, maybeSchemaStore); + maybeSchemaStore = this._schemaStore = new InputJSONSchemaStore( + this._schemaInputs, + maybeSchemaStore, + ); } + const schemaStore = maybeSchemaStore; const canonizer = new Canonizer(ctx); for (const address of this._additionalSchemaAddresses) { - const schema = await schemaStore.get(address, ctx.debugPrintSchemaResolving); + const schema = await schemaStore.get( + address, + ctx.debugPrintSchemaResolving, + ); if (schema === undefined) { return messageError("SchemaFetchErrorAdditional", { address }); } + canonizer.addSchema(schema, address); } - const resolver = new Resolver(ctx, defined(this._schemaStore), canonizer); + const resolver = new Resolver( + ctx, + defined(this._schemaStore), + canonizer, + ); for (const [normalizedURI, source] of this._schemaSources) { const givenName = source.name; - const refs = await refsInSchemaForURI(resolver, normalizedURI, givenName); + const refs = await refsInSchemaForURI( + resolver, + normalizedURI, + givenName, + ); if (Array.isArray(refs)) { let name: string; - if (this._schemaSources.length === 1 && givenName !== undefined) { + if ( + this._schemaSources.length === 1 && + givenName !== undefined + ) { name = givenName; } else { name = refs[0]; } + this.addTopLevel(name, refs[1]); } else { for (const [refName, ref] of refs) { @@ -1200,18 +1585,23 @@ export class JSONSchemaInput implements Input { } } - await addTypesInSchema(resolver, typeBuilder, this._topLevels, this._attributeProducers); + await addTypesInSchema( + resolver, + typeBuilder, + this._topLevels, + this._attributeProducers, + ); } - addTypesSync(): void { - return panic("addTypesSync not supported in JSONSchemaInput"); + public addTypesSync(): void { + panic("addTypesSync not supported in JSONSchemaInput"); } - async addSource(schemaSource: JSONSchemaSourceData): Promise { - return this.addSourceSync(schemaSource); + public async addSource(schemaSource: JSONSchemaSourceData): Promise { + this.addSourceSync(schemaSource); } - addSourceSync(schemaSource: JSONSchemaSourceData): void { + public addSourceSync(schemaSource: JSONSchemaSourceData): void { const { name, uris, schema, isConverted } = schemaSource; if (isConverted !== true) { @@ -1222,17 +1612,21 @@ export class JSONSchemaInput implements Input { if (uris === undefined) { normalizedURIs = [new URI(name)]; } else { - normalizedURIs = uris.map(uri => { + normalizedURIs = uris.map((uri) => { const normalizedURI = normalizeURI(uri); if (normalizedURI.clone().hash("").toString() === "") { normalizedURI.path(name); } + return normalizedURI; }); } if (schema === undefined) { - assert(uris !== undefined, "URIs must be given if schema source is not specified"); + assert( + uris !== undefined, + "URIs must be given if schema source is not specified", + ); } else { for (let i = 0; i < normalizedURIs.length; i++) { const normalizedURI = normalizedURIs[i]; @@ -1243,8 +1637,10 @@ export class JSONSchemaInput implements Input { if (suffix > 0) { uri.path(`${path}-${suffix}`); } + suffix++; } while (this._schemaInputs.has(uri.toString())); + this._schemaInputs.set(uri.toString(), schema); normalizedURIs[i] = uri.hash(normalizedURI.hash()); } @@ -1256,14 +1652,22 @@ export class JSONSchemaInput implements Input { } } - singleStringSchemaSource(): string | undefined { - if (!this._schemaSources.every(([_, { schema }]) => typeof schema === "string")) { + public singleStringSchemaSource(): string | undefined { + if ( + !this._schemaSources.every( + ([_, { schema }]) => typeof schema === "string", + ) + ) { return undefined; } - const set = new Set(this._schemaSources.map(([_, { schema }]) => schema as string)); + + const set = new Set( + this._schemaSources.map(([_, { schema }]) => schema as string), + ); if (set.size === 1) { return defined(iterableFirst(set)); } + return undefined; } } diff --git a/packages/quicktype-core/src/input/JSONSchemaStore.ts b/packages/quicktype-core/src/input/JSONSchemaStore.ts index dc7ef9aea..d0519e4a4 100644 --- a/packages/quicktype-core/src/input/JSONSchemaStore.ts +++ b/packages/quicktype-core/src/input/JSONSchemaStore.ts @@ -1,4 +1,4 @@ -import { StringMap, assert } from "../support/Support"; +import { type StringMap, assert } from "../support/Support"; export type JSONSchema = StringMap | boolean; @@ -6,33 +6,47 @@ export abstract class JSONSchemaStore { private readonly _schemas = new Map(); private add(address: string, schema: JSONSchema): void { - assert(!this._schemas.has(address), "Cannot set a schema for an address twice"); + assert( + !this._schemas.has(address), + "Cannot set a schema for an address twice", + ); this._schemas.set(address, schema); } // FIXME: Remove the undefined option - abstract fetch(_address: string): Promise; + public abstract fetch(_address: string): Promise; - async get(address: string, debugPrint: boolean): Promise { + public async get( + address: string, + debugPrint: boolean, + ): Promise { let schema = this._schemas.get(address); if (schema !== undefined) { return schema; } + if (debugPrint) { console.log(`trying to fetch ${address}`); } + try { schema = await this.fetch(address); - } catch {} + } catch (e) { + // FIXME: handle or log this error + } + if (schema === undefined) { if (debugPrint) { console.log(`couldn't fetch ${address}`); } + return undefined; } + if (debugPrint) { console.log(`successully fetched ${address}`); } + this.add(address, schema); return schema; } diff --git a/packages/quicktype-core/src/input/PathElement.ts b/packages/quicktype-core/src/input/PathElement.ts new file mode 100644 index 000000000..440484534 --- /dev/null +++ b/packages/quicktype-core/src/input/PathElement.ts @@ -0,0 +1,12 @@ +export enum PathElementKind { + Root = 1, + KeyOrIndex = 2, + Type = 3, + Object = 4, +} + +export type PathElement = + | { kind: PathElementKind.Root } + | { key: string; kind: PathElementKind.KeyOrIndex } + | { index: number; kind: PathElementKind.Type } + | { kind: PathElementKind.Object }; diff --git a/packages/quicktype-core/src/input/PostmanCollection.ts b/packages/quicktype-core/src/input/PostmanCollection.ts index d5de09947..cc4432682 100644 --- a/packages/quicktype-core/src/input/PostmanCollection.ts +++ b/packages/quicktype-core/src/input/PostmanCollection.ts @@ -1,5 +1,7 @@ import { parseJSON } from "../support/Support"; -import { JSONSourceData } from "./Inputs"; + +import type { JSONSourceData } from "./Inputs"; +import type { JSONSchema } from "./JSONSchemaStore"; function isValidJSON(s: string): boolean { try { @@ -12,50 +14,86 @@ function isValidJSON(s: string): boolean { export function sourcesFromPostmanCollection( collectionJSON: string, - collectionJSONAddress?: string -): { sources: JSONSourceData[]; description: string | undefined } { - const sources: JSONSourceData[] = []; + collectionJSONAddress?: string, +): { description: string | undefined; sources: Array> } { + const sources: Array> = []; const descriptions: string[] = []; - function processCollection(c: any): void { - if (typeof c !== "object") return; + function processCollection(c: JSONSchema | undefined): void { + if (typeof c !== "object") { + return; + } + if (Array.isArray(c.item)) { for (const item of c.item) { processCollection(item); } - if (typeof c.info === "object" && typeof c.info.description === "string") { + + if ( + c.info && + typeof c.info === "object" && + "description" in c.info && + typeof c.info?.description === "string" + ) { descriptions.push(c.info.description); } } + if (typeof c.name === "string" && Array.isArray(c.response)) { const samples: string[] = []; for (const r of c.response) { - if (typeof r === "object" && typeof r.body === "string" && isValidJSON(r.body)) { + if ( + typeof r === "object" && + typeof r.body === "string" && + isValidJSON(r.body) + ) { samples.push(r.body); } } + if (samples.length > 0) { - const source: JSONSourceData = { name: c.name, samples }; + const source: JSONSourceData = { + name: c.name, + samples, + }; const sourceDescription = [c.name]; - if (typeof c.request === "object") { - const { method, url } = c.request; - if (method !== undefined && typeof url === "object" && url.raw !== undefined) { + if (c.request && typeof c.request === "object") { + const { method, url } = c.request as { + method: unknown; + url: object; + }; + if ( + method !== undefined && + typeof url === "object" && + "raw" in url && + url.raw !== undefined + ) { sourceDescription.push(`${method} ${url.raw}`); } } - if (typeof c.request === "object" && typeof c.request.description === "string") { + if ( + c.request && + typeof c.request === "object" && + "description" in c.request && + typeof c.request.description === "string" + ) { sourceDescription.push(c.request.description); } - source.description = sourceDescription.length === 0 ? undefined : sourceDescription.join("\n\n"); + source.description = + sourceDescription.length === 0 + ? undefined + : sourceDescription.join("\n\n"); sources.push(source); } } } - processCollection(parseJSON(collectionJSON, "Postman collection", collectionJSONAddress)); + processCollection( + parseJSON(collectionJSON, "Postman collection", collectionJSONAddress), + ); const joinedDescription = descriptions.join("\n\n").trim(); let description: string | undefined = undefined; diff --git a/packages/quicktype-core/src/input/io/$fetch.ci.ts b/packages/quicktype-core/src/input/io/$fetch.ci.ts new file mode 100644 index 000000000..e52711a9d --- /dev/null +++ b/packages/quicktype-core/src/input/io/$fetch.ci.ts @@ -0,0 +1,3 @@ +console.info("=== RUNNING IN CI, USE FETCH.CI ==="); + +export const fetch = require("cross-fetch").default; diff --git a/packages/quicktype-core/src/input/io/$fetch.ts b/packages/quicktype-core/src/input/io/$fetch.ts new file mode 100644 index 000000000..e2dade593 --- /dev/null +++ b/packages/quicktype-core/src/input/io/$fetch.ts @@ -0,0 +1,11 @@ +import type CrossFetch from "cross-fetch"; + +let fetch: typeof CrossFetch; + +try { + fetch = global.fetch ?? require("cross-fetch").default; +} catch { + fetch = require("cross-fetch").default; +} + +export { fetch }; diff --git a/packages/quicktype-core/src/input/io/NodeIO.ts b/packages/quicktype-core/src/input/io/NodeIO.ts index e7cfe588e..b9b71ba92 100644 --- a/packages/quicktype-core/src/input/io/NodeIO.ts +++ b/packages/quicktype-core/src/input/io/NodeIO.ts @@ -1,12 +1,16 @@ -import * as fs from "fs"; -import { Readable } from "readable-stream"; +import * as fs from "node:fs"; + +import { defined, exceptionToString } from "@glideapps/ts-necessities"; import { isNode } from "browser-or-node"; +import isURL from "is-url"; +import type { Readable } from "readable-stream"; + +import { messageError } from "../../Messages"; +import { panic } from "../../support/Support"; + import { getStream } from "./get-stream"; -import { defined, exceptionToString } from "@glideapps/ts-necessities"; -import { messageError, panic } from "../../index"; -const isURL = require("is-url"); -import fetch from "cross-fetch"; +import { fetch } from "./$fetch"; interface HttpHeaders { [key: string]: string; @@ -17,7 +21,7 @@ function parseHeaders(httpHeaders?: string[]): HttpHeaders { return {}; } - return httpHeaders.reduce(function (result: HttpHeaders, httpHeader: string) { + return httpHeaders.reduce((result: HttpHeaders, httpHeader: string) => { if (httpHeader !== undefined && httpHeader.length > 0) { const split = httpHeader.indexOf(":"); @@ -34,35 +38,57 @@ function parseHeaders(httpHeaders?: string[]): HttpHeaders { }, {} as HttpHeaders); } -export async function readableFromFileOrURL(fileOrURL: string, httpHeaders?: string[]): Promise { +export async function readableFromFileOrURL( + fileOrURL: string, + httpHeaders?: string[], +): Promise { try { if (isURL(fileOrURL)) { const response = await fetch(fileOrURL, { - headers: parseHeaders(httpHeaders) + headers: parseHeaders(httpHeaders), }); + return defined(response.body) as unknown as Readable; - } else if (isNode) { + } + + if (isNode) { if (fileOrURL === "-") { // Cast node readable to isomorphic readable from readable-stream return process.stdin as unknown as Readable; } - const filePath = fs.lstatSync(fileOrURL).isSymbolicLink() ? fs.readlinkSync(fileOrURL) : fileOrURL; + + const filePath = fs.lstatSync(fileOrURL).isSymbolicLink() + ? fs.readlinkSync(fileOrURL) + : fileOrURL; if (fs.existsSync(filePath)) { // Cast node readable to isomorphic readable from readable-stream - return fs.createReadStream(filePath, "utf8") as unknown as Readable; + return fs.createReadStream( + filePath, + "utf8", + ) as unknown as Readable; } } } catch (e) { - return messageError("MiscReadError", { fileOrURL, message: exceptionToString(e) }); + return messageError("MiscReadError", { + fileOrURL, + message: exceptionToString(e), + }); } + return messageError("DriverInputFileDoesNotExist", { filename: fileOrURL }); } -export async function readFromFileOrURL(fileOrURL: string, httpHeaders?: string[]): Promise { +export async function readFromFileOrURL( + fileOrURL: string, + httpHeaders?: string[], +): Promise { const readable = await readableFromFileOrURL(fileOrURL, httpHeaders); try { return await getStream(readable); } catch (e) { - return messageError("MiscReadError", { fileOrURL, message: exceptionToString(e) }); + return messageError("MiscReadError", { + fileOrURL, + message: exceptionToString(e), + }); } } diff --git a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts index 19cd6ec30..b578abf3c 100644 --- a/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts +++ b/packages/quicktype-core/src/input/io/get-stream/buffer-stream.ts @@ -1,6 +1,16 @@ -import { Options } from "."; +/* eslint-disable @typescript-eslint/no-explicit-any */ import { PassThrough } from "readable-stream"; +import type { Options } from "./index"; + +export interface BufferedPassThrough extends PassThrough { + getBufferedValue: () => any; + getBufferedLength: () => number; + + // for compat with _Readable.Writable + readonly writableObjectMode: never; +} + export default function bufferStream(opts: Options) { opts = Object.assign({}, opts); @@ -22,11 +32,11 @@ export default function bufferStream(opts: Options) { let len = 0; const ret: any[] = []; const stream = new PassThrough({ - objectMode - }) as any; + objectMode, + }) as BufferedPassThrough; if (encoding) { - stream.setEncoding(encoding); + stream.setEncoding(encoding as BufferEncoding); } stream.on("data", (chunk: any) => { diff --git a/packages/quicktype-core/src/input/io/get-stream/index.ts b/packages/quicktype-core/src/input/io/get-stream/index.ts index 9036e7c89..04c7024b3 100644 --- a/packages/quicktype-core/src/input/io/get-stream/index.ts +++ b/packages/quicktype-core/src/input/io/get-stream/index.ts @@ -1,21 +1,23 @@ -import { Readable } from "readable-stream"; -import bufferStream from "./buffer-stream"; +/* eslint-disable @typescript-eslint/no-explicit-any */ +import type { Readable } from "readable-stream"; + +import bufferStream, { type BufferedPassThrough } from "./buffer-stream"; export interface Options { - maxBuffer?: number; array?: boolean; encoding?: string; + maxBuffer?: number; } -export function getStream(inputStream: Readable, opts: Options = {}) { +export async function getStream(inputStream: Readable, opts: Options = {}) { if (!inputStream) { - return Promise.reject(new Error("Expected a stream")); + return await Promise.reject(new Error("Expected a stream")); } - opts = Object.assign({ maxBuffer: Infinity }, opts); + opts = Object.assign({ maxBuffer: Number.POSITIVE_INFINITY }, opts); - const maxBuffer = opts.maxBuffer || Infinity; - let stream: any; + const maxBuffer = opts.maxBuffer ?? Number.POSITIVE_INFINITY; + let stream: BufferedPassThrough; let clean; const p = new Promise((resolve, reject) => { @@ -48,15 +50,15 @@ export function getStream(inputStream: Readable, opts: Options = {}) { }; }); - p.then(clean, clean); - - return p.then(() => stream.getBufferedValue()); + return await p.then(clean, clean).then(() => stream.getBufferedValue()); } +// FIXME: should these be async ? export function buffer(stream: Readable, opts: Options = {}) { - getStream(stream, Object.assign({}, opts, { encoding: "buffer" })); + void getStream(stream, Object.assign({}, opts, { encoding: "buffer" })); } +// FIXME: should these be async ? export function array(stream: Readable, opts: Options = {}) { - getStream(stream, Object.assign({}, opts, { array: true })); + void getStream(stream, Object.assign({}, opts, { array: true })); } diff --git a/packages/quicktype-core/src/language/All.ts b/packages/quicktype-core/src/language/All.ts index 19313870a..be1a29a4c 100644 --- a/packages/quicktype-core/src/language/All.ts +++ b/packages/quicktype-core/src/language/All.ts @@ -1,70 +1,101 @@ -import { iterableFind } from "collection-utils"; +import type { TargetLanguage } from "../TargetLanguage"; -import { TargetLanguage } from "../TargetLanguage"; - -import { CSharpTargetLanguage } from "./CSharp"; -import { GoTargetLanguage } from "./Golang"; import { CJSONTargetLanguage } from "./CJSON"; import { CPlusPlusTargetLanguage } from "./CPlusPlus"; -import { ObjectiveCTargetLanguage } from "./Objective-C"; +import { CrystalTargetLanguage } from "./Crystal"; +import { CSharpTargetLanguage } from "./CSharp"; +import { DartTargetLanguage } from "./Dart"; +import { ElixirTargetLanguage } from "./Elixir"; +import { ElmTargetLanguage } from "./Elm"; +import { GoTargetLanguage } from "./Golang"; +import { HaskellTargetLanguage } from "./Haskell"; import { JavaTargetLanguage } from "./Java"; import { JavaScriptTargetLanguage } from "./JavaScript"; import { JavaScriptPropTypesTargetLanguage } from "./JavaScriptPropTypes"; -import { TypeScriptTargetLanguage, FlowTargetLanguage } from "./TypeScriptFlow"; -import { SwiftTargetLanguage } from "./Swift"; +import { JSONSchemaTargetLanguage } from "./JSONSchema"; import { KotlinTargetLanguage } from "./Kotlin"; +import { ObjectiveCTargetLanguage } from "./Objective-C"; +import { PhpTargetLanguage } from "./Php"; +import { PikeTargetLanguage } from "./Pike"; +import { PythonTargetLanguage } from "./Python"; +import { RubyTargetLanguage } from "./Ruby"; +import { RustTargetLanguage } from "./Rust"; import { Scala3TargetLanguage } from "./Scala3"; import { SmithyTargetLanguage } from "./Smithy4s"; -import { ElmTargetLanguage } from "./Elm"; -import { JSONSchemaTargetLanguage } from "./JSONSchema"; -import { RustTargetLanguage } from "./Rust"; -import { CrystalTargetLanguage } from "./Crystal"; -import { RubyTargetLanguage } from "./ruby"; -import { DartTargetLanguage } from "./Dart"; -import { PythonTargetLanguage } from "./Python"; -import { PikeTargetLanguage } from "./Pike"; -import { HaskellTargetLanguage } from "./Haskell"; -import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; -import { PhpTargetLanguage } from "./Php"; +import { SwiftTargetLanguage } from "./Swift"; +import type { + LanguageDisplayName, + LanguageName, + LanguageNameMap, +} from "./types"; import { TypeScriptEffectSchemaTargetLanguage } from "./TypeScriptEffectSchema"; +import { FlowTargetLanguage, TypeScriptTargetLanguage } from "./TypeScriptFlow"; +import { TypeScriptZodTargetLanguage } from "./TypeScriptZod"; -export const all: TargetLanguage[] = [ - new CSharpTargetLanguage(), - new GoTargetLanguage(), - new RustTargetLanguage(), - new CrystalTargetLanguage(), +export const all = [ new CJSONTargetLanguage(), new CPlusPlusTargetLanguage(), - new ObjectiveCTargetLanguage(), + new CrystalTargetLanguage(), + new CSharpTargetLanguage(), + new DartTargetLanguage(), + new ElixirTargetLanguage(), + new ElmTargetLanguage(), + new FlowTargetLanguage(), + new GoTargetLanguage(), + new HaskellTargetLanguage(), new JavaTargetLanguage(), - new TypeScriptTargetLanguage(), new JavaScriptTargetLanguage(), new JavaScriptPropTypesTargetLanguage(), - new FlowTargetLanguage(), - new SwiftTargetLanguage(), - new Scala3TargetLanguage(), - new SmithyTargetLanguage(), - new KotlinTargetLanguage(), - new ElmTargetLanguage(), new JSONSchemaTargetLanguage(), - new RubyTargetLanguage(), - new DartTargetLanguage(), - new PythonTargetLanguage("Python", ["python", "py"], "py"), + new KotlinTargetLanguage(), + new ObjectiveCTargetLanguage(), + new PhpTargetLanguage(), new PikeTargetLanguage(), - new HaskellTargetLanguage(), - new TypeScriptZodTargetLanguage(), + new PythonTargetLanguage(), + new RubyTargetLanguage(), + new RustTargetLanguage(), + new Scala3TargetLanguage(), + new SmithyTargetLanguage(), + new SwiftTargetLanguage(), + new TypeScriptTargetLanguage(), new TypeScriptEffectSchemaTargetLanguage(), - new PhpTargetLanguage() -]; + new TypeScriptZodTargetLanguage(), +] as const; -export function languageNamed(name: string, targetLanguages?: TargetLanguage[]): TargetLanguage | undefined { - if (targetLanguages === undefined) { - targetLanguages = all; - } - const maybeTargetLanguage = iterableFind( - targetLanguages, - l => l.names.indexOf(name) >= 0 || l.displayName === name +all satisfies readonly TargetLanguage[]; + +export function languageNamed( + name: Name, + targetLanguages: readonly TargetLanguage[] = all, +): LanguageNameMap[Name] { + const foundLanguage = targetLanguages.find((language) => + language.names.includes(name), ); - if (maybeTargetLanguage !== undefined) return maybeTargetLanguage; - return iterableFind(targetLanguages, l => l.extension === name); + if (!foundLanguage) { + throw new Error(`Unknown language name: ${name}`); + } + + return foundLanguage as LanguageNameMap[Name]; +} + +export function isLanguageName(maybeName: string): maybeName is LanguageName { + if ( + all.some((lang) => + (lang.names as readonly string[]).includes(maybeName), + ) + ) { + return true; + } + + return false; +} + +export function isLanguageDisplayName( + maybeName: string, +): maybeName is LanguageDisplayName { + if (all.some((lang) => lang.displayName === maybeName)) { + return true; + } + + return false; } diff --git a/packages/quicktype-core/src/language/CJSON.ts b/packages/quicktype-core/src/language/CJSON.ts deleted file mode 100644 index 2a9ee43c5..000000000 --- a/packages/quicktype-core/src/language/CJSON.ts +++ /dev/null @@ -1,4136 +0,0 @@ -/** - * CJSON.ts - * This file is used to generate cJSON code with quicktype - * The generated code depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable - * - * Similarly to C++ generator, it is possible to generate a single header file or multiple header files. - * To generate multiple header files, use the following option: --source-style multi-source - * - * JSON data are represented using structures, and functions in the cJSON style are created to use them. - * To parse json data from json string use the following: struct * data = cJSON_Parse(); - * To get json data from cJSON object use the following: struct * data = cJSON_GetValue(); - * To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create(); - * To print json string from json data use the following: char * string = cJSON_Print(); - * To delete json data use the following: cJSON_Delete(); - * - * TODO list for futur enhancements: - * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map - * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) - * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) - * - Support of pure Any type for example providing a callback from the application to handle these cases dynamically - * See test/languages.ts for the test cases which are not implmented/checked. - */ - -/* Imports */ -import { TargetLanguage } from "../TargetLanguage"; -import { Type, TypeKind, ClassType, ArrayType, MapType, EnumType, UnionType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { NameStyle, Name, Namer, funPrefixNamer } from "../Naming"; -import { Sourcelike } from "../Source"; -import { - allUpperWordStyle, - legalizeCharacters, - isAscii, - isLetterOrUnderscoreOrDigit, - NamingStyle, - makeNameStyle -} from "../support/Strings"; -import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { EnumOption, StringOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { assert } from "../support/Support"; -import { RenderContext } from "../Renderer"; -import { getAccessorName } from "../attributes/AccessorNames"; -import { enumCaseValues } from "../attributes/EnumValues"; - -/* Naming styles */ -const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; -const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; -const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; -const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; -const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; -const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; - -/* cJSON generator options */ -export const cJSONOptions = { - typeSourceStyle: new EnumOption( - "source-style", - "Source code generation type, whether to generate single or multiple source files", - [ - ["single-source", true], - ["multi-source", false] - ], - "single-source", - "secondary" - ), - typeIntegerSize: new EnumOption( - "integer-size", - "Integer code generation type (int64_t by default)", - [ - ["int8_t", "int8_t"], - ["int16_t", "int16_t"], - ["int32_t", "int32_t"], - ["int64_t", "int64_t"] - ], - "int64_t", - "secondary" - ), - hashtableSize: new StringOption( - "hashtable-size", - "Hashtable size, used when maps are created (64 by default)", - "SIZE", - "64" - ), - addTypedefAlias: new EnumOption( - "typedef-alias", - "Add typedef alias to unions, structs, and enums (no typedef by default)", - [ - ["no-typedef", false], - ["add-typedef", true] - ], - "no-typedef", - "secondary" - ), - printStyle: new EnumOption( - "print-style", - "Which cJSON print should be used (formatted by default)", - [ - ["print-formatted", false], - ["print-unformatted", true] - ], - "print-formatted", - "secondary" - ), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ - pascalValue, - underscoreValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ - underscoreValue, - pascalValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ - upperUnderscoreValue, - underscoreValue, - pascalValue, - camelValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]) -}; - -/* cJSON generator target language */ -export class CJSONTargetLanguage extends TargetLanguage { - /** - * Constructor - * @param displayName: display name - * @params names: names - * @param extension: extension of files - */ - constructor(displayName = "C (cJSON)", names: string[] = ["cjson", "cJSON"], extension = "h") { - super(displayName, names, extension); - } - - /** - * Return cJSON generator options - * @return cJSON generator options array - */ - protected getOptions(): Option[] { - return [ - cJSONOptions.typeSourceStyle, - cJSONOptions.typeIntegerSize, - cJSONOptions.addTypedefAlias, - cJSONOptions.printStyle, - cJSONOptions.hashtableSize, - cJSONOptions.typeNamingStyle, - cJSONOptions.memberNamingStyle, - cJSONOptions.enumeratorNamingStyle - ]; - } - - /** - * Indicate if language support union with both number types - * @return true - */ - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - /** - * Indicate if language support optional class properties - * @return true - */ - get supportsOptionalClassProperties(): boolean { - return true; - } - - /** - * Create renderer - * @param renderContext: render context - * @param untypedOptionValues - * @return cJSON renderer - */ - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): CJSONRenderer { - return new CJSONRenderer(this, renderContext, getOptionValues(cJSONOptions, untypedOptionValues)); - } -} - -/* Function used to format names */ -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -/* Forbidden names for namespace */ -const keywords = [ - /* C and C++ keywords */ - "alignas", - "alignof", - "and", - "and_eq", - "asm", - "atomic_cancel", - "atomic_commit", - "atomic_noexcept", - "auto", - "bitand", - "bitor", - "bool", - "break", - "case", - "catch", - "char", - "char16_t", - "char32_t", - "class", - "compl", - "concept", - "const", - "constexpr", - "const_cast", - "continue", - "co_await", - "co_return", - "co_yield", - "decltype", - "default", - "delete", - "do", - "double", - "dynamic_cast", - "else", - "enum", - "explicit", - "export", - "extern", - "false", - "float", - "for", - "friend", - "goto", - "if", - "import", - "inline", - "int", - "long", - "module", - "mutable", - "namespace", - "new", - "noexcept", - "not", - "not_eq", - "nullptr", - "operator", - "or", - "or_eq", - "private", - "protected", - "public", - "register", - "reinterpret_cast", - "requires", - "restrict", - "return", - "short", - "signed", - "sizeof", - "static", - "static_assert", - "static_cast", - "struct", - "switch", - "synchronized", - "template", - "this", - "thread_local", - "throw", - "true", - "try", - "typedef", - "typeid", - "typename", - "typeof", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "while", - "xor", - "xor_eq", - "override", - "final", - "transaction_safe", - "transaction_safe_dynamic", - "NULL", - /* cJSON keywords */ - "Array", - "ArrayReference", - "Bool", - "DoubleArray", - "False", - "FloatArray", - "IntArray", - "Object", - "Null", - "Number", - "Raw", - "String", - "StringArray", - "StringReference", - "True" -]; - -/* Used to build forbidden global names */ -export enum GlobalNames { - ClassMemberConstraints, - ClassMemberConstraintException, - ValueTooLowException, - ValueTooHighException, - ValueTooShortException, - ValueTooLongException, - InvalidPatternException, - CheckConstraint -} - -/* To be able to support circles in multiple files - e.g. class#A using class#B using class#A (obviously not directly) we can forward declare them */ -export enum IncludeKind { - ForwardDeclare, - Include -} - -/* Used to map includes */ -export type IncludeRecord = { - kind: IncludeKind | undefined /* How to include that */; - typeKind: TypeKind | undefined /* What exactly to include */; -}; - -/* Used to map includes */ -export type TypeRecord = { - name: Name; - type: Type; - level: number; - variant: boolean; - forceInclude: boolean; -}; - -/* Map each and every unique type to a include kind, e.g. how to include the given type */ -export type IncludeMap = Map; - -/* cJSON type */ -export type TypeCJSON = { - cType: Sourcelike /* C type */; - optionalQualifier: string /* C optional qualifier, empty string if not defined */; - cjsonType: string /* cJSON type */; - isType: Sourcelike /* cJSON check type function */; - getValue: Sourcelike /* cJSON get value function */; - addToObject: Sourcelike /* cJSON add to object function */; - createObject: Sourcelike /* cJSON create object function */; - deleteType: Sourcelike /* cJSON delete function */; - items: TypeCJSON | undefined /* Sub-items, used for arrays and map */; - isNullable: boolean /* True if the field is nullable */; -}; - -/* cJSON renderer */ -export class CJSONRenderer extends ConvenienceRenderer { - private currentFilename: string | undefined; /* Current filename */ - private memberNameStyle: NameStyle; /* Member name style */ - private namedTypeNameStyle: NameStyle; /* Named type name style */ - private forbiddenGlobalNames: string[]; /* Forbidden global names */ - protected readonly typeIntegerSize: string; /* Integer code generation type */ - protected readonly hashtableSize: string; /* Hashtable default size */ - protected readonly typeNamingStyle: NamingStyle; /* Type naming style */ - protected readonly enumeratorNamingStyle: NamingStyle; /* Enum naming style */ - - /** - * Constructor - * @param targetLanguage: target language - * @param renderContext: render context - * @param _options: renderer options - */ - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - this.typeIntegerSize = _options.typeIntegerSize; - this.hashtableSize = _options.hashtableSize; - this.typeNamingStyle = _options.typeNamingStyle; - this.namedTypeNameStyle = makeNameStyle(this.typeNamingStyle, legalizeName); - this.enumeratorNamingStyle = _options.enumeratorNamingStyle; - this.memberNameStyle = makeNameStyle(_options.memberNamingStyle, legalizeName); - this.forbiddenGlobalNames = []; - for (const type of numberEnumValues(GlobalNames)) { - const genName = this.namedTypeNameStyle(GlobalNames[type]); - this.forbiddenGlobalNames.push(genName); - } - } - - /** - * Build forbidden names for namespace - * @return Forbidden names for namespace - */ - protected forbiddenNamesForGlobalNamespace(): string[] { - return [...keywords, ...this.forbiddenGlobalNames]; - } - - /** - * Build forbidden names for enums - * @return Forbidden names for enums - */ - protected forbiddenForEnumCases(_enumType: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - /** - * Build forbidden names for unions members - * @return Forbidden names for unions members - */ - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - /** - * Build forbidden names for objects - * @return Forbidden names for objects - */ - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - /** - * Build types member names - * @return types member namer - */ - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("types", this.namedTypeNameStyle); - } - - /** - * Build object properties member names - * @return object properties member namer - */ - protected namerForObjectProperty(): Namer { - return funPrefixNamer("members", this.memberNameStyle); - } - - /** - * Build union member names - * @return union member namer - */ - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("members", this.memberNameStyle); - } - - /** - * Build enum member names - * @return enum member namer - */ - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enumerators", makeNameStyle(this.enumeratorNamingStyle, legalizeName)); - } - - /** - * Override of super proposeUnionMemberName function - * @param unionType: union type - * @param unionName: union name - * @param fieldType: field type - * @param lookup: Lookup function - * @return Proposed union member name - */ - protected proposeUnionMemberName( - unionType: UnionType, - unionName: Name, - fieldType: Type, - lookup: (n: Name) => string - ): string { - let fieldName = super.proposeUnionMemberName(unionType, unionName, fieldType, lookup); - if ("bool" === fieldName) { - fieldName = "boolean"; - } else if ("double" === fieldName) { - fieldName = "number"; - } - return fieldName; - } - - /** - * Function called to emit typedef alias for a a given type - * @param fieldType: the variable type - * @param fieldName: name of the variable - */ - protected emitTypdefAlias(fieldType: Type, fieldName: Name) { - if (this._options.addTypedefAlias) { - this.emitLine("typedef ", this.quicktypeTypeToCJSON(fieldType, false).cType, " ", fieldName, ";"); - this.ensureBlankLine(); - } - } - - /** - * Function called to create header file(s) - * @param proposedFilename: source filename provided from stdin - */ - protected emitSourceStructure(proposedFilename: string): void { - /* Depending of source style option, generate a unique header or multiple header files */ - if (this._options.typeSourceStyle) { - this.emitSingleSourceStructure(proposedFilename); - } else { - this.emitMultiSourceStructure(); - } - } - - /** - * Function called to create a single header file with types and generators - * @param proposedFilename: source filename provided from stdin - */ - protected emitSingleSourceStructure(proposedFilename: string): void { - /* Create file */ - this.startFile(proposedFilename); - - /* Create types */ - this.forEachDeclaration("leading-and-interposing", decl => { - if (decl.kind === "forward") { - this.emitLine("struct ", this.nameForNamedType(decl.type), ";"); - } else if (decl.kind === "define") { - const type = decl.type; - if (type instanceof ClassType) { - this.emitClassTypedef(type); - } else if (type instanceof EnumType) { - this.emitEnumTypedef(type); - } else if (type instanceof UnionType) { - this.emitUnionTypedef(type); - } else { - panic("Cannot declare type"); - } - } else { - assertNever(decl.kind); - } - }); - - /* Create top level type */ - this.forEachTopLevel( - "leading", - (type: Type, className: Name) => this.emitTopLevelTypedef(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined - ); - - /* Create enum prototypes */ - this.forEachEnum("leading-and-interposing", (enumType: EnumType, _enumName: Name) => - this.emitEnumPrototypes(enumType) - ); - - /* Create union prototypes */ - this.forEachUnion("leading-and-interposing", (unionType: UnionType) => this.emitUnionPrototypes(unionType)); - - /* Create class prototypes */ - this.forEachObject("leading-and-interposing", (classType: ClassType, _className: Name) => - this.emitClassPrototypes(classType) - ); - - /* Create top level prototypes */ - this.forEachTopLevel( - "leading", - (type: Type, className: Name) => this.emitTopLevelPrototypes(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined - ); - - /* Create enum functions */ - this.forEachEnum("leading-and-interposing", (enumType: EnumType, _enumName: Name) => - this.emitEnumFunctions(enumType) - ); - - /* Create union functions */ - this.forEachUnion("leading-and-interposing", (unionType: UnionType) => this.emitUnionFunctions(unionType)); - - /* Create class functions */ - this.forEachObject("leading-and-interposing", (classType: ClassType, _className: Name) => - this.emitClassFunctions(classType) - ); - - /* Create top level functions */ - this.forEachTopLevel( - "leading", - (type: Type, className: Name) => this.emitTopLevelFunctions(type, className), - type => this.namedTypeToNameForTopLevel(type) === undefined - ); - - /* Close file */ - this.finishFile(); - } - - /** - * Function called to create a multiple header files with types and generators - */ - protected emitMultiSourceStructure(): void { - /* Array of includes */ - let includes: string[]; - - /* Create each file */ - this.forEachNamedType( - "leading-and-interposing", - (classType: ClassType, _name: Name) => { - this.emitClass(classType, includes); - }, - (enumType, _name) => { - this.emitEnum(enumType, includes); - }, - (unionType, _name) => { - this.emitUnion(unionType, includes); - } - ); - - /* Create top level file */ - this.forEachTopLevel( - "leading", - (type: Type, className: Name) => this.emitTopLevel(type, className, includes), - type => this.namedTypeToNameForTopLevel(type) === undefined - ); - } - - /** - * Function called to create an enum header files with types and generators - * @param enumType: enum type - * @param includes: Array of includes - */ - protected emitEnum(enumType: EnumType, includes: string[]): void { - /* Create file */ - const enumName = this.nameForNamedType(enumType); - const filename = this.sourcelikeToString(enumName).concat(".h"); - includes.push(filename); - this.startFile(filename); - - /* Create includes */ - this.emitIncludes(enumType, this.sourcelikeToString(filename)); - - /* Create types */ - this.emitEnumTypedef(enumType); - - /* Create prototypes */ - this.emitEnumPrototypes(enumType); - - /* Create functions */ - this.emitEnumFunctions(enumType); - - /* Close file */ - this.finishFile(); - } - - /** - * Function called to create enum typedef - * @param enumType: enum type - */ - protected emitEnumTypedef(enumType: EnumType): void { - /* FIXME: Now there is a language with need of global enum name, see FIXME in makeNameForEnumCase of ConvenienceRenderer.ts, should simplify here when fixed */ - - const enumName = this.nameForNamedType(enumType); - const enumValues = enumCaseValues(enumType, this.targetLanguage.name); - - this.emitDescription(this.descriptionForType(enumType)); - this.emitBlock( - ["enum ", enumName], - () => { - const combinedName = allUpperWordStyle(this.sourcelikeToString(enumName)); - this.forEachEnumCase(enumType, "none", (name, jsonName) => { - if (enumValues !== undefined) { - const [enumValue] = getAccessorName(enumValues, jsonName); - if (enumValue !== undefined) { - this.emitLine(combinedName, "_", name, " = ", enumValue.toString(), ","); - } else { - this.emitLine(combinedName, "_", name, ","); - } - } else { - this.emitLine(combinedName, "_", name, ","); - } - }); - }, - "", - true - ); - this.ensureBlankLine(); - this.emitTypdefAlias(enumType, enumName); - } - - /** - * Function called to create enum prototypes - * @param enumType: enum type - */ - protected emitEnumPrototypes(enumType: EnumType): void { - const enumName = this.nameForNamedType(enumType); - - this.emitLine("enum ", enumName, " cJSON_Get", enumName, "Value(", this.withConst("cJSON"), " * j);"); - this.emitLine("cJSON * cJSON_Create", enumName, "(", this.withConst(["enum ", enumName]), " x);"); - this.ensureBlankLine(); - } - - /** - * Function called to create enum functions - * @param enumType: enum type - */ - protected emitEnumFunctions(enumType: EnumType): void { - const enumName = this.nameForNamedType(enumType); - - /* Create cJSON to enumName generator function */ - this.emitBlock(["enum ", enumName, " cJSON_Get", enumName, "Value(", this.withConst("cJSON"), " * j)"], () => { - this.emitLine("enum ", enumName, " x = 0;"); - this.emitBlock(["if (NULL != j)"], () => { - let onFirst = true; - const combinedName = allUpperWordStyle(this.sourcelikeToString(enumName)); - this.forEachEnumCase(enumType, "none", (name, jsonName) => { - this.emitLine( - onFirst ? "" : "else ", - 'if (!strcmp(cJSON_GetStringValue(j), "', - jsonName, - '")) x = ', - combinedName, - "_", - name, - ";" - ); - onFirst = false; - }); - }); - this.emitLine("return x;"); - }); - this.ensureBlankLine(); - - /* Create enumName to cJSON generator function */ - this.emitBlock(["cJSON * cJSON_Create", enumName, "(", this.withConst(["enum ", enumName]), " x)"], () => { - this.emitLine("cJSON * j = NULL;"); - this.emitBlock(["switch (x)"], () => { - const combinedName = allUpperWordStyle(this.sourcelikeToString(enumName)); - this.forEachEnumCase(enumType, "none", (name, jsonName) => { - this.emitLine( - "case ", - combinedName, - "_", - name, - ': j = cJSON_CreateString("', - jsonName, - '"); break;' - ); - }); - }); - this.emitLine("return j;"); - }); - this.ensureBlankLine(); - } - - /** - * Function called to create a union header files with types and generators - * @param unionType: union type - * @param includes: Array of includes - */ - protected emitUnion(unionType: UnionType, includes: string[]): void { - /* Create file */ - const unionName = this.nameForNamedType(unionType); - const filename = this.sourcelikeToString(unionName).concat(".h"); - includes.push(filename); - this.startFile(filename); - - /* Create includes */ - this.emitIncludes(unionType, this.sourcelikeToString(filename)); - - /* Create types */ - this.emitUnionTypedef(unionType); - - /* Create prototypes */ - this.emitUnionPrototypes(unionType); - - /* Create functions */ - this.emitUnionFunctions(unionType); - - /* Close file */ - this.finishFile(); - } - - /** - * Function called to create union typedef - * @param unionType: union type - */ - protected emitUnionTypedef(unionType: UnionType): void { - const [_hasNull, nonNulls] = removeNullFromUnion(unionType); - const unionName = this.nameForNamedType(unionType); - - this.emitDescription(this.descriptionForType(unionType)); - this.emitBlock( - ["struct ", unionName], - () => { - this.emitLine("int type;"); - this.emitBlock( - ["union"], - () => { - for (const type of nonNulls) { - const cJSON = this.quicktypeTypeToCJSON(type, false); - this.emitLine( - cJSON.cType, - cJSON.optionalQualifier !== "" ? " " : "", - cJSON.optionalQualifier, - " ", - this.nameForUnionMember(unionType, type), - ";" - ); - } - }, - "value", - true - ); - }, - "", - true - ); - this.ensureBlankLine(); - this.emitTypdefAlias(unionType, unionName); - } - - /** - * Function called to create union prototypes - * @param unionType: union type - */ - protected emitUnionPrototypes(unionType: UnionType): void { - const unionName = this.nameForNamedType(unionType); - - this.emitLine("struct ", unionName, " * cJSON_Get", unionName, "Value(const cJSON * j);"); - this.emitLine("cJSON * cJSON_Create", unionName, "(", this.withConst(["struct ", unionName]), " * x);"); - this.emitLine("void cJSON_Delete", unionName, "(struct ", unionName, " * x);"); - this.ensureBlankLine(); - } - - /** - * Function called to create union functions - * @param unionType: union type - */ - protected emitUnionFunctions(unionType: UnionType): void { - const [hasNull, nonNulls] = removeNullFromUnion(unionType); - const unionName = this.nameForNamedType(unionType); - - /* Create cJSON to unionType generator function */ - this.emitBlock(["struct ", unionName, " * cJSON_Get", unionName, "Value(const cJSON * j)"], () => { - let onFirst = true; - this.emitLine("struct ", unionName, " * x = cJSON_malloc(sizeof(struct ", unionName, "));"); - this.emitBlock(["if (NULL != x)"], () => { - this.emitLine("memset(x, 0, sizeof(struct ", unionName, "));"); - if (hasNull !== null) { - this.emitBlock(["if (cJSON_IsNull(j))"], () => { - this.emitLine("x->type = cJSON_NULL;"); - }); - onFirst = false; - } - for (const type of nonNulls) { - const cJSON = this.quicktypeTypeToCJSON(type, false); - this.emitBlock([onFirst === true ? "if (" : "else if (", cJSON.isType, "(j))"], () => { - this.emitLine("x->type = ", cJSON.cjsonType, ";"); - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - const level = 0; - const child_level = 1; - this.emitLine(cJSON.cType, " * x", child_level.toString(), " = list_create(false, NULL);"); - this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); - this.emitBlock( - [ - "cJSON_ArrayForEach(e", - child_level.toString(), - ", j", - level > 0 ? level.toString() : "", - ")" - ], - () => { - const add = (cJSON: TypeCJSON, level: number, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", (", - cJSON.items!.cType, - " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", strdup(", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ")), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - "), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - this.emitLine( - cJSON.items!.cType, - " * tmp", - level > 0 ? level.toString() : "", - " = cJSON_malloc(sizeof(", - cJSON.items!.cType, - "));" - ); - this.emitBlock( - ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], - () => { - this.emitLine( - "* tmp", - level > 0 ? level.toString() : "", - " = ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ");" - ); - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", tmp", - level > 0 ? level.toString() : "", - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - ["if (!cJSON_IsNull(e", child_level.toString(), "))"], - () => { - add(cJSON, level, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", (void *)0xDEADBEEF, sizeof(void *));" - ); - }); - } else { - add(cJSON, level, child_level); - } - } - ); - this.emitLine( - "x->value.", - this.nameForUnionMember(unionType, type), - " = x", - child_level.toString(), - ";" - ); - }); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - const level = 0; - const child_level = 1; - this.emitLine( - cJSON.cType, - " * x", - child_level.toString(), - " = hashtable_create(", - this.hashtableSize, - ", false);" - ); - this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); - this.emitBlock( - [ - "cJSON_ArrayForEach(e", - child_level.toString(), - ", j", - level > 0 ? level.toString() : "", - ")" - ], - () => { - const add = (cJSON: TypeCJSON, level: number, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, (", - cJSON.items!.cType, - " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, strdup(", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ")), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - "), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - this.emitLine( - cJSON.items!.cType, - " * tmp", - level > 0 ? level.toString() : "", - " = cJSON_malloc(sizeof(", - cJSON.items!.cType, - "));" - ); - this.emitBlock( - ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], - () => { - this.emitLine( - "* tmp", - level > 0 ? level.toString() : "", - " = ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ");" - ); - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, tmp", - level > 0 ? level.toString() : "", - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - ["if (!cJSON_IsNull(e", child_level.toString(), "))"], - () => { - add(cJSON, level, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, (void *)0xDEADBEEF, sizeof(void *));" - ); - }); - } else { - add(cJSON, level, child_level); - } - } - ); - this.emitLine( - "x->value.", - this.nameForUnionMember(unionType, type), - " = x", - child_level.toString(), - ";" - ); - }); - } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { - this.emitLine( - "x->value.", - this.nameForUnionMember(unionType, type), - " = (", - cJSON.cType, - " *)0xDEADBEEF;" - ); - } else if (cJSON.cjsonType === "cJSON_String") { - this.emitLine( - "x->value.", - this.nameForUnionMember(unionType, type), - " = strdup(", - cJSON.getValue, - "(j));" - ); - } else { - this.emitLine( - "x->value.", - this.nameForUnionMember(unionType, type), - " = ", - cJSON.getValue, - "(j);" - ); - } - }); - onFirst = false; - } - }); - this.emitLine("return x;"); - }); - this.ensureBlankLine(); - - /* Create unionName to cJSON generator function */ - this.emitBlock( - ["cJSON * cJSON_Create", unionName, "(", this.withConst(["struct ", unionName]), " * x)"], - () => { - this.emitLine("cJSON * j = NULL;"); - this.emitBlock(["if (NULL != x)"], () => { - let onFirst = true; - if (hasNull !== null) { - this.emitBlock(["if (cJSON_NULL == x->type)"], () => { - this.emitLine("j = cJSON_CreateNull();"); - }); - onFirst = false; - } - for (const type of nonNulls) { - const cJSON = this.quicktypeTypeToCJSON(type, false); - this.emitBlock( - [onFirst === true ? "if (" : "else if (", cJSON.cjsonType, " == x->type)"], - () => { - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - const level = 0; - const child_level = 1; - this.emitLine( - "cJSON * j", - child_level.toString(), - " = ", - cJSON.createObject, - "();" - ); - this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { - this.emitLine( - cJSON.items!.cType, - " * x", - child_level.toString(), - " = list_get_head(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - const add = (cJSON: TypeCJSON, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.items!.createObject, - "());" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.items!.createObject, - "(x", - child_level.toString(), - "));" - ); - } else { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.items!.createObject, - "(*x", - child_level.toString(), - "));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], - () => { - add(cJSON, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", cJSON_CreateNull());" - ); - }); - } else { - add(cJSON, child_level); - } - this.emitLine( - "x", - child_level.toString(), - " = list_get_next(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - }); - this.emitLine("j = j", child_level.toString(), ";"); - }); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - const level = 0; - const child_level = 1; - this.emitLine( - "cJSON * j", - child_level.toString(), - " = ", - cJSON.createObject, - "();" - ); - this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { - this.emitLine("char **keys", child_level.toString(), " = NULL;"); - this.emitLine( - "size_t count", - child_level.toString(), - " = hashtable_get_keys(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ", &keys", - child_level.toString(), - ");" - ); - this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { - this.emitBlock( - [ - "for (size_t index", - child_level.toString(), - " = 0; index", - child_level.toString(), - " < count", - child_level.toString(), - "; index", - child_level.toString(), - "++)" - ], - () => { - this.emitLine( - cJSON.items!.cType, - " *x", - child_level.toString(), - " = hashtable_lookup(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "]);" - ); - const add = (cJSON: TypeCJSON, child_level: number) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], ", - cJSON.items!.createObject, - "());" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], ", - cJSON.items!.createObject, - "(x", - child_level.toString(), - "));" - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], ", - cJSON.items!.createObject, - "(*x", - child_level.toString(), - "));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if ((void *)0xDEADBEEF != x", - child_level.toString(), - ")" - ], - () => { - add(cJSON, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], cJSON_CreateNull());" - ); - }); - } else { - add(cJSON, child_level); - } - } - ); - this.emitLine("cJSON_free(keys", child_level.toString(), ");"); - }); - this.emitLine("j = j", child_level.toString(), ";"); - }); - } else if (cJSON.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.cjsonType === "cJSON_NULL") { - this.emitLine("j = ", cJSON.createObject, "();"); - } else { - this.emitLine( - "j = ", - cJSON.createObject, - "(x->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - } - } - ); - onFirst = false; - } - }); - this.emitLine("return j;"); - } - ); - this.ensureBlankLine(); - - /* Create unionName delete function */ - this.emitBlock(["void cJSON_Delete", unionName, "(struct ", unionName, " * x)"], () => { - this.emitBlock(["if (NULL != x)"], () => { - let onFirst = true; - for (const type of nonNulls) { - const cJSON = this.quicktypeTypeToCJSON(type, false); - this.emitBlock([onFirst === true ? "if (" : "else if (", cJSON.cjsonType, " == x->type)"], () => { - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - const level = 0; - const child_level = 1; - this.emitBlock( - [ - "if (NULL != x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ")" - ], - () => { - this.emitLine( - cJSON.items!.cType, - " * x", - child_level.toString(), - " = list_get_head(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - /* Nothing to do */ - } else { - if (cJSON.items!.isNullable) { - this.emitBlock( - ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], - () => { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - ); - } else { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - } - this.emitLine( - "x", - child_level.toString(), - " = list_get_next(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - }); - this.emitLine( - cJSON.deleteType, - "(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - } - ); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - const level = 0; - const child_level = 1; - this.emitBlock( - [ - "if (NULL != x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ")" - ], - () => { - this.emitLine("char **keys", child_level.toString(), " = NULL;"); - this.emitLine( - "size_t count", - child_level.toString(), - " = hashtable_get_keys(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ", &keys", - child_level.toString(), - ");" - ); - this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { - this.emitBlock( - [ - "for (size_t index", - child_level.toString(), - " = 0; index", - child_level.toString(), - " < count", - child_level.toString(), - "; index", - child_level.toString(), - "++)" - ], - () => { - this.emitLine( - cJSON.items!.cType, - " *x", - child_level.toString(), - " = hashtable_lookup(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "]);" - ); - this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - /* Nothing to do */ - } else { - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if ((void *)0xDEADBEEF != x", - child_level.toString(), - ")" - ], - () => { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - ); - } else { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - } - }); - } - ); - this.emitLine("cJSON_free(keys", child_level.toString(), ");"); - }); - this.emitLine( - cJSON.deleteType, - "(x", - level > 0 ? level.toString() : "", - "->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - } - ); - } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { - /* Nothing to do */ - } else if ( - cJSON.cjsonType === "cJSON_String" || - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - this.emitLine( - cJSON.deleteType, - "(x->value.", - this.nameForUnionMember(unionType, type), - ");" - ); - } else { - /* Nothing to do */ - } - }); - onFirst = false; - } - this.emitLine("cJSON_free(x);"); - }); - }); - this.ensureBlankLine(); - } - - /** - * Function called to create a class header files with types and generators - * @param classType: class type - * @param includes: Array of includes - */ - protected emitClass(classType: ClassType, includes: string[]): void { - /* Create file */ - const className = this.nameForNamedType(classType); - const filename = this.sourcelikeToString(className).concat(".h"); - includes.push(filename); - this.startFile(filename); - - /* Create includes */ - this.emitIncludes(classType, this.sourcelikeToString(filename)); - - /* Create types */ - this.emitClassTypedef(classType); - - /* Create prototypes */ - this.emitClassPrototypes(classType); - - /* Create functions */ - this.emitClassFunctions(classType); - - /* Close file */ - this.finishFile(); - } - - /** - * Function called to create class typedef - * @param classType: class type - */ - protected emitClassTypedef(classType: ClassType): void { - const className = this.nameForNamedType(classType); - - this.emitDescription(this.descriptionForType(classType)); - this.emitBlock( - ["struct ", className], - () => { - this.forEachClassProperty(classType, "none", (name, jsonName, property) => { - this.emitDescription(this.descriptionForClassProperty(classType, jsonName)); - const cJSON = this.quicktypeTypeToCJSON(property.type, property.isOptional); - this.emitLine( - cJSON.cType, - cJSON.optionalQualifier !== "" ? " " : "", - cJSON.optionalQualifier, - " ", - name, - ";" - ); - }); - }, - "", - true - ); - this.ensureBlankLine(); - this.emitTypdefAlias(classType, className); - } - - /** - * Function called to create class prototypes - * @param classType: class type - */ - protected emitClassPrototypes(classType: ClassType): void { - const className = this.nameForNamedType(classType); - - this.emitLine("struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s);"); - this.emitLine("struct ", className, " * cJSON_Get", className, "Value(", this.withConst("cJSON"), " * j);"); - this.emitLine("cJSON * cJSON_Create", className, "(", this.withConst(["struct ", className]), " * x);"); - this.emitLine("char * cJSON_Print", className, "(", this.withConst(["struct ", className]), " * x);"); - this.emitLine("void cJSON_Delete", className, "(struct ", className, " * x);"); - this.ensureBlankLine(); - } - - /** - * Function called to create class functions - * @param classType: class type - */ - protected emitClassFunctions(classType: ClassType): void { - const className = this.nameForNamedType(classType); - - /* Create string to className generator function */ - this.emitBlock( - ["struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s)"], - () => { - this.emitLine("struct ", className, " * x = NULL;"); - this.emitBlock(["if (NULL != s)"], () => { - this.emitLine("cJSON * j = cJSON_Parse(s);"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitLine("x = cJSON_Get", className, "Value(j);"); - this.emitLine("cJSON_Delete(j);"); - }); - }); - this.emitLine("return x;"); - } - ); - this.ensureBlankLine(); - - /* Create cJSON to className generator function */ - this.emitBlock( - ["struct ", className, " * cJSON_Get", className, "Value(", this.withConst("cJSON"), " * j)"], - () => { - this.emitLine("struct ", className, " * x = NULL;"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitBlock(["if (NULL != (x = cJSON_malloc(sizeof(struct ", className, "))))"], () => { - this.emitLine("memset(x, 0, sizeof(struct ", className, "));"); - const recur = (type: Type, level: number) => { - if (type instanceof ArrayType) { - const child_level = level + 1; - const cJSON = this.quicktypeTypeToCJSON(type.items, false); - this.emitLine("list_t * x", child_level.toString(), " = list_create(false, NULL);"); - this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); - this.emitBlock( - ["cJSON_ArrayForEach(e", child_level.toString(), ", e", level.toString(), ")"], - () => { - if (cJSON.cjsonType === "cJSON_Array") { - const child_level2 = child_level + 1; - recur(type.items, child_level); - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", x", - child_level2.toString(), - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.cjsonType === "cJSON_Invalid" || - cJSON.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", (", - cJSON.cType, - " *)0xDEADBEEF, sizeof(", - cJSON.cType, - " *));" - ); - } else if (cJSON.cjsonType === "cJSON_String") { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", strdup(", - cJSON.getValue, - "(e", - child_level.toString(), - ")), sizeof(", - cJSON.cType, - " *));" - ); - } else if ( - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", ", - cJSON.getValue, - "(e", - child_level.toString(), - "), sizeof(", - cJSON.cType, - " *));" - ); - } else { - this.emitLine( - cJSON.cType, - " * tmp", - level > 0 ? level.toString() : "", - " = cJSON_malloc(sizeof(", - cJSON.cType, - "));" - ); - this.emitBlock( - ["if (NULL != tmp", level > 0 ? level.toString() : "", ")"], - () => { - this.emitLine( - "* tmp", - level > 0 ? level.toString() : "", - " = ", - cJSON.getValue, - "(e", - child_level.toString(), - ");" - ); - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", tmp", - level > 0 ? level.toString() : "", - ", sizeof(", - cJSON.cType, - " *));" - ); - } - ); - } - } - ); - }); - } else if (type instanceof ClassType) { - this.forEachClassProperty(type, "none", (name, jsonName, property) => { - const cJSON = this.quicktypeTypeToCJSON(property.type, property.isOptional); - this.emitBlock( - !cJSON.isNullable - ? [ - "if (cJSON_HasObjectItem(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"))' - ] - : [ - "if ((cJSON_HasObjectItem(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '")) && (!cJSON_IsNull(cJSON_GetObjectItemCaseSensitive(j', - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"))))' - ], - () => { - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - const child_level = level + 1; - this.emitLine( - cJSON.cType, - " * x", - child_level.toString(), - " = list_create(false, NULL);" - ); - this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); - this.emitLine( - "cJSON * j", - child_level.toString(), - " = cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '");' - ); - this.emitBlock( - [ - "cJSON_ArrayForEach(e", - child_level.toString(), - ", j", - child_level.toString(), - ")" - ], - () => { - const add = ( - type: Type, - cJSON: TypeCJSON, - level: number, - child_level: number - ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - if (type instanceof ArrayType) { - const child_level2 = child_level + 1; - recur(type.items, child_level); - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", x", - child_level2.toString(), - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - panic("Invalid type"); - } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", (", - cJSON.items!.cType, - " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", strdup(", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ")), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - "), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - this.emitLine( - cJSON.items!.cType, - " * tmp", - level > 0 ? level.toString() : "", - " = cJSON_malloc(sizeof(", - cJSON.items!.cType, - "));" - ); - this.emitBlock( - [ - "if (NULL != tmp", - level > 0 ? level.toString() : "", - ")" - ], - () => { - this.emitLine( - "* tmp", - level > 0 ? level.toString() : "", - " = ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ");" - ); - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", tmp", - level > 0 ? level.toString() : "", - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if (!cJSON_IsNull(e", - child_level.toString(), - "))" - ], - () => { - add(property.type, cJSON, level, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - "list_add_tail(x", - child_level.toString(), - ", (void *)0xDEADBEEF, sizeof(void *));" - ); - }); - } else { - add(property.type, cJSON, level, child_level); - } - } - ); - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = x", - child_level.toString(), - ";" - ); - }); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - const child_level = level + 1; - this.emitLine( - cJSON.cType, - " * x", - child_level.toString(), - " = hashtable_create(", - this.hashtableSize, - ", false);" - ); - this.emitBlock(["if (NULL != x", child_level.toString(), ")"], () => { - this.emitLine("cJSON * e", child_level.toString(), " = NULL;"); - this.emitLine( - "cJSON * j", - child_level.toString(), - " = cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '");' - ); - this.emitBlock( - [ - "cJSON_ArrayForEach(e", - child_level.toString(), - ", j", - child_level.toString(), - ")" - ], - () => { - const add = ( - type: Type, - cJSON: TypeCJSON, - level: number, - child_level: number - ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - if (type instanceof MapType) { - const child_level2 = child_level + 1; - recur(type.values, child_level); - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, x", - child_level2.toString(), - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - panic("Invalid type"); - } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, (", - cJSON.items!.cType, - " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, strdup(", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ")), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - "), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - this.emitLine( - cJSON.items!.cType, - " * tmp", - level > 0 ? level.toString() : "", - " = cJSON_malloc(sizeof(", - cJSON.items!.cType, - "));" - ); - this.emitBlock( - [ - "if (NULL != tmp", - level > 0 ? level.toString() : "", - ")" - ], - () => { - this.emitLine( - "* tmp", - level > 0 ? level.toString() : "", - " = ", - cJSON.items!.getValue, - "(e", - child_level.toString(), - ");" - ); - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, tmp", - level > 0 ? level.toString() : "", - ", sizeof(", - cJSON.items!.cType, - " *));" - ); - } - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if (!cJSON_IsNull(e", - child_level.toString(), - "))" - ], - () => { - add(property.type, cJSON, level, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - "hashtable_add(x", - child_level.toString(), - ", e", - child_level.toString(), - "->string, (void *)0xDEADBEEF, sizeof(void *));" - ); - }); - } else { - add(property.type, cJSON, level, child_level); - } - } - ); - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = x", - child_level.toString(), - ";" - ); - }); - } else if ( - cJSON.cjsonType === "cJSON_Invalid" || - cJSON.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = (", - cJSON.cType, - " *)0xDEADBEEF;" - ); - } else if (cJSON.cjsonType === "cJSON_String") { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = strdup(", - cJSON.getValue, - "(cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '")));' - ); - } else if ( - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = ", - cJSON.getValue, - "(cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"));' - ); - } else { - if (property.isOptional || cJSON.isNullable) { - this.emitBlock( - [ - "if (NULL != (x", - level > 0 ? level.toString() : "", - "->", - name, - " = cJSON_malloc(sizeof(", - cJSON.cType, - "))))" - ], - () => { - this.emitLine( - "*x", - level > 0 ? level.toString() : "", - "->", - name, - " = ", - cJSON.getValue, - "(cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"));' - ); - } - ); - } else { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = ", - cJSON.getValue, - "(cJSON_GetObjectItemCaseSensitive(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '"));' - ); - } - } - } - ); - if (!property.isOptional && !cJSON.isNullable) { - if (cJSON.cjsonType === "cJSON_Array") { - this.emitBlock(["else"], () => { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = list_create(false, NULL);" - ); - }); - } else if (cJSON.cjsonType === "cJSON_Map") { - this.emitBlock(["else"], () => { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = hashtable_create(", - this.hashtableSize, - ", false);" - ); - }); - } else if ( - cJSON.cjsonType === "cJSON_Invalid" || - cJSON.cjsonType === "cJSON_NULL" - ) { - this.emitBlock(["else"], () => { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - " = (", - cJSON.cType, - " *)0xDEADBEEF;" - ); - }); - } else if (cJSON.cjsonType === "cJSON_String") { - this.emitBlock(["else"], () => { - this.emitBlock( - [ - "if (NULL != (x", - level > 0 ? level.toString() : "", - "->", - name, - " = cJSON_malloc(sizeof(", - cJSON.cType, - "))))" - ], - () => { - this.emitLine( - "x", - level > 0 ? level.toString() : "", - "->", - name, - "[0] = '\\0';" - ); - } - ); - }); - } else { - /* Nothing to do */ - } - } - }); - } - }; - recur(classType, 0); - }); - }); - this.emitLine("return x;"); - } - ); - this.ensureBlankLine(); - - /* Create className to cJSON generator function */ - this.emitBlock( - ["cJSON * cJSON_Create", className, "(", this.withConst(["struct ", className]), " * x)"], - () => { - this.emitLine("cJSON * j = NULL;"); - this.emitBlock(["if (NULL != x)"], () => { - this.emitBlock(["if (NULL != (j = cJSON_CreateObject()))"], () => { - const recur = (type: Type, level: number) => { - if (type instanceof ArrayType) { - const child_level = level + 1; - const cJSON = this.quicktypeTypeToCJSON(type.items, false); - this.emitLine("cJSON * j", child_level.toString(), " = cJSON_CreateArray();"); - this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { - this.emitLine( - cJSON.cType, - " * x", - child_level.toString(), - " = list_get_head(x", - level.toString(), - ");" - ); - this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.cjsonType === "cJSON_Array") { - const child_level2 = child_level + 1; - recur(type.items, child_level); - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", j", - child_level2.toString(), - ");" - ); - } else if (cJSON.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.cjsonType === "cJSON_NULL") { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.createObject, - "());" - ); - } else if ( - cJSON.cjsonType === "cJSON_String" || - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.createObject, - "(x", - child_level.toString(), - "));" - ); - } else { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.createObject, - "(*x", - child_level.toString(), - "));" - ); - } - this.emitLine( - "x", - child_level.toString(), - " = list_get_next(x", - level.toString(), - ");" - ); - }); - }); - } else if (type instanceof ClassType) { - this.forEachClassProperty(type, "none", (name, jsonName, property) => { - const cJSON = this.quicktypeTypeToCJSON(property.type, property.isOptional); - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - const child_level = level + 1; - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - "cJSON * j", - child_level.toString(), - " = cJSON_AddArrayToObject(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '");' - ); - this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { - this.emitLine( - cJSON.items!.cType, - " * x", - child_level.toString(), - " = list_get_head(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - this.emitBlock( - ["while (NULL != x", child_level.toString(), ")"], - () => { - const add = ( - type: Type, - cJSON: TypeCJSON, - child_level: number - ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - if (type instanceof ArrayType) { - const child_level2 = child_level + 1; - recur(type.items, child_level); - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", j", - child_level2.toString(), - ");" - ); - } else { - panic("Invalid type"); - } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.items!.createObject, - "());" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.items!.createObject, - "(x", - child_level.toString(), - "));" - ); - } else { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", ", - cJSON.items!.createObject, - "(*x", - child_level.toString(), - "));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if ((void *)0xDEADBEEF != x", - child_level.toString(), - ")" - ], - () => { - add(property.type, cJSON, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - "cJSON_AddItemToArray(j", - child_level.toString(), - ", cJSON_CreateNull());" - ); - }); - } else { - add(property.type, cJSON, child_level); - } - this.emitLine( - "x", - child_level.toString(), - " = list_get_next(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - }); - } - ); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - const child_level = level + 1; - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - "cJSON * j", - child_level.toString(), - " = ", - cJSON.createObject, - "();" - ); - this.emitBlock(["if (NULL != j", child_level.toString(), ")"], () => { - this.emitLine("char **keys", child_level.toString(), " = NULL;"); - this.emitLine( - "size_t count", - child_level.toString(), - " = hashtable_get_keys(x", - level > 0 ? level.toString() : "", - "->", - name, - ", &keys", - child_level.toString(), - ");" - ); - this.emitBlock( - ["if (NULL != keys", child_level.toString(), ")"], - () => { - this.emitBlock( - [ - "for (size_t index", - child_level.toString(), - " = 0; index", - child_level.toString(), - " < count", - child_level.toString(), - "; index", - child_level.toString(), - "++)" - ], - () => { - this.emitLine( - cJSON.items!.cType, - " *x", - child_level.toString(), - " = hashtable_lookup(x", - level > 0 ? level.toString() : "", - "->", - name, - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "]);" - ); - const add = ( - type: Type, - cJSON: TypeCJSON, - child_level: number - ) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - if (type instanceof MapType) { - const child_level2 = child_level + 1; - recur(type.values, child_level); - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], j", - child_level2.toString(), - ");" - ); - } else { - panic("Invalid type"); - } - } else if ( - cJSON.items!.cjsonType === "cJSON_Map" - ) { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" - ) { - /* Nothing to do */ - } else if ( - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], ", - cJSON.items!.createObject, - "());" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], ", - cJSON.items!.createObject, - "(x", - child_level.toString(), - "));" - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], ", - cJSON.items!.createObject, - "(*x", - child_level.toString(), - "));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if ((void *)0xDEADBEEF != x", - child_level.toString(), - ")" - ], - () => { - add(property.type, cJSON, child_level); - } - ); - this.emitBlock(["else"], () => { - this.emitLine( - cJSON.addToObject, - "(j", - child_level.toString(), - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "], cJSON_CreateNull());" - ); - }); - } else { - add(property.type, cJSON, child_level); - } - } - ); - this.emitLine( - "cJSON_free(keys", - child_level.toString(), - ");" - ); - } - ); - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", j', - child_level.toString(), - ");" - ); - }); - } - ); - } else if (cJSON.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.cjsonType === "cJSON_NULL") { - if (property.isOptional) { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '");' - ); - } - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '");' - ); - } - } else if (cJSON.cjsonType === "cJSON_String") { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", x', - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - if (!property.isOptional && !cJSON.isNullable) { - this.emitBlock(["else"], () => { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", "");' - ); - }); - } - } else if ( - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - if (property.isOptional || cJSON.isNullable) { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", ', - cJSON.createObject, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - "));" - ); - } - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", ', - cJSON.createObject, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - "));" - ); - } - } else if (cJSON.cjsonType === "cJSON_Enum") { - if (property.isOptional || cJSON.isNullable) { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", ', - cJSON.createObject, - "(*x", - level > 0 ? level.toString() : "", - "->", - name, - "));" - ); - } - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", ', - cJSON.createObject, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - "));" - ); - } - } else { - if (property.isOptional || cJSON.isNullable) { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", *x', - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '", x', - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - } - if (cJSON.isNullable) { - this.emitBlock(["else"], () => { - this.emitLine( - "cJSON_AddNullToObject(j", - level > 0 ? level.toString() : "", - ', "', - jsonName, - '");' - ); - }); - } - }); - } - }; - recur(classType, 0); - }); - }); - this.emitLine("return j;"); - } - ); - this.ensureBlankLine(); - - /* Create className to string generator function */ - this.emitBlock(["char * cJSON_Print", className, "(", this.withConst(["struct ", className]), " * x)"], () => { - this.emitLine("char * s = NULL;"); - this.emitBlock(["if (NULL != x)"], () => { - this.emitLine("cJSON * j = cJSON_Create", className, "(x);"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitLine(this._options.printStyle ? "s = cJSON_PrintUnformatted(j);" : "s = cJSON_Print(j);"); - this.emitLine("cJSON_Delete(j);"); - }); - }); - this.emitLine("return s;"); - }); - this.ensureBlankLine(); - - /* Create className delete function */ - this.emitBlock(["void cJSON_Delete", className, "(struct ", className, " * x)"], () => { - this.emitBlock(["if (NULL != x)"], () => { - const recur = (type: Type, level: number) => { - if (type instanceof ArrayType) { - const child_level = level + 1; - const cJSON = this.quicktypeTypeToCJSON(type.items, false); - this.emitLine( - cJSON.cType, - " * x", - child_level.toString(), - " = list_get_head(x", - level.toString(), - ");" - ); - this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.cjsonType === "cJSON_Array") { - recur(type.items, child_level); - this.emitLine(cJSON.deleteType, "(x", child_level.toString(), ");"); - } else if (cJSON.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { - /* Nothing to do */ - } else { - this.emitLine(cJSON.deleteType, "(x", child_level.toString(), ");"); - } - this.emitLine("x", child_level.toString(), " = list_get_next(x", level.toString(), ");"); - }); - } else if (type instanceof ClassType) { - this.forEachClassProperty(type, "none", (name, _jsonName, property) => { - const cJSON = this.quicktypeTypeToCJSON(property.type, property.isOptional); - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - const child_level = level + 1; - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.items!.cType, - " * x", - child_level.toString(), - " = list_get_head(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - this.emitBlock(["while (NULL != x", child_level.toString(), ")"], () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - if (property.type instanceof ArrayType) { - recur(property.type.items, child_level); - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } else { - panic("Invalid type"); - } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - /* Nothing to do */ - } else { - if (cJSON.items!.isNullable) { - this.emitBlock( - ["if ((void *)0xDEADBEEF != x", child_level.toString(), ")"], - () => { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - ); - } else { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - } - this.emitLine( - "x", - child_level.toString(), - " = list_get_next(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - }); - this.emitLine( - cJSON.deleteType, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - const child_level = level + 1; - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine("char **keys", child_level.toString(), " = NULL;"); - this.emitLine( - "size_t count", - child_level.toString(), - " = hashtable_get_keys(x", - level > 0 ? level.toString() : "", - "->", - name, - ", &keys", - child_level.toString(), - ");" - ); - this.emitBlock(["if (NULL != keys", child_level.toString(), ")"], () => { - this.emitBlock( - [ - "for (size_t index", - child_level.toString(), - " = 0; index", - child_level.toString(), - " < count", - child_level.toString(), - "; index", - child_level.toString(), - "++)" - ], - () => { - this.emitLine( - cJSON.items!.cType, - " *x", - child_level.toString(), - " = hashtable_lookup(x", - level > 0 ? level.toString() : "", - "->", - name, - ", keys", - child_level.toString(), - "[index", - child_level.toString(), - "]);" - ); - this.emitBlock( - ["if (NULL != x", child_level.toString(), ")"], - () => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - if (property.type instanceof MapType) { - recur(property.type.values, child_level); - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } else { - panic("Invalid type"); - } - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - /* Nothing to do */ - } else { - if (cJSON.items!.isNullable) { - this.emitBlock( - [ - "if ((void *)0xDEADBEEF != x", - child_level.toString(), - ")" - ], - () => { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - ); - } else { - this.emitLine( - cJSON.items!.deleteType, - "(x", - child_level.toString(), - ");" - ); - } - } - } - ); - } - ); - this.emitLine("cJSON_free(keys", child_level.toString(), ");"); - }); - this.emitLine( - cJSON.deleteType, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { - /* Nothing to do */ - } else if ( - cJSON.cjsonType === "cJSON_String" || - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.deleteType, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - } else { - if (property.isOptional || cJSON.isNullable) { - this.emitBlock( - ["if (NULL != x", level > 0 ? level.toString() : "", "->", name, ")"], - () => { - this.emitLine( - cJSON.deleteType, - "(x", - level > 0 ? level.toString() : "", - "->", - name, - ");" - ); - } - ); - } - } - }); - } - }; - recur(classType, 0); - this.emitLine("cJSON_free(x);"); - }); - }); - this.ensureBlankLine(); - } - - /** - * Function called to create a top level header files with types and generators - * @param type: type of the top level element - * @param className: top level class name - * @param includes: Array of includes - */ - protected emitTopLevel(type: Type, className: Name, includes: string[]): void { - /* Create file */ - const filename = this.sourcelikeToString(className).concat(".h"); - this.startFile(filename); - - /* Create includes - This create too much includes but this is safer because of specific corner cases */ - includes.forEach(name => { - this.emitIncludeLine(name); - }); - this.ensureBlankLine(); - - /* Create types */ - this.emitTopLevelTypedef(type, className); - - /* Create prototypes */ - this.emitTopLevelPrototypes(type, className); - - /* Create functions */ - this.emitTopLevelFunctions(type, className); - - /* Close file */ - this.finishFile(); - } - - /** - * Function called to create top level typedef - * @param type: type of the top level element - * @param className: top level class name - */ - protected emitTopLevelTypedef(type: Type, className: Name): void { - this.emitBlock( - ["struct ", className], - () => { - const cJSON = this.quicktypeTypeToCJSON(type, false); - this.emitLine( - cJSON.cType, - cJSON.optionalQualifier !== "" ? " " : "", - cJSON.optionalQualifier, - " value;" - ); - }, - "", - true - ); - this.ensureBlankLine(); - this.emitTypdefAlias(type, className); - } - - /** - * Function called to create top level prototypes - * @param type: type of the top level element - * @param className: top level class name - */ - protected emitTopLevelPrototypes(_type: Type, className: Name): void { - this.emitLine("struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s);"); - this.emitLine("struct ", className, " * cJSON_Get", className, "Value(", this.withConst("cJSON"), " * j);"); - this.emitLine("cJSON * cJSON_Create", className, "(", this.withConst(["struct ", className]), " * x);"); - this.emitLine("char * cJSON_Print", className, "(", this.withConst(["struct ", className]), " * x);"); - this.emitLine("void cJSON_Delete", className, "(struct ", className, " * x);"); - this.ensureBlankLine(); - } - - /** - * Function called to create top level functions - * @param type: type of the top level element - * @param className: top level class name - */ - protected emitTopLevelFunctions(type: Type, className: Name): void { - /* Create string to className generator function */ - this.emitBlock( - ["struct ", className, " * cJSON_Parse", className, "(", this.withConst("char"), " * s)"], - () => { - this.emitLine("struct ", className, " * x = NULL;"); - this.emitBlock(["if (NULL != s)"], () => { - this.emitLine("cJSON * j = cJSON_Parse(s);"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitLine("x = cJSON_Get", className, "Value(j);"); - this.emitLine("cJSON_Delete(j);"); - }); - }); - this.emitLine("return x;"); - } - ); - this.ensureBlankLine(); - - /* Create cJSON to className generator function */ - this.emitBlock( - ["struct ", className, " * cJSON_Get", className, "Value(", this.withConst("cJSON"), " * j)"], - () => { - this.emitLine("struct ", className, " * x = NULL;"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitBlock(["if (NULL != (x = cJSON_malloc(sizeof(struct ", className, "))))"], () => { - this.emitLine("memset(x, 0, sizeof(struct ", className, "));"); - const cJSON = this.quicktypeTypeToCJSON(type, false); - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - this.emitLine("x->value = list_create(false, NULL);"); - this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine("cJSON * e = NULL;"); - this.emitBlock(["cJSON_ArrayForEach(e, j)"], () => { - const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "list_add_tail(x->value, (", - cJSON.items!.cType, - " *)0xDEADBEAF, sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { - this.emitLine( - "list_add_tail(x->value, strdup(", - cJSON.items!.getValue, - "(e)), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - this.emitLine( - "list_add_tail(x->value, ", - cJSON.items!.getValue, - "(e), sizeof(", - cJSON.items!.cType, - " *));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock(["if (!cJSON_IsNull(e))"], () => { - add(cJSON); - }); - this.emitBlock(["else"], () => { - this.emitLine( - "list_add_tail(x->value, (void *)0xDEADBEEF, sizeof(void *));" - ); - }); - } else { - add(cJSON); - } - }); - }); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - this.emitLine("x->value = hashtable_create(", this.hashtableSize, ", false);"); - this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine("cJSON * e = NULL;"); - this.emitBlock(["cJSON_ArrayForEach(e, j)"], () => { - const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if ( - cJSON.items!.cjsonType === "cJSON_Invalid" || - cJSON.items!.cjsonType === "cJSON_NULL" - ) { - this.emitLine( - "hashtable_add(x->value, e->string, (", - cJSON.items!.cType, - " *)0xDEADBEEF, sizeof(", - cJSON.items!.cType, - " *));" - ); - } else if (cJSON.items!.cjsonType === "cJSON_String") { - this.emitLine( - "hashtable_add(x->value, e->string, strdup(", - cJSON.items!.getValue, - "(e)), sizeof(", - cJSON.items!.cType, - " *));" - ); - } else { - this.emitLine( - "hashtable_add(x->value, e->string, ", - cJSON.items!.getValue, - "(e), sizeof(", - cJSON.items!.cType, - " *));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock(["if (!cJSON_IsNull(e))"], () => { - add(cJSON); - }); - this.emitBlock(["else"], () => { - this.emitLine( - "hashtable_add(x->value, e->string, (void *)0xDEADBEEF, sizeof(void *));" - ); - }); - } else { - add(cJSON); - } - }); - }); - } else if (cJSON.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.cjsonType === "cJSON_NULL") { - this.emitLine("x->value = (", cJSON.cType, " *)0xDEADBEEF;"); - } else if (cJSON.cjsonType === "cJSON_String") { - this.emitLine("x->value = strdup(", cJSON.getValue, "(j));"); - } else { - this.emitLine("x->value = ", cJSON.getValue, "(j);"); - } - }); - }); - this.emitLine("return x;"); - } - ); - this.ensureBlankLine(); - - /* Create className to cJSON generator function */ - this.emitBlock( - ["cJSON * cJSON_Create", className, "(", this.withConst(["struct ", className]), " * x)"], - () => { - this.emitLine("cJSON * j = NULL;"); - this.emitBlock(["if (NULL != x)"], () => { - const cJSON = this.quicktypeTypeToCJSON(type, false); - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine("j = ", cJSON.createObject, "();"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitLine(cJSON.items!.cType, " * x1 = list_get_head(x->value);"); - this.emitBlock(["while (NULL != x1)"], () => { - const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { - this.emitLine( - "cJSON_AddItemToArray(j, ", - cJSON.items!.createObject, - "());" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - "cJSON_AddItemToArray(j, ", - cJSON.items!.createObject, - "(x1));" - ); - } else { - this.emitLine( - "cJSON_AddItemToArray(j, ", - cJSON.items!.createObject, - "(*x1));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock(["if ((void *)0xDEADBEEF != x1)"], () => { - add(cJSON); - }); - this.emitBlock(["else"], () => { - this.emitLine("cJSON_AddItemToArray(j, cJSON_CreateNull());"); - }); - } else { - add(cJSON); - } - this.emitLine("x1 = list_get_next(x->value);"); - }); - }); - }); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine("j = ", cJSON.createObject, "();"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitLine("char **keys = NULL;"); - this.emitLine("size_t count = hashtable_get_keys(x->value, &keys);"); - this.emitBlock(["if (NULL != keys)"], () => { - this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { - this.emitLine( - cJSON.items!.cType, - " *x2 = hashtable_lookup(x->value, keys[index]);" - ); - const add = (cJSON: TypeCJSON) => { - if (cJSON.items!.cjsonType === "cJSON_Array") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Map") { - /* Not supported */ - } else if (cJSON.items!.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.items!.cjsonType === "cJSON_NULL") { - this.emitLine( - cJSON.addToObject, - "(j, keys[index], ", - cJSON.items!.createObject, - "());" - ); - } else if ( - cJSON.items!.cjsonType === "cJSON_String" || - cJSON.items!.cjsonType === "cJSON_Object" || - cJSON.items!.cjsonType === "cJSON_Union" - ) { - this.emitLine( - cJSON.addToObject, - "(j, keys[index], ", - cJSON.items!.createObject, - "(x2));" - ); - } else { - this.emitLine( - cJSON.addToObject, - "(j, keys[index], ", - cJSON.items!.createObject, - "(*x2));" - ); - } - }; - if (cJSON.items!.isNullable) { - this.emitBlock(["if ((void *)0xDEADBEEF != x2)"], () => { - add(cJSON); - }); - this.emitBlock(["else"], () => { - this.emitLine( - cJSON.addToObject, - "(j, keys[index], cJSON_CreateNull());" - ); - }); - } else { - add(cJSON); - } - }); - this.emitLine("cJSON_free(keys);"); - }); - }); - }); - } else if (cJSON.cjsonType === "cJSON_Invalid") { - /* Nothing to do */ - } else if (cJSON.cjsonType === "cJSON_NULL") { - this.emitLine("j = ", cJSON.createObject, "();"); - } else { - this.emitLine("j = ", cJSON.createObject, "(x->value);"); - } - }); - this.emitLine("return j;"); - } - ); - this.ensureBlankLine(); - - /* Create className to string generator function */ - this.emitBlock(["char * cJSON_Print", className, "(", this.withConst(["struct ", className]), " * x)"], () => { - this.emitLine("char * s = NULL;"); - this.emitBlock(["if (NULL != x)"], () => { - this.emitLine("cJSON * j = cJSON_Create", className, "(x);"); - this.emitBlock(["if (NULL != j)"], () => { - this.emitLine("s = cJSON_Print(j);"); - this.emitLine("cJSON_Delete(j);"); - }); - }); - this.emitLine("return s;"); - }); - this.ensureBlankLine(); - - /* Create className delete function */ - this.emitBlock(["void cJSON_Delete", className, "(struct ", className, " * x)"], () => { - this.emitBlock(["if (NULL != x)"], () => { - const cJSON = this.quicktypeTypeToCJSON(type, false); - if (cJSON.cjsonType === "cJSON_Array" && cJSON.items !== undefined) { - this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine(cJSON.items!.cType, " * x1 = list_get_head(x->value);"); - this.emitBlock(["while (NULL != x1)"], () => { - if (cJSON.items!.isNullable) { - this.emitBlock(["if ((void *)0xDEADBEEF != x1)"], () => { - this.emitLine(cJSON.items!.deleteType, "(x1);"); - }); - } else { - this.emitLine(cJSON.items!.deleteType, "(x1);"); - } - this.emitLine("x1 = list_get_next(x->value);"); - }); - this.emitLine(cJSON.deleteType, "(x->value);"); - }); - } else if (cJSON.cjsonType === "cJSON_Map" && cJSON.items !== undefined) { - this.emitBlock(["if (NULL != x->value)"], () => { - this.emitLine("char **keys = NULL;"); - this.emitLine("size_t count = hashtable_get_keys(x->value, &keys);"); - this.emitBlock(["if (NULL != keys)"], () => { - this.emitBlock(["for (size_t index = 0; index < count; index++)"], () => { - this.emitLine(cJSON.items!.cType, " *x2 = hashtable_lookup(x->value, keys[index]);"); - this.emitBlock(["if (NULL != x2)"], () => { - if (cJSON.items!.isNullable) { - this.emitBlock(["if ((", cJSON.items!.cType, " *)0xDEADBEEF != x2)"], () => { - this.emitLine(cJSON.items!.deleteType, "(x2);"); - }); - } else { - this.emitLine(cJSON.items!.deleteType, "(x2);"); - } - }); - }); - this.emitLine("cJSON_free(keys);"); - }); - this.emitLine(cJSON.deleteType, "(x->value);"); - }); - } else if (cJSON.cjsonType === "cJSON_Invalid" || cJSON.cjsonType === "cJSON_NULL") { - /* Nothing to do */ - } else if ( - cJSON.cjsonType === "cJSON_String" || - cJSON.cjsonType === "cJSON_Object" || - cJSON.cjsonType === "cJSON_Union" - ) { - this.emitLine(cJSON.deleteType, "(x->value);"); - } else { - /* Nothing to do */ - } - this.emitLine("cJSON_free(x);"); - }); - }); - this.ensureBlankLine(); - } - - /** - * Convert quicktype type to cJSON type - * @param t: quicktype type - * @param isOptional: true if the field is optional - * @param isNullable: true if the field is nullable - * @return cJSON type - */ - protected quicktypeTypeToCJSON(t: Type, isOptional: boolean, isNullable = false): TypeCJSON { - /* Compute cJSON type */ - return matchType( - t, - _anyType => { - return { - cType: "void", - optionalQualifier: "*", - cjsonType: "cJSON_Invalid", - isType: "cJSON_IsInvalid", - getValue: "", - addToObject: "", - createObject: "", - deleteType: "", - items: undefined, - isNullable - }; - }, - _nullType => { - return { - cType: "void", - optionalQualifier: "*", - cjsonType: "cJSON_NULL", - isType: "cJSON_IsNull", - getValue: "", - addToObject: "cJSON_AddNullToObject", - createObject: "cJSON_CreateNull", - deleteType: "cJSON_free", - items: undefined, - isNullable - }; - }, - _boolType => { - return { - cType: "bool", - optionalQualifier: isOptional === true ? "*" : "", - cjsonType: "cJSON_Bool", - isType: "cJSON_IsBool", - getValue: "cJSON_IsTrue", - addToObject: "cJSON_AddBoolToObject", - createObject: "cJSON_CreateBool", - deleteType: "cJSON_free", - items: undefined, - isNullable - }; - }, - _integerType => { - return { - cType: this.typeIntegerSize, - optionalQualifier: isOptional === true ? "*" : "", - cjsonType: "cJSON_Number", - isType: "cJSON_IsNumber", - getValue: "cJSON_GetNumberValue", - addToObject: "cJSON_AddNumberToObject", - createObject: "cJSON_CreateNumber", - deleteType: "cJSON_free", - items: undefined, - isNullable - }; - }, - _doubleType => { - return { - cType: "double", - optionalQualifier: isOptional === true ? "*" : "", - cjsonType: "cJSON_Number", - isType: "cJSON_IsNumber", - getValue: "cJSON_GetNumberValue", - addToObject: "cJSON_AddNumberToObject", - createObject: "cJSON_CreateNumber", - deleteType: "cJSON_free", - items: undefined, - isNullable - }; - }, - _stringType => { - return { - cType: "char", - optionalQualifier: "*", - cjsonType: "cJSON_String", - isType: "cJSON_IsString", - getValue: "cJSON_GetStringValue", - addToObject: "cJSON_AddStringToObject", - createObject: "cJSON_CreateString", - deleteType: "cJSON_free", - items: undefined, - isNullable - }; - }, - arrayType => { - const items = this.quicktypeTypeToCJSON(arrayType.items, false); - return { - cType: "list_t", - optionalQualifier: "*", - cjsonType: "cJSON_Array", - isType: "cJSON_IsArray", - getValue: "cJSON_GetArrayItem", - addToObject: "cJSON_AddItemToObject", - createObject: "cJSON_CreateArray", - deleteType: "list_release", - items, - isNullable - }; - }, - classType => { - return { - cType: ["struct ", this.nameForNamedType(classType)], - optionalQualifier: "*", - cjsonType: "cJSON_Object", - isType: "cJSON_IsObject", - getValue: ["cJSON_Get", this.nameForNamedType(classType), "Value"], - addToObject: "cJSON_AddItemToObject", - createObject: ["cJSON_Create", this.nameForNamedType(classType)], - deleteType: ["cJSON_Delete", this.nameForNamedType(classType)], - items: undefined, - isNullable - }; - }, - mapType => { - const items = this.quicktypeTypeToCJSON(mapType.values, false); - return { - cType: "hashtable_t", - optionalQualifier: "*", - cjsonType: "cJSON_Map", - isType: "cJSON_IsObject", - getValue: "", - addToObject: "cJSON_AddItemToObject", - createObject: "cJSON_CreateObject", - deleteType: "hashtable_release", - items, - isNullable - }; - }, - enumType => { - return { - cType: ["enum ", this.nameForNamedType(enumType)], - optionalQualifier: isOptional === true ? "*" : "", - cjsonType: "cJSON_Enum", - isType: "cJSON_IsString", - getValue: ["cJSON_Get", this.nameForNamedType(enumType), "Value"], - addToObject: "cJSON_AddItemToObject", - createObject: ["cJSON_Create", this.nameForNamedType(enumType)], - deleteType: "cJSON_free", - items: undefined, - isNullable - }; - }, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return this.quicktypeTypeToCJSON(nullable, true, true); - } else { - return { - cType: ["struct ", this.nameForNamedType(unionType)], - optionalQualifier: "*", - cjsonType: "cJSON_Union", - isType: "", - getValue: ["cJSON_Get", this.nameForNamedType(unionType), "Value"], - addToObject: "cJSON_AddItemToObject", - createObject: ["cJSON_Create", this.nameForNamedType(unionType)], - deleteType: ["cJSON_Delete", this.nameForNamedType(unionType)], - items: undefined, - isNullable - }; - } - } - ); - } - - /** - * Function called to create a file - * @param proposedFilename: source filename provided from stdin - */ - protected startFile(proposedFilename: Sourcelike): void { - /* Check if previous file is closed, create a new file */ - assert(this.currentFilename === undefined, "Previous file wasn't finished"); - if (proposedFilename !== undefined) { - this.currentFilename = this.sourcelikeToString(proposedFilename); - } - - /* Check if file has been created */ - if (this.currentFilename !== undefined) { - /* Write header */ - this.emitDescriptionBlock([ - this.currentFilename, - "This file has been autogenerated using quicktype https://github.com/quicktype/quicktype - DO NOT EDIT", - "This file depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable", - "To parse json data from json string use the following: struct * data = cJSON_Parse();", - "To get json data from cJSON object use the following: struct * data = cJSON_GetValue();", - "To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create();", - "To print json string from json data use the following: char * string = cJSON_Print();", - "To delete json data use the following: cJSON_Delete();" - ]); - this.ensureBlankLine(); - - /* Write include guard */ - this.emitLine( - "#ifndef __", - allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__" - ); - this.emitLine( - "#define __", - allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__" - ); - this.ensureBlankLine(); - - /* Write C++ guard */ - this.emitLine("#ifdef __cplusplus"); - this.emitLine('extern "C" {'); - this.emitLine("#endif"); - this.ensureBlankLine(); - - /* Write includes */ - this.emitIncludeLine("stdint.h", true); - this.emitIncludeLine("stdbool.h", true); - this.emitIncludeLine("stdlib.h", true); - this.emitIncludeLine("string.h", true); - this.emitIncludeLine("cJSON.h", true); - this.emitIncludeLine("hashtable.h", true); - this.emitIncludeLine("list.h", true); - this.ensureBlankLine(); - - /* Additional cJSON types */ - this.emitLine("#ifndef cJSON_Bool"); - this.emitLine("#define cJSON_Bool (cJSON_True | cJSON_False)"); - this.emitLine("#endif"); - this.emitLine("#ifndef cJSON_Map"); - this.emitLine("#define cJSON_Map (1 << 16)"); - this.emitLine("#endif"); - this.emitLine("#ifndef cJSON_Enum"); - this.emitLine("#define cJSON_Enum (1 << 17)"); - this.emitLine("#endif"); - this.ensureBlankLine(); - } - } - - /** - * Function called to close current file - */ - protected finishFile(): void { - /* Check if file has been created */ - if (this.currentFilename !== undefined) { - /* Write C++ guard */ - this.emitLine("#ifdef __cplusplus"); - this.emitLine("}"); - this.emitLine("#endif"); - this.ensureBlankLine(); - - /* Write include guard */ - this.emitLine( - "#endif /* __", - allUpperWordStyle(this.currentFilename.replace(new RegExp(/[^a-zA-Z0-9]+/, "g"), "_")), - "__ */" - ); - this.ensureBlankLine(); - - /* Close file */ - super.finishFile(defined(this.currentFilename)); - this.currentFilename = undefined; - } - } - - /** - * Check if type need declaration before use - * @note If returning true, canBeForwardDeclared must be declared - * @return Always returns true - */ - protected get needsTypeDeclarationBeforeUse(): boolean { - return true; - } - - /** - * Check if type can be forward declared - * @return true for classes, false otherwise - */ - protected canBeForwardDeclared(type: Type): boolean { - return type.kind === "class"; - } - - /** - * Add const to wanted Sourcelike - * @return Const Sourcelike - */ - protected withConst(s: Sourcelike): Sourcelike { - return ["const ", s]; - } - - /** - * Emit include line - * @param name: filename to include - * @pram global: true if global include, false otherwise (default) - */ - protected emitIncludeLine(name: Sourcelike, global = false): void { - this.emitLine("#include ", global ? "<" : '"', name, global ? ">" : '"'); - } - - /** - * Emit description block - * @param lines: description block lines - */ - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); - } - - /** - * Emit code block - * @param line: code block line - * @param f: callback function - * @param withName: name of the block as string - * @param withSemicolon: true to add semicolon at the end of the block, false otherwise - * @param withIndent: true to indent the block (default), false otherwise - */ - protected emitBlock( - line: Sourcelike, - f: () => void, - withName = "", - withSemicolon = false, - withIndent = true - ): void { - this.emitLine(line, " {"); - this.preventBlankLine(); - if (withIndent) { - this.indent(f); - } else { - f(); - } - this.preventBlankLine(); - if (withSemicolon) { - if (withName !== "") { - this.emitLine("} ", withName, ";"); - } else { - this.emitLine("};"); - } - } else { - if (withName !== "") { - this.emitLine("} ", withName); - } else { - this.emitLine("}"); - } - } - } - - /** - * Emit includes - * @param type: class, union or enum type - * @param filename: current file name - */ - protected emitIncludes(type: ClassType | UnionType | EnumType, filename: string): void { - /* List required includes */ - const includes: IncludeMap = new Map(); - if (type instanceof UnionType) { - this.updateIncludes(false, includes, type); - } else if (type instanceof ClassType) { - this.forEachClassProperty(type, "none", (_name, _jsonName, property) => { - this.updateIncludes(true, includes, property.type); - }); - } - - /* Emit includes */ - if (includes.size !== 0) { - includes.forEach((_rec: IncludeRecord, name: string) => { - name = name.concat(".h"); - if (name !== filename) { - this.emitIncludeLine(name); - } - }); - } - this.ensureBlankLine(); - } - - /** - * Compute includes - * @param isClassMender: true if class, false otherwise - * @param includes: include map - * @param propertyType: property type - */ - protected updateIncludes(isClassMember: boolean, includes: IncludeMap, propertyType: Type): void { - const propTypes = this.generatedTypes(isClassMember, propertyType); - for (const t of propTypes) { - const typeName = this.sourcelikeToString(t.name); - const propRecord: IncludeRecord = { kind: undefined, typeKind: undefined }; - if (t.type instanceof ClassType) { - /* We can NOT forward declare direct class members, e.g. a class type is included at level#0 */ - /* HOWEVER if it is not a direct class member, then we can SURELY forward declare it */ - propRecord.typeKind = "class"; - propRecord.kind = t.level === 0 ? IncludeKind.Include : IncludeKind.ForwardDeclare; - if (t.forceInclude) { - propRecord.kind = IncludeKind.Include; - } - } else if (t.type instanceof EnumType) { - propRecord.typeKind = "enum"; - propRecord.kind = IncludeKind.ForwardDeclare; - } else if (t.type instanceof UnionType) { - propRecord.typeKind = "union"; - /* Recurse into the union */ - const [maybeNull] = removeNullFromUnion(t.type, true); - if (maybeNull !== undefined) { - /* Houston this is a variant, include it */ - propRecord.kind = IncludeKind.Include; - } else { - if (t.forceInclude) { - propRecord.kind = IncludeKind.Include; - } else { - propRecord.kind = IncludeKind.ForwardDeclare; - } - } - } - if (includes.has(typeName)) { - const incKind = includes.get(typeName); - /* If we already include the type as typed include, do not write it over with forward declare */ - if (incKind !== undefined && incKind.kind === IncludeKind.ForwardDeclare) { - includes.set(typeName, propRecord); - } - } else { - includes.set(typeName, propRecord); - } - } - } - - /** - * Compute generated types - * @param isClassMender: true if class, false otherwise - * @param type: type - * @return Type record array - */ - protected generatedTypes(isClassMember: boolean, type: Type): TypeRecord[] { - const result: TypeRecord[] = []; - const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { - if (t instanceof ArrayType) { - recur(forceInclude, isVariant, l + 1, t.items); - } else if (t instanceof ClassType) { - result.push({ - name: this.nameForNamedType(t), - type: t, - level: l, - variant: isVariant, - forceInclude - }); - } else if (t instanceof MapType) { - recur(forceInclude, isVariant, l + 1, t.values); - } else if (t instanceof EnumType) { - result.push({ - name: this.nameForNamedType(t), - type: t, - level: l, - variant: isVariant, - forceInclude: false - }); - } else if (t instanceof UnionType) { - /** - * If we have a union as a class member and we see it as a "named union", - * we can safely include it as-is. - * HOWEVER if we define a union on its own, we must recurse into the - * typedefinition and include all subtypes. - */ - if (this.unionNeedsName(t) && isClassMember) { - /** - * This is NOT ENOUGH. - * We have a variant member in a class, e.g. defined with a boost::variant. - * The compiler can only compile the class if IT KNOWS THE SIZES - * OF ALL MEMBERS OF THE VARIANT. - * So it means that you must include ALL SUBTYPES (practically classes only) - * AS WELL - */ - forceInclude = true; - result.push({ - name: this.nameForNamedType(t), - type: t, - level: l, - variant: true, - forceInclude - }); - /** intentional "fall-through", add all subtypes as well - but forced include */ - } - - const [hasNull, nonNulls] = removeNullFromUnion(t); - isVariant = hasNull !== null; - /** we need to collect all the subtypes of the union */ - for (const tt of nonNulls) { - recur(forceInclude, isVariant, l + 1, tt); - } - } - }; - recur(false, false, 0, type); - return result; - } -} diff --git a/packages/quicktype-core/src/language/CJSON/CJSONRenderer.ts b/packages/quicktype-core/src/language/CJSON/CJSONRenderer.ts new file mode 100644 index 000000000..936a0baa4 --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/CJSONRenderer.ts @@ -0,0 +1,5930 @@ +// FIXME: NEEDS REFACTOR +/* eslint-disable @typescript-eslint/no-shadow */ +/* eslint-disable @typescript-eslint/naming-convention */ + +import { getAccessorName } from "../../attributes/AccessorNames"; +import { enumCaseValues } from "../../attributes/EnumValues"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { + type Name, + type NameStyle, + type Namer, + funPrefixNamer, +} from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import type { Sourcelike } from "../../Source"; +import { + type NamingStyle, + allUpperWordStyle, + makeNameStyle, +} from "../../support/Strings"; +import { + assert, + assertNever, + defined, + numberEnumValues, + panic, +} from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + ClassType, + EnumType, + MapType, + type Type, + UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { cJSONOptions } from "./language"; +import { + GlobalNames, + IncludeKind, + type IncludeMap, + type IncludeRecord, + type TypeCJSON, + type TypeRecord, + legalizeName, +} from "./utils"; + +export class CJSONRenderer extends ConvenienceRenderer { + private currentFilename: string | undefined; /* Current filename */ + + private readonly memberNameStyle: NameStyle; /* Member name style */ + + private readonly namedTypeNameStyle: NameStyle; /* Named type name style */ + + private readonly forbiddenGlobalNames: string[]; /* Forbidden global names */ + + protected readonly typeIntegerSize: string; /* Integer code generation type */ + + protected readonly hashtableSize: string; /* Hashtable default size */ + + protected readonly typeNamingStyle: NamingStyle; /* Type naming style */ + + protected readonly enumeratorNamingStyle: NamingStyle; /* Enum naming style */ + + private includes: string[]; + + /** + * Constructor + * @param targetLanguage: target language + * @param renderContext: render context + * @param _options: renderer options + */ + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + this.typeIntegerSize = _options.typeIntegerSize; + this.hashtableSize = _options.hashtableSize; + this.typeNamingStyle = _options.typeNamingStyle; + this.namedTypeNameStyle = makeNameStyle( + this.typeNamingStyle, + legalizeName, + ); + this.enumeratorNamingStyle = _options.enumeratorNamingStyle; + this.memberNameStyle = makeNameStyle( + _options.memberNamingStyle, + legalizeName, + ); + this.forbiddenGlobalNames = []; + this.includes = []; + for (const type of numberEnumValues(GlobalNames)) { + const genName = this.namedTypeNameStyle(GlobalNames[type]); + this.forbiddenGlobalNames.push(genName); + } + } + + /** + * Build forbidden names for namespace + * @return Forbidden names for namespace + */ + protected forbiddenNamesForGlobalNamespace(): string[] { + return [...keywords, ...this.forbiddenGlobalNames]; + } + + /** + * Build forbidden names for enums + * @return Forbidden names for enums + */ + protected forbiddenForEnumCases( + _enumType: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + /** + * Build forbidden names for unions members + * @return Forbidden names for unions members + */ + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + /** + * Build forbidden names for objects + * @return Forbidden names for objects + */ + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + /** + * Build types member names + * @return types member namer + */ + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("types", this.namedTypeNameStyle); + } + + /** + * Build object properties member names + * @return object properties member namer + */ + protected namerForObjectProperty(): Namer { + return funPrefixNamer("members", this.memberNameStyle); + } + + /** + * Build union member names + * @return union member namer + */ + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer("members", this.memberNameStyle); + } + + /** + * Build enum member names + * @return enum member namer + */ + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer( + "enumerators", + makeNameStyle(this.enumeratorNamingStyle, legalizeName), + ); + } + + /** + * Override of super proposeUnionMemberName function + * @param unionType: union type + * @param unionName: union name + * @param fieldType: field type + * @param lookup: Lookup function + * @return Proposed union member name + */ + protected proposeUnionMemberName( + unionType: UnionType, + unionName: Name, + fieldType: Type, + lookup: (n: Name) => string, + ): string { + let fieldName = super.proposeUnionMemberName( + unionType, + unionName, + fieldType, + lookup, + ); + if ("bool" === fieldName) { + fieldName = "boolean"; + } else if ("double" === fieldName) { + fieldName = "number"; + } + + return fieldName; + } + + /** + * Function called to emit typedef alias for a a given type + * @param fieldType: the variable type + * @param fieldName: name of the variable + */ + protected emitTypedefAlias(fieldType: Type, fieldName: Name): void { + if (this._options.addTypedefAlias) { + this.emitLine( + "typedef ", + this.quicktypeTypeToCJSON(fieldType, false).cType, + " ", + fieldName, + ";", + ); + this.ensureBlankLine(); + } + } + + /** + * Function called to create header file(s) + * @param proposedFilename: source filename provided from stdin + */ + protected emitSourceStructure(proposedFilename: string): void { + /* Depending of source style option, generate a unique header or multiple header files */ + if (this._options.typeSourceStyle) { + this.emitSingleSourceStructure(proposedFilename); + } else { + this.emitMultiSourceStructure(); + } + } + + /** + * Function called to create a single header file with types and generators + * @param proposedFilename: source filename provided from stdin + */ + protected emitSingleSourceStructure(proposedFilename: string): void { + /* Create file */ + this.startFile(proposedFilename); + + /* Create types */ + this.forEachDeclaration("leading-and-interposing", (decl) => { + if (decl.kind === "forward") { + this.emitLine("struct ", this.nameForNamedType(decl.type), ";"); + } else if (decl.kind === "define") { + const type = decl.type; + if (type instanceof ClassType) { + this.emitClassTypedef(type); + } else if (type instanceof EnumType) { + this.emitEnumTypedef(type); + } else if (type instanceof UnionType) { + this.emitUnionTypedef(type); + } else { + panic("Cannot declare type"); + } + } else { + assertNever(decl.kind); + } + }); + + /* Create top level type */ + this.forEachTopLevel( + "leading", + (type: Type, className: Name) => + this.emitTopLevelTypedef(type, className), + (type) => this.namedTypeToNameForTopLevel(type) === undefined, + ); + + /* Create enum prototypes */ + this.forEachEnum( + "leading-and-interposing", + (enumType: EnumType, _enumName: Name) => + this.emitEnumPrototypes(enumType), + ); + + /* Create union prototypes */ + this.forEachUnion("leading-and-interposing", (unionType: UnionType) => + this.emitUnionPrototypes(unionType), + ); + + /* Create class prototypes */ + this.forEachObject( + "leading-and-interposing", + (classType: ClassType, _className: Name) => + this.emitClassPrototypes(classType), + ); + + /* Create top level prototypes */ + this.forEachTopLevel( + "leading", + (type: Type, className: Name) => + this.emitTopLevelPrototypes(type, className), + (type) => this.namedTypeToNameForTopLevel(type) === undefined, + ); + + /* Create enum functions */ + this.forEachEnum( + "leading-and-interposing", + (enumType: EnumType, _enumName: Name) => + this.emitEnumFunctions(enumType), + ); + + /* Create union functions */ + this.forEachUnion("leading-and-interposing", (unionType: UnionType) => + this.emitUnionFunctions(unionType), + ); + + /* Create class functions */ + this.forEachObject( + "leading-and-interposing", + (classType: ClassType, _className: Name) => + this.emitClassFunctions(classType), + ); + + /* Create top level functions */ + this.forEachTopLevel( + "leading", + (type: Type, className: Name) => + this.emitTopLevelFunctions(type, className), + (type) => this.namedTypeToNameForTopLevel(type) === undefined, + ); + + /* Close file */ + this.finishFile(); + } + + /** + * Function called to create a multiple header files with types and generators + */ + protected emitMultiSourceStructure(): void { + /* Create each file */ + this.forEachNamedType( + "leading-and-interposing", + (classType: ClassType, _name: Name) => { + this.emitClass(classType); + }, + (enumType, _name) => { + this.emitEnum(enumType); + }, + (unionType, _name) => { + this.emitUnion(unionType); + }, + ); + + /* Create top level file */ + this.forEachTopLevel( + "leading", + (type: Type, className: Name) => + this.emitTopLevel(type, className, this.includes), + (type) => this.namedTypeToNameForTopLevel(type) === undefined, + ); + } + + /** + * Function called to create an enum header files with types and generators + * @param enumType: enum type + */ + protected emitEnum(enumType: EnumType): void { + /* Create file */ + const enumName = this.nameForNamedType(enumType); + const filename = this.sourcelikeToString(enumName).concat(".h"); + this.includes.push(filename); + this.startFile(filename); + + /* Create includes */ + this.emitIncludes(enumType, this.sourcelikeToString(filename)); + + /* Create types */ + this.emitEnumTypedef(enumType); + + /* Create prototypes */ + this.emitEnumPrototypes(enumType); + + /* Create functions */ + this.emitEnumFunctions(enumType); + + /* Close file */ + this.finishFile(); + } + + /** + * Function called to create enum typedef + * @param enumType: enum type + */ + protected emitEnumTypedef(enumType: EnumType): void { + /* FIXME: Now there is a language with need of global enum name, see FIXME in makeNameForEnumCase of ConvenienceRenderer.ts, should simplify here when fixed */ + + const enumName = this.nameForNamedType(enumType); + const enumValues = enumCaseValues(enumType, this.targetLanguage.name); + + this.emitDescription(this.descriptionForType(enumType)); + this.emitBlock( + ["enum ", enumName], + () => { + const combinedName = allUpperWordStyle( + this.sourcelikeToString(enumName), + ); + this.forEachEnumCase(enumType, "none", (name, jsonName) => { + if (enumValues !== undefined) { + const [enumValue] = getAccessorName( + enumValues, + jsonName, + ); + if (enumValue !== undefined) { + this.emitLine( + combinedName, + "_", + name, + " = ", + enumValue.toString(), + ",", + ); + } else { + this.emitLine(combinedName, "_", name, ","); + } + } else { + this.emitLine(combinedName, "_", name, ","); + } + }); + }, + "", + true, + ); + this.ensureBlankLine(); + this.emitTypedefAlias(enumType, enumName); + } + + /** + * Function called to create enum prototypes + * @param enumType: enum type + */ + protected emitEnumPrototypes(enumType: EnumType): void { + const enumName = this.nameForNamedType(enumType); + + this.emitLine( + "enum ", + enumName, + " cJSON_Get", + enumName, + "Value(", + this.withConst("cJSON"), + " * j);", + ); + this.emitLine( + "cJSON * cJSON_Create", + enumName, + "(", + this.withConst(["enum ", enumName]), + " x);", + ); + this.ensureBlankLine(); + } + + /** + * Function called to create enum functions + * @param enumType: enum type + */ + protected emitEnumFunctions(enumType: EnumType): void { + const enumName = this.nameForNamedType(enumType); + + /* Create cJSON to enumName generator function */ + this.emitBlock( + [ + "enum ", + enumName, + " cJSON_Get", + enumName, + "Value(", + this.withConst("cJSON"), + " * j)", + ], + () => { + this.emitLine("enum ", enumName, " x = 0;"); + this.emitBlock(["if (NULL != j)"], () => { + let onFirst = true; + const combinedName = allUpperWordStyle( + this.sourcelikeToString(enumName), + ); + this.forEachEnumCase(enumType, "none", (name, jsonName) => { + this.emitLine( + onFirst ? "" : "else ", + 'if (!strcmp(cJSON_GetStringValue(j), "', + jsonName, + '")) x = ', + combinedName, + "_", + name, + ";", + ); + onFirst = false; + }); + }); + this.emitLine("return x;"); + }, + ); + this.ensureBlankLine(); + + /* Create enumName to cJSON generator function */ + this.emitBlock( + [ + "cJSON * cJSON_Create", + enumName, + "(", + this.withConst(["enum ", enumName]), + " x)", + ], + () => { + this.emitLine("cJSON * j = NULL;"); + this.emitBlock(["switch (x)"], () => { + const combinedName = allUpperWordStyle( + this.sourcelikeToString(enumName), + ); + this.forEachEnumCase(enumType, "none", (name, jsonName) => { + this.emitLine( + "case ", + combinedName, + "_", + name, + ': j = cJSON_CreateString("', + jsonName, + '"); break;', + ); + }); + }); + this.emitLine("return j;"); + }, + ); + this.ensureBlankLine(); + } + + /** + * Function called to create a union header files with types and generators + * @param unionType: union type + */ + protected emitUnion(unionType: UnionType): void { + /* Create file */ + const unionName = this.nameForNamedType(unionType); + const filename = this.sourcelikeToString(unionName).concat(".h"); + this.includes.push(filename); + this.startFile(filename); + + /* Create includes */ + this.emitIncludes(unionType, this.sourcelikeToString(filename)); + + /* Create types */ + this.emitUnionTypedef(unionType); + + /* Create prototypes */ + this.emitUnionPrototypes(unionType); + + /* Create functions */ + this.emitUnionFunctions(unionType); + + /* Close file */ + this.finishFile(); + } + + /** + * Function called to create union typedef + * @param unionType: union type + */ + protected emitUnionTypedef(unionType: UnionType): void { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [_hasNull, nonNulls] = removeNullFromUnion(unionType); + const unionName = this.nameForNamedType(unionType); + + this.emitDescription(this.descriptionForType(unionType)); + this.emitBlock( + ["struct ", unionName], + () => { + this.emitLine("int type;"); + this.emitBlock( + ["union"], + () => { + for (const type of nonNulls) { + const cJSON = this.quicktypeTypeToCJSON( + type, + false, + ); + this.emitLine( + cJSON.cType, + cJSON.optionalQualifier !== "" ? " " : "", + cJSON.optionalQualifier, + " ", + this.nameForUnionMember(unionType, type), + ";", + ); + } + }, + "value", + true, + ); + }, + "", + true, + ); + this.ensureBlankLine(); + this.emitTypedefAlias(unionType, unionName); + } + + /** + * Function called to create union prototypes + * @param unionType: union type + */ + protected emitUnionPrototypes(unionType: UnionType): void { + const unionName = this.nameForNamedType(unionType); + + this.emitLine( + "struct ", + unionName, + " * cJSON_Get", + unionName, + "Value(const cJSON * j);", + ); + this.emitLine( + "cJSON * cJSON_Create", + unionName, + "(", + this.withConst(["struct ", unionName]), + " * x);", + ); + this.emitLine( + "void cJSON_Delete", + unionName, + "(struct ", + unionName, + " * x);", + ); + this.ensureBlankLine(); + } + + /** + * Function called to create union functions + * @param unionType: union type + */ + protected emitUnionFunctions(unionType: UnionType): void { + const [hasNull, nonNulls] = removeNullFromUnion(unionType); + const unionName = this.nameForNamedType(unionType); + + /* Create cJSON to unionType generator function */ + this.emitBlock( + [ + "struct ", + unionName, + " * cJSON_Get", + unionName, + "Value(const cJSON * j)", + ], + () => { + let onFirst = true; + this.emitLine( + "struct ", + unionName, + " * x = cJSON_malloc(sizeof(struct ", + unionName, + "));", + ); + this.emitBlock(["if (NULL != x)"], () => { + this.emitLine( + "memset(x, 0, sizeof(struct ", + unionName, + "));", + ); + if (hasNull !== null) { + this.emitBlock(["if (cJSON_IsNull(j))"], () => { + this.emitLine("x->type = cJSON_NULL;"); + }); + onFirst = false; + } + + for (const type of nonNulls) { + const cJSON = this.quicktypeTypeToCJSON(type, false); + this.emitBlock( + [ + onFirst === true ? "if (" : "else if (", + cJSON.isType, + "(j))", + ], + () => { + this.emitLine( + "x->type = ", + cJSON.cjsonType, + ";", + ); + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + const level = 0; + const child_level = 1; + this.emitLine( + cJSON.cType, + " * x", + child_level.toString(), + " = list_create(false, NULL);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "cJSON * e", + child_level.toString(), + " = NULL;", + ); + this.emitBlock( + [ + "cJSON_ArrayForEach(e", + child_level.toString(), + ", j", + level > 0 + ? level.toString() + : "", + ")", + ], + () => { + const add = ( + cJSON: TypeCJSON, + level: number, + child_level: number, + ) => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" || + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", (", + cJSON.items + ?.cType, + " *)0xDEADBEEF, sizeof(", + cJSON.items + ?.cType, + " *));", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", strdup(", + cJSON.items + ?.getValue, + "(e", + child_level.toString(), + ")), sizeof(", + cJSON.items + ?.cType, + " *));", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Object" || + cJSON.items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", ", + cJSON.items + ?.getValue, + "(e", + child_level.toString(), + "), sizeof(", + cJSON.items + ?.cType, + " *));", + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.cType, + " * tmp", + level > 0 + ? level.toString() + : "", + " = cJSON_malloc(sizeof(", + cJSON.items + ?.cType, + "));", + ); + this.emitBlock( + [ + "if (NULL != tmp", + level > 0 + ? level.toString() + : "", + ")", + ], + () => { + this.emitLine( + "* tmp", + level > + 0 + ? level.toString() + : "", + " = ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + ");", + ); + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", tmp", + level > + 0 + ? level.toString() + : "", + ", sizeof(", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " *));", + ); + }, + ); + } + }; + + if ( + cJSON.items?.isNullable + ) { + this.emitBlock( + [ + "if (!cJSON_IsNull(e", + child_level.toString(), + "))", + ], + () => { + add( + cJSON, + level, + child_level, + ); + }, + ); + this.emitBlock( + ["else"], + () => { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", (void *)0xDEADBEEF, sizeof(void *));", + ); + }, + ); + } else { + add( + cJSON, + level, + child_level, + ); + } + }, + ); + this.emitLine( + "x->value.", + this.nameForUnionMember( + unionType, + type, + ), + " = x", + child_level.toString(), + ";", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + const level = 0; + const child_level = 1; + this.emitLine( + cJSON.cType, + " * x", + child_level.toString(), + " = hashtable_create(", + this.hashtableSize, + ", false);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "cJSON * e", + child_level.toString(), + " = NULL;", + ); + this.emitBlock( + [ + "cJSON_ArrayForEach(e", + child_level.toString(), + ", j", + level > 0 + ? level.toString() + : "", + ")", + ], + () => { + const add = ( + cJSON: TypeCJSON, + level: number, + child_level: number, + ) => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" || + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, (", + cJSON.items + ?.cType, + " *)0xDEADBEEF, sizeof(", + cJSON.items + ?.cType, + " *));", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, strdup(", + cJSON.items + ?.getValue, + "(e", + child_level.toString(), + ")), sizeof(", + cJSON.items + ?.cType, + " *));", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Object" || + cJSON.items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, ", + cJSON.items + ?.getValue, + "(e", + child_level.toString(), + "), sizeof(", + cJSON.items + ?.cType, + " *));", + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.cType, + " * tmp", + level > 0 + ? level.toString() + : "", + " = cJSON_malloc(sizeof(", + cJSON.items + ?.cType, + "));", + ); + this.emitBlock( + [ + "if (NULL != tmp", + level > 0 + ? level.toString() + : "", + ")", + ], + () => { + this.emitLine( + "* tmp", + level > + 0 + ? level.toString() + : "", + " = ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + ");", + ); + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, tmp", + level > + 0 + ? level.toString() + : "", + ", sizeof(", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " *));", + ); + }, + ); + } + }; + + if ( + cJSON.items?.isNullable + ) { + this.emitBlock( + [ + "if (!cJSON_IsNull(e", + child_level.toString(), + "))", + ], + () => { + add( + cJSON, + level, + child_level, + ); + }, + ); + this.emitBlock( + ["else"], + () => { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, (void *)0xDEADBEEF, sizeof(void *));", + ); + }, + ); + } else { + add( + cJSON, + level, + child_level, + ); + } + }, + ); + this.emitLine( + "x->value.", + this.nameForUnionMember( + unionType, + type, + ), + " = x", + child_level.toString(), + ";", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Invalid" || + cJSON.cjsonType === "cJSON_NULL" + ) { + this.emitLine( + "x->value.", + this.nameForUnionMember( + unionType, + type, + ), + " = (", + cJSON.cType, + " *)0xDEADBEEF;", + ); + } else if (cJSON.cjsonType === "cJSON_String") { + this.emitLine( + "x->value.", + this.nameForUnionMember( + unionType, + type, + ), + " = strdup(", + cJSON.getValue, + "(j));", + ); + } else { + this.emitLine( + "x->value.", + this.nameForUnionMember( + unionType, + type, + ), + " = ", + cJSON.getValue, + "(j);", + ); + } + }, + ); + onFirst = false; + } + }); + this.emitLine("return x;"); + }, + ); + this.ensureBlankLine(); + + /* Create unionName to cJSON generator function */ + this.emitBlock( + [ + "cJSON * cJSON_Create", + unionName, + "(", + this.withConst(["struct ", unionName]), + " * x)", + ], + () => { + this.emitLine("cJSON * j = NULL;"); + this.emitBlock(["if (NULL != x)"], () => { + let onFirst = true; + if (hasNull !== null) { + this.emitBlock(["if (cJSON_NULL == x->type)"], () => { + this.emitLine("j = cJSON_CreateNull();"); + }); + onFirst = false; + } + + for (const type of nonNulls) { + const cJSON = this.quicktypeTypeToCJSON(type, false); + this.emitBlock( + [ + onFirst === true ? "if (" : "else if (", + cJSON.cjsonType, + " == x->type)", + ], + () => { + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + const level = 0; + const child_level = 1; + this.emitLine( + "cJSON * j", + child_level.toString(), + " = ", + cJSON.createObject, + "();", + ); + this.emitBlock( + [ + "if (NULL != j", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " * x", + child_level.toString(), + " = list_get_head(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + this.emitBlock( + [ + "while (NULL != x", + child_level.toString(), + ")", + ], + () => { + const add = ( + cJSON: TypeCJSON, + child_level: number, + ) => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON.items + ?.createObject, + "());", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_String" || + cJSON.items + ?.cjsonType === + "cJSON_Object" || + cJSON.items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON.items + ?.createObject, + "(x", + child_level.toString(), + "));", + ); + } else { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + // @ts-expect-error awaiting refactor + cJSON.items + ?.createObject, + "(*x", + child_level.toString(), + "));", + ); + } + }; + + if ( + cJSON.items?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + add( + cJSON, + child_level, + ); + }, + ); + this.emitBlock( + ["else"], + () => { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", cJSON_CreateNull());", + ); + }, + ); + } else { + add(cJSON, child_level); + } + + this.emitLine( + "x", + child_level.toString(), + " = list_get_next(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + }, + ); + this.emitLine( + "j = j", + child_level.toString(), + ";", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + const level = 0; + const child_level = 1; + this.emitLine( + "cJSON * j", + child_level.toString(), + " = ", + cJSON.createObject, + "();", + ); + this.emitBlock( + [ + "if (NULL != j", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "char **keys", + child_level.toString(), + " = NULL;", + ); + this.emitLine( + "size_t count", + child_level.toString(), + " = hashtable_get_keys(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ", &keys", + child_level.toString(), + ");", + ); + this.emitBlock( + [ + "if (NULL != keys", + child_level.toString(), + ")", + ], + () => { + this.emitBlock( + [ + "for (size_t index", + child_level.toString(), + " = 0; index", + child_level.toString(), + " < count", + child_level.toString(), + "; index", + child_level.toString(), + "++)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.cType, + " *x", + child_level.toString(), + " = hashtable_lookup(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "]);", + ); + const add = ( + cJSON: TypeCJSON, + child_level: number, + ) => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], ", + cJSON + .items + ?.createObject, + "());", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_String" || + cJSON.items + ?.cjsonType === + "cJSON_Object" || + cJSON.items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], ", + cJSON + .items + ?.createObject, + "(x", + child_level.toString(), + "));", + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.createObject, + "(*x", + child_level.toString(), + "));", + ); + } + }; + + if ( + cJSON.items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + add( + cJSON, + child_level, + ); + }, + ); + this.emitBlock( + ["else"], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], cJSON_CreateNull());", + ); + }, + ); + } else { + add( + cJSON, + child_level, + ); + } + }, + ); + this.emitLine( + "cJSON_free(keys", + child_level.toString(), + ");", + ); + }, + ); + this.emitLine( + "j = j", + child_level.toString(), + ";", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if (cJSON.cjsonType === "cJSON_NULL") { + this.emitLine( + "j = ", + cJSON.createObject, + "();", + ); + } else { + this.emitLine( + "j = ", + cJSON.createObject, + "(x->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + } + }, + ); + onFirst = false; + } + }); + this.emitLine("return j;"); + }, + ); + this.ensureBlankLine(); + + /* Create unionName delete function */ + this.emitBlock( + ["void cJSON_Delete", unionName, "(struct ", unionName, " * x)"], + () => { + this.emitBlock(["if (NULL != x)"], () => { + let onFirst = true; + for (const type of nonNulls) { + const cJSON = this.quicktypeTypeToCJSON(type, false); + this.emitBlock( + [ + onFirst === true ? "if (" : "else if (", + cJSON.cjsonType, + " == x->type)", + ], + () => { + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + const level = 0; + const child_level = 1; + this.emitBlock( + [ + "if (NULL != x", + level > 0 ? level.toString() : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " * x", + child_level.toString(), + " = list_get_head(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + this.emitBlock( + [ + "while (NULL != x", + child_level.toString(), + ")", + ], + () => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" || + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + /* Nothing to do */ + } else { + if ( + cJSON.items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + }, + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + } + } + + this.emitLine( + "x", + child_level.toString(), + " = list_get_next(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + }, + ); + this.emitLine( + cJSON.deleteType, + "(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + const level = 0; + const child_level = 1; + this.emitBlock( + [ + "if (NULL != x", + level > 0 ? level.toString() : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ")", + ], + () => { + this.emitLine( + "char **keys", + child_level.toString(), + " = NULL;", + ); + this.emitLine( + "size_t count", + child_level.toString(), + " = hashtable_get_keys(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ", &keys", + child_level.toString(), + ");", + ); + this.emitBlock( + [ + "if (NULL != keys", + child_level.toString(), + ")", + ], + () => { + this.emitBlock( + [ + "for (size_t index", + child_level.toString(), + " = 0; index", + child_level.toString(), + " < count", + child_level.toString(), + "; index", + child_level.toString(), + "++)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.cType, + " *x", + child_level.toString(), + " = hashtable_lookup(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "]);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + if ( + cJSON + .items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Invalid" || + cJSON + .items + ?.cjsonType === + "cJSON_NULL" + ) { + /* Nothing to do */ + } else { + if ( + cJSON + .items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + }, + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + } + } + }, + ); + }, + ); + this.emitLine( + "cJSON_free(keys", + child_level.toString(), + ");", + ); + }, + ); + this.emitLine( + cJSON.deleteType, + "(x", + level > 0 + ? level.toString() + : "", + "->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Invalid" || + cJSON.cjsonType === "cJSON_NULL" + ) { + /* Nothing to do */ + } else if ( + cJSON.cjsonType === "cJSON_String" || + cJSON.cjsonType === "cJSON_Object" || + cJSON.cjsonType === "cJSON_Union" + ) { + this.emitLine( + cJSON.deleteType, + "(x->value.", + this.nameForUnionMember( + unionType, + type, + ), + ");", + ); + } else { + /* Nothing to do */ + } + }, + ); + onFirst = false; + } + + this.emitLine("cJSON_free(x);"); + }); + }, + ); + this.ensureBlankLine(); + } + + /** + * Function called to create a class header files with types and generators + * @param classType: class type + */ + protected emitClass(classType: ClassType): void { + /* Create file */ + const className = this.nameForNamedType(classType); + const filename = this.sourcelikeToString(className).concat(".h"); + this.includes.push(filename); + this.startFile(filename); + + /* Create includes */ + this.emitIncludes(classType, this.sourcelikeToString(filename)); + + /* Create types */ + this.emitClassTypedef(classType); + + /* Create prototypes */ + this.emitClassPrototypes(classType); + + /* Create functions */ + this.emitClassFunctions(classType); + + /* Close file */ + this.finishFile(); + } + + /** + * Function called to create class typedef + * @param classType: class type + */ + protected emitClassTypedef(classType: ClassType): void { + const className = this.nameForNamedType(classType); + + this.emitDescription(this.descriptionForType(classType)); + this.emitBlock( + ["struct ", className], + () => { + this.forEachClassProperty( + classType, + "none", + (name, jsonName, property) => { + this.emitDescription( + this.descriptionForClassProperty( + classType, + jsonName, + ), + ); + const cJSON = this.quicktypeTypeToCJSON( + property.type, + property.isOptional, + ); + this.emitLine( + cJSON.cType, + cJSON.optionalQualifier !== "" ? " " : "", + cJSON.optionalQualifier, + " ", + name, + ";", + ); + }, + ); + }, + "", + true, + ); + this.ensureBlankLine(); + this.emitTypedefAlias(classType, className); + } + + /** + * Function called to create class prototypes + * @param classType: class type + */ + protected emitClassPrototypes(classType: ClassType): void { + const className = this.nameForNamedType(classType); + + this.emitLine( + "struct ", + className, + " * cJSON_Parse", + className, + "(", + this.withConst("char"), + " * s);", + ); + this.emitLine( + "struct ", + className, + " * cJSON_Get", + className, + "Value(", + this.withConst("cJSON"), + " * j);", + ); + this.emitLine( + "cJSON * cJSON_Create", + className, + "(", + this.withConst(["struct ", className]), + " * x);", + ); + this.emitLine( + "char * cJSON_Print", + className, + "(", + this.withConst(["struct ", className]), + " * x);", + ); + this.emitLine( + "void cJSON_Delete", + className, + "(struct ", + className, + " * x);", + ); + this.ensureBlankLine(); + } + + /** + * Function called to create class functions + * @param classType: class type + */ + protected emitClassFunctions(classType: ClassType): void { + const className = this.nameForNamedType(classType); + + /* Create string to className generator function */ + this.emitBlock( + [ + "struct ", + className, + " * cJSON_Parse", + className, + "(", + this.withConst("char"), + " * s)", + ], + () => { + this.emitLine("struct ", className, " * x = NULL;"); + this.emitBlock(["if (NULL != s)"], () => { + this.emitLine("cJSON * j = cJSON_Parse(s);"); + this.emitBlock(["if (NULL != j)"], () => { + this.emitLine("x = cJSON_Get", className, "Value(j);"); + this.emitLine("cJSON_Delete(j);"); + }); + }); + this.emitLine("return x;"); + }, + ); + this.ensureBlankLine(); + + /* Create cJSON to className generator function */ + this.emitBlock( + [ + "struct ", + className, + " * cJSON_Get", + className, + "Value(", + this.withConst("cJSON"), + " * j)", + ], + () => { + this.emitLine("struct ", className, " * x = NULL;"); + this.emitBlock(["if (NULL != j)"], () => { + this.emitBlock( + [ + "if (NULL != (x = cJSON_malloc(sizeof(struct ", + className, + "))))", + ], + () => { + this.emitLine( + "memset(x, 0, sizeof(struct ", + className, + "));", + ); + const recur = (type: Type, level: number) => { + if (type instanceof ArrayType) { + const child_level = level + 1; + const cJSON = this.quicktypeTypeToCJSON( + type.items, + false, + ); + this.emitLine( + "list_t * x", + child_level.toString(), + " = list_create(false, NULL);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "cJSON * e", + child_level.toString(), + " = NULL;", + ); + this.emitBlock( + [ + "cJSON_ArrayForEach(e", + child_level.toString(), + ", e", + level.toString(), + ")", + ], + () => { + if ( + cJSON.cjsonType === + "cJSON_Array" + ) { + const child_level2 = + child_level + 1; + recur( + type.items, + child_level, + ); + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", x", + child_level2.toString(), + ", sizeof(", + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " *));", + ); + } else if ( + cJSON.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.cjsonType === + "cJSON_Invalid" || + cJSON.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", (", + cJSON.cType, + " *)0xDEADBEEF, sizeof(", + cJSON.cType, + " *));", + ); + } else if ( + cJSON.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", strdup(", + cJSON.getValue, + "(e", + child_level.toString(), + ")), sizeof(", + cJSON.cType, + " *));", + ); + } else if ( + cJSON.cjsonType === + "cJSON_Object" || + cJSON.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", ", + cJSON.getValue, + "(e", + child_level.toString(), + "), sizeof(", + cJSON.cType, + " *));", + ); + } else { + this.emitLine( + cJSON.cType, + " * tmp", + level > 0 + ? level.toString() + : "", + " = cJSON_malloc(sizeof(", + cJSON.cType, + "));", + ); + this.emitBlock( + [ + "if (NULL != tmp", + level > 0 + ? level.toString() + : "", + ")", + ], + () => { + this.emitLine( + "* tmp", + level > 0 + ? level.toString() + : "", + " = ", + cJSON.getValue, + "(e", + child_level.toString(), + ");", + ); + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", tmp", + level > 0 + ? level.toString() + : "", + ", sizeof(", + cJSON.cType, + " *));", + ); + }, + ); + } + }, + ); + }, + ); + } else if (type instanceof ClassType) { + this.forEachClassProperty( + type, + "none", + (name, jsonName, property) => { + const cJSON = + this.quicktypeTypeToCJSON( + property.type, + property.isOptional, + ); + this.emitBlock( + !cJSON.isNullable + ? [ + "if (cJSON_HasObjectItem(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '"))', + ] + : [ + "if ((cJSON_HasObjectItem(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '")) && (!cJSON_IsNull(cJSON_GetObjectItemCaseSensitive(j', + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '"))))', + ], + () => { + if ( + cJSON.cjsonType === + "cJSON_Array" && + cJSON.items !== + undefined + ) { + const child_level = + level + 1; + this.emitLine( + cJSON.cType, + " * x", + child_level.toString(), + " = list_create(false, NULL);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "cJSON * e", + child_level.toString(), + " = NULL;", + ); + this.emitLine( + "cJSON * j", + child_level.toString(), + " = cJSON_GetObjectItemCaseSensitive(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '");', + ); + this.emitBlock( + [ + "cJSON_ArrayForEach(e", + child_level.toString(), + ", j", + child_level.toString(), + ")", + ], + () => { + const add = + ( + type: Type, + cJSON: TypeCJSON, + level: number, + child_level: number, + ) => { + if ( + cJSON + .items + ?.cjsonType === + "cJSON_Array" + ) { + if ( + type instanceof + ArrayType + ) { + const child_level2 = + child_level + + 1; + recur( + type.items, + child_level, + ); + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", x", + child_level2.toString(), + ", sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else { + panic( + "Invalid type", + ); + } + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Invalid" || + cJSON + .items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", (", + cJSON + .items + ?.cType, + " *)0xDEADBEEF, sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", strdup(", + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + ")), sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Object" || + cJSON + .items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", ", + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + "), sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " * tmp", + level > + 0 + ? level.toString() + : "", + " = cJSON_malloc(sizeof(", + cJSON + .items + ?.cType, + "));", + ); + this.emitBlock( + [ + "if (NULL != tmp", + level > + 0 + ? level.toString() + : "", + ")", + ], + () => { + this.emitLine( + "* tmp", + level > + 0 + ? level.toString() + : "", + " = ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + ");", + ); + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", tmp", + level > + 0 + ? level.toString() + : "", + ", sizeof(", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " *));", + ); + }, + ); + } + }; + + if ( + cJSON + .items + ?.isNullable + ) { + this.emitBlock( + [ + "if (!cJSON_IsNull(e", + child_level.toString(), + "))", + ], + () => { + add( + property.type, + cJSON, + level, + child_level, + ); + }, + ); + this.emitBlock( + [ + "else", + ], + () => { + this.emitLine( + "list_add_tail(x", + child_level.toString(), + ", (void *)0xDEADBEEF, sizeof(void *));", + ); + }, + ); + } else { + add( + property.type, + cJSON, + level, + child_level, + ); + } + }, + ); + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = x", + child_level.toString(), + ";", + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_Map" && + cJSON.items !== + undefined + ) { + const child_level = + level + 1; + this.emitLine( + cJSON.cType, + " * x", + child_level.toString(), + " = hashtable_create(", + this.hashtableSize, + ", false);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "cJSON * e", + child_level.toString(), + " = NULL;", + ); + this.emitLine( + "cJSON * j", + child_level.toString(), + " = cJSON_GetObjectItemCaseSensitive(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '");', + ); + this.emitBlock( + [ + "cJSON_ArrayForEach(e", + child_level.toString(), + ", j", + child_level.toString(), + ")", + ], + () => { + const add = + ( + type: Type, + cJSON: TypeCJSON, + level: number, + child_level: number, + ) => { + if ( + cJSON + .items + ?.cjsonType === + "cJSON_Array" + ) { + if ( + type instanceof + MapType + ) { + const child_level2 = + child_level + + 1; + recur( + type.values, + child_level, + ); + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, x", + child_level2.toString(), + ", sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else { + panic( + "Invalid type", + ); + } + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Invalid" || + cJSON + .items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, (", + cJSON + .items + ?.cType, + " *)0xDEADBEEF, sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, strdup(", + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + ")), sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Object" || + cJSON + .items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, ", + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + "), sizeof(", + cJSON + .items + ?.cType, + " *));", + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " * tmp", + level > + 0 + ? level.toString() + : "", + " = cJSON_malloc(sizeof(", + cJSON + .items + ?.cType, + "));", + ); + this.emitBlock( + [ + "if (NULL != tmp", + level > + 0 + ? level.toString() + : "", + ")", + ], + () => { + this.emitLine( + "* tmp", + level > + 0 + ? level.toString() + : "", + " = ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.getValue, + "(e", + child_level.toString(), + ");", + ); + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, tmp", + level > + 0 + ? level.toString() + : "", + ", sizeof(", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " *));", + ); + }, + ); + } + }; + + if ( + cJSON + .items + ?.isNullable + ) { + this.emitBlock( + [ + "if (!cJSON_IsNull(e", + child_level.toString(), + "))", + ], + () => { + add( + property.type, + cJSON, + level, + child_level, + ); + }, + ); + this.emitBlock( + [ + "else", + ], + () => { + this.emitLine( + "hashtable_add(x", + child_level.toString(), + ", e", + child_level.toString(), + "->string, (void *)0xDEADBEEF, sizeof(void *));", + ); + }, + ); + } else { + add( + property.type, + cJSON, + level, + child_level, + ); + } + }, + ); + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = x", + child_level.toString(), + ";", + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_Invalid" || + cJSON.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = (", + cJSON.cType, + " *)0xDEADBEEF;", + ); + } else if ( + cJSON.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = strdup(", + cJSON.getValue, + "(cJSON_GetObjectItemCaseSensitive(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '")));', + ); + } else if ( + cJSON.cjsonType === + "cJSON_Object" || + cJSON.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = ", + cJSON.getValue, + "(cJSON_GetObjectItemCaseSensitive(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '"));', + ); + } else { + if ( + property.isOptional || + cJSON.isNullable + ) { + this.emitBlock( + [ + "if (NULL != (x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = cJSON_malloc(sizeof(", + cJSON.cType, + "))))", + ], + () => { + this.emitLine( + "*x", + level > + 0 + ? level.toString() + : "", + "->", + name, + " = ", + cJSON.getValue, + "(cJSON_GetObjectItemCaseSensitive(j", + level > + 0 + ? level.toString() + : "", + ', "', + jsonName, + '"));', + ); + }, + ); + } else { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = ", + cJSON.getValue, + "(cJSON_GetObjectItemCaseSensitive(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '"));', + ); + } + } + }, + ); + if ( + !property.isOptional && + !cJSON.isNullable + ) { + if ( + cJSON.cjsonType === + "cJSON_Array" + ) { + this.emitBlock( + ["else"], + () => { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = list_create(false, NULL);", + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_Map" + ) { + this.emitBlock( + ["else"], + () => { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = hashtable_create(", + this + .hashtableSize, + ", false);", + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_Invalid" || + cJSON.cjsonType === + "cJSON_NULL" + ) { + this.emitBlock( + ["else"], + () => { + this.emitLine( + "x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = (", + cJSON.cType, + " *)0xDEADBEEF;", + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_String" + ) { + this.emitBlock( + ["else"], + () => { + this.emitBlock( + [ + "if (NULL != (x", + level > 0 + ? level.toString() + : "", + "->", + name, + " = cJSON_malloc(sizeof(", + cJSON.cType, + "))))", + ], + () => { + this.emitLine( + "x", + level > + 0 + ? level.toString() + : "", + "->", + name, + "[0] = '\\0';", + ); + }, + ); + }, + ); + } else { + /* Nothing to do */ + } + } + }, + ); + } + }; + + recur(classType, 0); + }, + ); + }); + this.emitLine("return x;"); + }, + ); + this.ensureBlankLine(); + + /* Create className to cJSON generator function */ + this.emitBlock( + [ + "cJSON * cJSON_Create", + className, + "(", + this.withConst(["struct ", className]), + " * x)", + ], + () => { + this.emitLine("cJSON * j = NULL;"); + this.emitBlock(["if (NULL != x)"], () => { + this.emitBlock( + ["if (NULL != (j = cJSON_CreateObject()))"], + () => { + const recur = (type: Type, level: number) => { + if (type instanceof ArrayType) { + const child_level = level + 1; + const cJSON = this.quicktypeTypeToCJSON( + type.items, + false, + ); + this.emitLine( + "cJSON * j", + child_level.toString(), + " = cJSON_CreateArray();", + ); + this.emitBlock( + [ + "if (NULL != j", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + cJSON.cType, + " * x", + child_level.toString(), + " = list_get_head(x", + level.toString(), + ");", + ); + this.emitBlock( + [ + "while (NULL != x", + child_level.toString(), + ")", + ], + () => { + if ( + cJSON.cjsonType === + "cJSON_Array" + ) { + const child_level2 = + child_level + 1; + recur( + type.items, + child_level, + ); + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", j", + child_level2.toString(), + ");", + ); + } else if ( + cJSON.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON.createObject, + "());", + ); + } else if ( + cJSON.cjsonType === + "cJSON_String" || + cJSON.cjsonType === + "cJSON_Object" || + cJSON.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON.createObject, + "(x", + child_level.toString(), + "));", + ); + } else { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON.createObject, + "(*x", + child_level.toString(), + "));", + ); + } + + this.emitLine( + "x", + child_level.toString(), + " = list_get_next(x", + level.toString(), + ");", + ); + }, + ); + }, + ); + } else if (type instanceof ClassType) { + this.forEachClassProperty( + type, + "none", + (name, jsonName, property) => { + const cJSON = + this.quicktypeTypeToCJSON( + property.type, + property.isOptional, + ); + if ( + cJSON.cjsonType === + "cJSON_Array" && + cJSON.items !== undefined + ) { + const child_level = level + 1; + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + "cJSON * j", + child_level.toString(), + " = cJSON_AddArrayToObject(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '");', + ); + this.emitBlock( + [ + "if (NULL != j", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.cType, + " * x", + child_level.toString(), + " = list_get_head(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + this.emitBlock( + [ + "while (NULL != x", + child_level.toString(), + ")", + ], + () => { + const add = + ( + type: Type, + cJSON: TypeCJSON, + child_level: number, + ) => { + if ( + cJSON + .items + ?.cjsonType === + "cJSON_Array" + ) { + if ( + type instanceof + ArrayType + ) { + const child_level2 = + child_level + + 1; + recur( + type.items, + child_level, + ); + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", j", + child_level2.toString(), + ");", + ); + } else { + panic( + "Invalid type", + ); + } + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON + .items + ?.createObject, + "());", + ); + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_String" || + cJSON + .items + ?.cjsonType === + "cJSON_Object" || + cJSON + .items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + cJSON + .items + ?.createObject, + "(x", + child_level.toString(), + "));", + ); + } else { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.createObject, + "(*x", + child_level.toString(), + "));", + ); + } + }; + + if ( + cJSON + .items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + add( + property.type, + cJSON, + child_level, + ); + }, + ); + this.emitBlock( + [ + "else", + ], + () => { + this.emitLine( + "cJSON_AddItemToArray(j", + child_level.toString(), + ", cJSON_CreateNull());", + ); + }, + ); + } else { + add( + property.type, + cJSON, + child_level, + ); + } + + this.emitLine( + "x", + child_level.toString(), + " = list_get_next(x", + level > + 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + }, + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_Map" && + cJSON.items !== undefined + ) { + const child_level = level + 1; + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + "cJSON * j", + child_level.toString(), + " = ", + cJSON.createObject, + "();", + ); + this.emitBlock( + [ + "if (NULL != j", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + "char **keys", + child_level.toString(), + " = NULL;", + ); + this.emitLine( + "size_t count", + child_level.toString(), + " = hashtable_get_keys(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ", &keys", + child_level.toString(), + ");", + ); + this.emitBlock( + [ + "if (NULL != keys", + child_level.toString(), + ")", + ], + () => { + this.emitBlock( + [ + "for (size_t index", + child_level.toString(), + " = 0; index", + child_level.toString(), + " < count", + child_level.toString(), + "; index", + child_level.toString(), + "++)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.cType, + " *x", + child_level.toString(), + " = hashtable_lookup(x", + level > + 0 + ? level.toString() + : "", + "->", + name, + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "]);", + ); + const add = + ( + type: Type, + cJSON: TypeCJSON, + child_level: number, + ) => { + if ( + cJSON + .items + ?.cjsonType === + "cJSON_Array" + ) { + if ( + type instanceof + MapType + ) { + const child_level2 = + child_level + + 1; + recur( + type.values, + child_level, + ); + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], j", + child_level2.toString(), + ");", + ); + } else { + panic( + "Invalid type", + ); + } + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], ", + cJSON + .items + ?.createObject, + "());", + ); + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_String" || + cJSON + .items + ?.cjsonType === + "cJSON_Object" || + cJSON + .items + ?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], ", + cJSON + .items + ?.createObject, + "(x", + child_level.toString(), + "));", + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], ", + // @ts-expect-error awaiting refactor + cJSON + .items + ?.createObject, + "(*x", + child_level.toString(), + "));", + ); + } + }; + + if ( + cJSON + .items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + add( + property.type, + cJSON, + child_level, + ); + }, + ); + this.emitBlock( + [ + "else", + ], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + child_level.toString(), + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "], cJSON_CreateNull());", + ); + }, + ); + } else { + add( + property.type, + cJSON, + child_level, + ); + } + }, + ); + this.emitLine( + "cJSON_free(keys", + child_level.toString(), + ");", + ); + }, + ); + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", j', + child_level.toString(), + ");", + ); + }, + ); + }, + ); + } else if ( + cJSON.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON.cjsonType === "cJSON_NULL" + ) { + if (property.isOptional) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '");', + ); + }, + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '");', + ); + } + } else if ( + cJSON.cjsonType === + "cJSON_String" + ) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", x', + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + if ( + !property.isOptional && + !cJSON.isNullable + ) { + this.emitBlock( + ["else"], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", "");', + ); + }, + ); + } + } else if ( + cJSON.cjsonType === + "cJSON_Object" || + cJSON.cjsonType === + "cJSON_Union" + ) { + if ( + property.isOptional || + cJSON.isNullable + ) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", ', + cJSON.createObject, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + "));", + ); + }, + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", ', + cJSON.createObject, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + "));", + ); + } + } else if ( + cJSON.cjsonType === "cJSON_Enum" + ) { + if ( + property.isOptional || + cJSON.isNullable + ) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", ', + cJSON.createObject, + "(*x", + level > 0 + ? level.toString() + : "", + "->", + name, + "));", + ); + }, + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", ', + cJSON.createObject, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + "));", + ); + } + } else { + if ( + property.isOptional || + cJSON.isNullable + ) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", *x', + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '", x', + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + } + } + + if (cJSON.isNullable) { + this.emitBlock(["else"], () => { + this.emitLine( + "cJSON_AddNullToObject(j", + level > 0 + ? level.toString() + : "", + ', "', + jsonName, + '");', + ); + }); + } + }, + ); + } + }; + + recur(classType, 0); + }, + ); + }); + this.emitLine("return j;"); + }, + ); + this.ensureBlankLine(); + + /* Create className to string generator function */ + this.emitBlock( + [ + "char * cJSON_Print", + className, + "(", + this.withConst(["struct ", className]), + " * x)", + ], + () => { + this.emitLine("char * s = NULL;"); + this.emitBlock(["if (NULL != x)"], () => { + this.emitLine( + "cJSON * j = cJSON_Create", + className, + "(x);", + ); + this.emitBlock(["if (NULL != j)"], () => { + this.emitLine( + this._options.printStyle + ? "s = cJSON_PrintUnformatted(j);" + : "s = cJSON_Print(j);", + ); + this.emitLine("cJSON_Delete(j);"); + }); + }); + this.emitLine("return s;"); + }, + ); + this.ensureBlankLine(); + + /* Create className delete function */ + this.emitBlock( + ["void cJSON_Delete", className, "(struct ", className, " * x)"], + () => { + this.emitBlock(["if (NULL != x)"], () => { + const recur = (type: Type, level: number) => { + if (type instanceof ArrayType) { + const child_level = level + 1; + const cJSON = this.quicktypeTypeToCJSON( + type.items, + false, + ); + this.emitLine( + cJSON.cType, + " * x", + child_level.toString(), + " = list_get_head(x", + level.toString(), + ");", + ); + this.emitBlock( + [ + "while (NULL != x", + child_level.toString(), + ")", + ], + () => { + if (cJSON.cjsonType === "cJSON_Array") { + recur(type.items, child_level); + this.emitLine( + cJSON.deleteType, + "(x", + child_level.toString(), + ");", + ); + } else if ( + cJSON.cjsonType === "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.cjsonType === "cJSON_Invalid" || + cJSON.cjsonType === "cJSON_NULL" + ) { + /* Nothing to do */ + } else { + this.emitLine( + cJSON.deleteType, + "(x", + child_level.toString(), + ");", + ); + } + + this.emitLine( + "x", + child_level.toString(), + " = list_get_next(x", + level.toString(), + ");", + ); + }, + ); + } else if (type instanceof ClassType) { + this.forEachClassProperty( + type, + "none", + (name, _jsonName, property) => { + const cJSON = this.quicktypeTypeToCJSON( + property.type, + property.isOptional, + ); + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + const child_level = level + 1; + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " * x", + child_level.toString(), + " = list_get_head(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + this.emitBlock( + [ + "while (NULL != x", + child_level.toString(), + ")", + ], + () => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + if ( + property.type instanceof + ArrayType + ) { + recur( + property + .type + .items, + child_level, + ); + this.emitLine( + cJSON.items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + } else { + panic( + "Invalid type", + ); + } + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" || + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + /* Nothing to do */ + } else { + if ( + cJSON.items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + }, + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + } + } + + this.emitLine( + "x", + child_level.toString(), + " = list_get_next(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + this.emitLine( + cJSON.deleteType, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + const child_level = level + 1; + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + "char **keys", + child_level.toString(), + " = NULL;", + ); + this.emitLine( + "size_t count", + child_level.toString(), + " = hashtable_get_keys(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ", &keys", + child_level.toString(), + ");", + ); + this.emitBlock( + [ + "if (NULL != keys", + child_level.toString(), + ")", + ], + () => { + this.emitBlock( + [ + "for (size_t index", + child_level.toString(), + " = 0; index", + child_level.toString(), + " < count", + child_level.toString(), + "; index", + child_level.toString(), + "++)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.cType, + " *x", + child_level.toString(), + " = hashtable_lookup(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ", keys", + child_level.toString(), + "[index", + child_level.toString(), + "]);", + ); + this.emitBlock( + [ + "if (NULL != x", + child_level.toString(), + ")", + ], + () => { + if ( + cJSON + .items + ?.cjsonType === + "cJSON_Array" + ) { + if ( + property.type instanceof + MapType + ) { + recur( + property + .type + .values, + child_level, + ); + this.emitLine( + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + } else { + panic( + "Invalid type", + ); + } + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON + .items + ?.cjsonType === + "cJSON_Invalid" || + cJSON + .items + ?.cjsonType === + "cJSON_NULL" + ) { + /* Nothing to do */ + } else { + if ( + cJSON + .items + ?.isNullable + ) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x", + child_level.toString(), + ")", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + }, + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON + .items + ?.deleteType, + "(x", + child_level.toString(), + ");", + ); + } + } + }, + ); + }, + ); + this.emitLine( + "cJSON_free(keys", + child_level.toString(), + ");", + ); + }, + ); + this.emitLine( + cJSON.deleteType, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Invalid" || + cJSON.cjsonType === "cJSON_NULL" + ) { + /* Nothing to do */ + } else if ( + cJSON.cjsonType === "cJSON_String" || + cJSON.cjsonType === "cJSON_Object" || + cJSON.cjsonType === "cJSON_Union" + ) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.deleteType, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + } else { + if ( + property.isOptional || + cJSON.isNullable + ) { + this.emitBlock( + [ + "if (NULL != x", + level > 0 + ? level.toString() + : "", + "->", + name, + ")", + ], + () => { + this.emitLine( + cJSON.deleteType, + "(x", + level > 0 + ? level.toString() + : "", + "->", + name, + ");", + ); + }, + ); + } + } + }, + ); + } + }; + + recur(classType, 0); + this.emitLine("cJSON_free(x);"); + }); + }, + ); + this.ensureBlankLine(); + } + + /** + * Function called to create a top level header files with types and generators + * @param type: type of the top level element + * @param className: top level class name + * @param includes: Array of includes + */ + protected emitTopLevel( + type: Type, + className: Name, + includes: string[], + ): void { + /* Create file */ + const filename = this.sourcelikeToString(className).concat(".h"); + this.startFile(filename); + + /* Create includes - This create too much includes but this is safer because of specific corner cases */ + includes.forEach((name) => { + this.emitIncludeLine(name); + }); + this.ensureBlankLine(); + + /* Create types */ + this.emitTopLevelTypedef(type, className); + + /* Create prototypes */ + this.emitTopLevelPrototypes(type, className); + + /* Create functions */ + this.emitTopLevelFunctions(type, className); + + /* Close file */ + this.finishFile(); + } + + /** + * Function called to create top level typedef + * @param type: type of the top level element + * @param className: top level class name + */ + protected emitTopLevelTypedef(type: Type, className: Name): void { + this.emitBlock( + ["struct ", className], + () => { + const cJSON = this.quicktypeTypeToCJSON(type, false); + this.emitLine( + cJSON.cType, + cJSON.optionalQualifier !== "" ? " " : "", + cJSON.optionalQualifier, + " value;", + ); + }, + "", + true, + ); + this.ensureBlankLine(); + this.emitTypedefAlias(type, className); + } + + /** + * Function called to create top level prototypes + * @param type: type of the top level element + * @param className: top level class name + */ + protected emitTopLevelPrototypes(_type: Type, className: Name): void { + this.emitLine( + "struct ", + className, + " * cJSON_Parse", + className, + "(", + this.withConst("char"), + " * s);", + ); + this.emitLine( + "struct ", + className, + " * cJSON_Get", + className, + "Value(", + this.withConst("cJSON"), + " * j);", + ); + this.emitLine( + "cJSON * cJSON_Create", + className, + "(", + this.withConst(["struct ", className]), + " * x);", + ); + this.emitLine( + "char * cJSON_Print", + className, + "(", + this.withConst(["struct ", className]), + " * x);", + ); + this.emitLine( + "void cJSON_Delete", + className, + "(struct ", + className, + " * x);", + ); + this.ensureBlankLine(); + } + + /** + * Function called to create top level functions + * @param type: type of the top level element + * @param className: top level class name + */ + protected emitTopLevelFunctions(type: Type, className: Name): void { + /* Create string to className generator function */ + this.emitBlock( + [ + "struct ", + className, + " * cJSON_Parse", + className, + "(", + this.withConst("char"), + " * s)", + ], + () => { + this.emitLine("struct ", className, " * x = NULL;"); + this.emitBlock(["if (NULL != s)"], () => { + this.emitLine("cJSON * j = cJSON_Parse(s);"); + this.emitBlock(["if (NULL != j)"], () => { + this.emitLine("x = cJSON_Get", className, "Value(j);"); + this.emitLine("cJSON_Delete(j);"); + }); + }); + this.emitLine("return x;"); + }, + ); + this.ensureBlankLine(); + + /* Create cJSON to className generator function */ + this.emitBlock( + [ + "struct ", + className, + " * cJSON_Get", + className, + "Value(", + this.withConst("cJSON"), + " * j)", + ], + () => { + this.emitLine("struct ", className, " * x = NULL;"); + this.emitBlock(["if (NULL != j)"], () => { + this.emitBlock( + [ + "if (NULL != (x = cJSON_malloc(sizeof(struct ", + className, + "))))", + ], + () => { + this.emitLine( + "memset(x, 0, sizeof(struct ", + className, + "));", + ); + const cJSON = this.quicktypeTypeToCJSON( + type, + false, + ); + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + this.emitLine( + "x->value = list_create(false, NULL);", + ); + this.emitBlock( + ["if (NULL != x->value)"], + () => { + this.emitLine("cJSON * e = NULL;"); + this.emitBlock( + ["cJSON_ArrayForEach(e, j)"], + () => { + const add = ( + cJSON: TypeCJSON, + ) => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" || + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "list_add_tail(x->value, (", + cJSON.items?.cType, + " *)0xDEADBEAF, sizeof(", + cJSON.items?.cType, + " *));", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "list_add_tail(x->value, strdup(", + cJSON.items + ?.getValue, + "(e)), sizeof(", + cJSON.items?.cType, + " *));", + ); + } else { + this.emitLine( + "list_add_tail(x->value, ", + // @ts-expect-error awaiting refactor + cJSON.items + ?.getValue, + "(e), sizeof(", + cJSON.items?.cType, + " *));", + ); + } + }; + + if (cJSON.items?.isNullable) { + this.emitBlock( + [ + "if (!cJSON_IsNull(e))", + ], + () => { + add(cJSON); + }, + ); + this.emitBlock( + ["else"], + () => { + this.emitLine( + "list_add_tail(x->value, (void *)0xDEADBEEF, sizeof(void *));", + ); + }, + ); + } else { + add(cJSON); + } + }, + ); + }, + ); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + this.emitLine( + "x->value = hashtable_create(", + this.hashtableSize, + ", false);", + ); + this.emitBlock( + ["if (NULL != x->value)"], + () => { + this.emitLine("cJSON * e = NULL;"); + this.emitBlock( + ["cJSON_ArrayForEach(e, j)"], + () => { + const add = ( + cJSON: TypeCJSON, + ) => { + if ( + cJSON.items + ?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_Invalid" || + cJSON.items + ?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "hashtable_add(x->value, e->string, (", + cJSON.items?.cType, + " *)0xDEADBEEF, sizeof(", + cJSON.items?.cType, + " *));", + ); + } else if ( + cJSON.items + ?.cjsonType === + "cJSON_String" + ) { + this.emitLine( + "hashtable_add(x->value, e->string, strdup(", + cJSON.items + ?.getValue, + "(e)), sizeof(", + cJSON.items?.cType, + " *));", + ); + } else { + this.emitLine( + "hashtable_add(x->value, e->string, ", + // @ts-expect-error awaiting refactor + cJSON.items + ?.getValue, + "(e), sizeof(", + cJSON.items?.cType, + " *));", + ); + } + }; + + if (cJSON.items?.isNullable) { + this.emitBlock( + [ + "if (!cJSON_IsNull(e))", + ], + () => { + add(cJSON); + }, + ); + this.emitBlock( + ["else"], + () => { + this.emitLine( + "hashtable_add(x->value, e->string, (void *)0xDEADBEEF, sizeof(void *));", + ); + }, + ); + } else { + add(cJSON); + } + }, + ); + }, + ); + } else if (cJSON.cjsonType === "cJSON_Invalid") { + /* Nothing to do */ + } else if (cJSON.cjsonType === "cJSON_NULL") { + this.emitLine( + "x->value = (", + cJSON.cType, + " *)0xDEADBEEF;", + ); + } else if (cJSON.cjsonType === "cJSON_String") { + this.emitLine( + "x->value = strdup(", + cJSON.getValue, + "(j));", + ); + } else { + this.emitLine( + "x->value = ", + cJSON.getValue, + "(j);", + ); + } + }, + ); + }); + this.emitLine("return x;"); + }, + ); + this.ensureBlankLine(); + + /* Create className to cJSON generator function */ + this.emitBlock( + [ + "cJSON * cJSON_Create", + className, + "(", + this.withConst(["struct ", className]), + " * x)", + ], + () => { + this.emitLine("cJSON * j = NULL;"); + this.emitBlock(["if (NULL != x)"], () => { + const cJSON = this.quicktypeTypeToCJSON(type, false); + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + this.emitBlock(["if (NULL != x->value)"], () => { + this.emitLine("j = ", cJSON.createObject, "();"); + this.emitBlock(["if (NULL != j)"], () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " * x1 = list_get_head(x->value);", + ); + this.emitBlock(["while (NULL != x1)"], () => { + const add = (cJSON: TypeCJSON) => { + if ( + cJSON.items?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items?.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON.items?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + "cJSON_AddItemToArray(j, ", + cJSON.items?.createObject, + "());", + ); + } else if ( + cJSON.items?.cjsonType === + "cJSON_String" || + cJSON.items?.cjsonType === + "cJSON_Object" || + cJSON.items?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + "cJSON_AddItemToArray(j, ", + cJSON.items?.createObject, + "(x1));", + ); + } else { + this.emitLine( + "cJSON_AddItemToArray(j, ", + // @ts-expect-error awaiting refactor + cJSON.items?.createObject, + "(*x1));", + ); + } + }; + + if (cJSON.items?.isNullable) { + this.emitBlock( + ["if ((void *)0xDEADBEEF != x1)"], + () => { + add(cJSON); + }, + ); + this.emitBlock(["else"], () => { + this.emitLine( + "cJSON_AddItemToArray(j, cJSON_CreateNull());", + ); + }); + } else { + add(cJSON); + } + + this.emitLine( + "x1 = list_get_next(x->value);", + ); + }); + }); + }); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + this.emitBlock(["if (NULL != x->value)"], () => { + this.emitLine("j = ", cJSON.createObject, "();"); + this.emitBlock(["if (NULL != j)"], () => { + this.emitLine("char **keys = NULL;"); + this.emitLine( + "size_t count = hashtable_get_keys(x->value, &keys);", + ); + this.emitBlock(["if (NULL != keys)"], () => { + this.emitBlock( + [ + "for (size_t index = 0; index < count; index++)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " *x2 = hashtable_lookup(x->value, keys[index]);", + ); + const add = (cJSON: TypeCJSON) => { + if ( + cJSON.items?.cjsonType === + "cJSON_Array" + ) { + /* Not supported */ + } else if ( + cJSON.items?.cjsonType === + "cJSON_Map" + ) { + /* Not supported */ + } else if ( + cJSON.items?.cjsonType === + "cJSON_Invalid" + ) { + /* Nothing to do */ + } else if ( + cJSON.items?.cjsonType === + "cJSON_NULL" + ) { + this.emitLine( + cJSON.addToObject, + "(j, keys[index], ", + cJSON.items + ?.createObject, + "());", + ); + } else if ( + cJSON.items?.cjsonType === + "cJSON_String" || + cJSON.items?.cjsonType === + "cJSON_Object" || + cJSON.items?.cjsonType === + "cJSON_Union" + ) { + this.emitLine( + cJSON.addToObject, + "(j, keys[index], ", + cJSON.items + ?.createObject, + "(x2));", + ); + } else { + this.emitLine( + cJSON.addToObject, + "(j, keys[index], ", + // @ts-expect-error awaiting refactor + cJSON.items + ?.createObject, + "(*x2));", + ); + } + }; + + if (cJSON.items?.isNullable) { + this.emitBlock( + [ + "if ((void *)0xDEADBEEF != x2)", + ], + () => { + add(cJSON); + }, + ); + this.emitBlock(["else"], () => { + this.emitLine( + cJSON.addToObject, + "(j, keys[index], cJSON_CreateNull());", + ); + }); + } else { + add(cJSON); + } + }, + ); + this.emitLine("cJSON_free(keys);"); + }); + }); + }); + } else if (cJSON.cjsonType === "cJSON_Invalid") { + /* Nothing to do */ + } else if (cJSON.cjsonType === "cJSON_NULL") { + this.emitLine("j = ", cJSON.createObject, "();"); + } else { + this.emitLine( + "j = ", + cJSON.createObject, + "(x->value);", + ); + } + }); + this.emitLine("return j;"); + }, + ); + this.ensureBlankLine(); + + /* Create className to string generator function */ + this.emitBlock( + [ + "char * cJSON_Print", + className, + "(", + this.withConst(["struct ", className]), + " * x)", + ], + () => { + this.emitLine("char * s = NULL;"); + this.emitBlock(["if (NULL != x)"], () => { + this.emitLine( + "cJSON * j = cJSON_Create", + className, + "(x);", + ); + this.emitBlock(["if (NULL != j)"], () => { + this.emitLine("s = cJSON_Print(j);"); + this.emitLine("cJSON_Delete(j);"); + }); + }); + this.emitLine("return s;"); + }, + ); + this.ensureBlankLine(); + + /* Create className delete function */ + this.emitBlock( + ["void cJSON_Delete", className, "(struct ", className, " * x)"], + () => { + this.emitBlock(["if (NULL != x)"], () => { + const cJSON = this.quicktypeTypeToCJSON(type, false); + if ( + cJSON.cjsonType === "cJSON_Array" && + cJSON.items !== undefined + ) { + this.emitBlock(["if (NULL != x->value)"], () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " * x1 = list_get_head(x->value);", + ); + this.emitBlock(["while (NULL != x1)"], () => { + if (cJSON.items?.isNullable) { + this.emitBlock( + ["if ((void *)0xDEADBEEF != x1)"], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.deleteType, + "(x1);", + ); + }, + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.deleteType, + "(x1);", + ); + } + + this.emitLine("x1 = list_get_next(x->value);"); + }); + this.emitLine(cJSON.deleteType, "(x->value);"); + }); + } else if ( + cJSON.cjsonType === "cJSON_Map" && + cJSON.items !== undefined + ) { + this.emitBlock(["if (NULL != x->value)"], () => { + this.emitLine("char **keys = NULL;"); + this.emitLine( + "size_t count = hashtable_get_keys(x->value, &keys);", + ); + this.emitBlock(["if (NULL != keys)"], () => { + this.emitBlock( + [ + "for (size_t index = 0; index < count; index++)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.cType, + " *x2 = hashtable_lookup(x->value, keys[index]);", + ); + this.emitBlock( + ["if (NULL != x2)"], + () => { + if (cJSON.items?.isNullable) { + this.emitBlock( + [ + "if ((", + cJSON.items?.cType, + " *)0xDEADBEEF != x2)", + ], + () => { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items + ?.deleteType, + "(x2);", + ); + }, + ); + } else { + this.emitLine( + // @ts-expect-error awaiting refactor + cJSON.items?.deleteType, + "(x2);", + ); + } + }, + ); + }, + ); + this.emitLine("cJSON_free(keys);"); + }); + this.emitLine(cJSON.deleteType, "(x->value);"); + }); + } else if ( + cJSON.cjsonType === "cJSON_Invalid" || + cJSON.cjsonType === "cJSON_NULL" + ) { + /* Nothing to do */ + } else if ( + cJSON.cjsonType === "cJSON_String" || + cJSON.cjsonType === "cJSON_Object" || + cJSON.cjsonType === "cJSON_Union" + ) { + this.emitLine(cJSON.deleteType, "(x->value);"); + } else { + /* Nothing to do */ + } + + this.emitLine("cJSON_free(x);"); + }); + }, + ); + this.ensureBlankLine(); + } + + /** + * Convert quicktype type to cJSON type + * @param t: quicktype type + * @param isOptional: true if the field is optional + * @param isNullable: true if the field is nullable + * @return cJSON type + */ + protected quicktypeTypeToCJSON( + t: Type, + isOptional: boolean, + isNullable = false, + ): TypeCJSON { + /* Compute cJSON type */ + return matchType( + t, + (_anyType) => { + return { + cType: "void", + optionalQualifier: "*", + cjsonType: "cJSON_Invalid", + isType: "cJSON_IsInvalid", + getValue: "", + addToObject: "", + createObject: "", + deleteType: "", + items: undefined, + isNullable, + }; + }, + (_nullType) => { + return { + cType: "void", + optionalQualifier: "*", + cjsonType: "cJSON_NULL", + isType: "cJSON_IsNull", + getValue: "", + addToObject: "cJSON_AddNullToObject", + createObject: "cJSON_CreateNull", + deleteType: "cJSON_free", + items: undefined, + isNullable, + }; + }, + (_boolType) => { + return { + cType: "bool", + optionalQualifier: isOptional === true ? "*" : "", + cjsonType: "cJSON_Bool", + isType: "cJSON_IsBool", + getValue: "cJSON_IsTrue", + addToObject: "cJSON_AddBoolToObject", + createObject: "cJSON_CreateBool", + deleteType: "cJSON_free", + items: undefined, + isNullable, + }; + }, + (_integerType) => { + return { + cType: this.typeIntegerSize, + optionalQualifier: isOptional === true ? "*" : "", + cjsonType: "cJSON_Number", + isType: "cJSON_IsNumber", + getValue: "cJSON_GetNumberValue", + addToObject: "cJSON_AddNumberToObject", + createObject: "cJSON_CreateNumber", + deleteType: "cJSON_free", + items: undefined, + isNullable, + }; + }, + (_doubleType) => { + return { + cType: "double", + optionalQualifier: isOptional === true ? "*" : "", + cjsonType: "cJSON_Number", + isType: "cJSON_IsNumber", + getValue: "cJSON_GetNumberValue", + addToObject: "cJSON_AddNumberToObject", + createObject: "cJSON_CreateNumber", + deleteType: "cJSON_free", + items: undefined, + isNullable, + }; + }, + (_stringType) => { + return { + cType: "char", + optionalQualifier: "*", + cjsonType: "cJSON_String", + isType: "cJSON_IsString", + getValue: "cJSON_GetStringValue", + addToObject: "cJSON_AddStringToObject", + createObject: "cJSON_CreateString", + deleteType: "cJSON_free", + items: undefined, + isNullable, + }; + }, + (arrayType) => { + const items = this.quicktypeTypeToCJSON(arrayType.items, false); + return { + cType: "list_t", + optionalQualifier: "*", + cjsonType: "cJSON_Array", + isType: "cJSON_IsArray", + getValue: "cJSON_GetArrayItem", + addToObject: "cJSON_AddItemToObject", + createObject: "cJSON_CreateArray", + deleteType: "list_release", + items, + isNullable, + }; + }, + (classType) => { + return { + cType: ["struct ", this.nameForNamedType(classType)], + optionalQualifier: "*", + cjsonType: "cJSON_Object", + isType: "cJSON_IsObject", + getValue: [ + "cJSON_Get", + this.nameForNamedType(classType), + "Value", + ], + addToObject: "cJSON_AddItemToObject", + createObject: [ + "cJSON_Create", + this.nameForNamedType(classType), + ], + deleteType: [ + "cJSON_Delete", + this.nameForNamedType(classType), + ], + items: undefined, + isNullable, + }; + }, + (mapType) => { + const items = this.quicktypeTypeToCJSON(mapType.values, false); + return { + cType: "hashtable_t", + optionalQualifier: "*", + cjsonType: "cJSON_Map", + isType: "cJSON_IsObject", + getValue: "", + addToObject: "cJSON_AddItemToObject", + createObject: "cJSON_CreateObject", + deleteType: "hashtable_release", + items, + isNullable, + }; + }, + (enumType) => { + return { + cType: ["enum ", this.nameForNamedType(enumType)], + optionalQualifier: isOptional === true ? "*" : "", + cjsonType: "cJSON_Enum", + isType: "cJSON_IsString", + getValue: [ + "cJSON_Get", + this.nameForNamedType(enumType), + "Value", + ], + addToObject: "cJSON_AddItemToObject", + createObject: [ + "cJSON_Create", + this.nameForNamedType(enumType), + ], + deleteType: "cJSON_free", + items: undefined, + isNullable, + }; + }, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return this.quicktypeTypeToCJSON(nullable, true, true); + } + + return { + cType: ["struct ", this.nameForNamedType(unionType)], + optionalQualifier: "*", + cjsonType: "cJSON_Union", + isType: "", + getValue: [ + "cJSON_Get", + this.nameForNamedType(unionType), + "Value", + ], + addToObject: "cJSON_AddItemToObject", + createObject: [ + "cJSON_Create", + this.nameForNamedType(unionType), + ], + deleteType: [ + "cJSON_Delete", + this.nameForNamedType(unionType), + ], + items: undefined, + isNullable, + }; + }, + ); + } + + /** + * Function called to create a file + * @param proposedFilename: source filename provided from stdin + */ + protected startFile(proposedFilename: Sourcelike): void { + /* Check if previous file is closed, create a new file */ + assert( + this.currentFilename === undefined, + "Previous file wasn't finished", + ); + if (proposedFilename !== undefined) { + this.currentFilename = this.sourcelikeToString(proposedFilename); + } + + /* Check if file has been created */ + if (this.currentFilename !== undefined) { + /* Write header */ + this.emitDescriptionBlock([ + this.currentFilename, + "This file has been autogenerated using quicktype https://github.com/quicktype/quicktype - DO NOT EDIT", + "This file depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable", + "To parse json data from json string use the following: struct * data = cJSON_Parse();", + "To get json data from cJSON object use the following: struct * data = cJSON_GetValue();", + "To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create();", + "To print json string from json data use the following: char * string = cJSON_Print();", + "To delete json data use the following: cJSON_Delete();", + ]); + this.ensureBlankLine(); + + /* Write include guard */ + this.emitLine( + "#ifndef __", + allUpperWordStyle( + this.currentFilename.replace( + new RegExp(/[^a-zA-Z0-9]+/, "g"), + "_", + ), + ), + "__", + ); + this.emitLine( + "#define __", + allUpperWordStyle( + this.currentFilename.replace( + new RegExp(/[^a-zA-Z0-9]+/, "g"), + "_", + ), + ), + "__", + ); + this.ensureBlankLine(); + + /* Write C++ guard */ + this.emitLine("#ifdef __cplusplus"); + this.emitLine('extern "C" {'); + this.emitLine("#endif"); + this.ensureBlankLine(); + + /* Write includes */ + this.emitIncludeLine("stdint.h", true); + this.emitIncludeLine("stdbool.h", true); + this.emitIncludeLine("stdlib.h", true); + this.emitIncludeLine("string.h", true); + this.emitIncludeLine("cJSON.h", true); + this.emitIncludeLine("hashtable.h", true); + this.emitIncludeLine("list.h", true); + this.ensureBlankLine(); + + /* Additional cJSON types */ + this.emitLine("#ifndef cJSON_Bool"); + this.emitLine("#define cJSON_Bool (cJSON_True | cJSON_False)"); + this.emitLine("#endif"); + this.emitLine("#ifndef cJSON_Map"); + this.emitLine("#define cJSON_Map (1 << 16)"); + this.emitLine("#endif"); + this.emitLine("#ifndef cJSON_Enum"); + this.emitLine("#define cJSON_Enum (1 << 17)"); + this.emitLine("#endif"); + this.ensureBlankLine(); + } + } + + /** + * Function called to close current file + */ + protected finishFile(): void { + /* Check if file has been created */ + if (this.currentFilename !== undefined) { + /* Write C++ guard */ + this.emitLine("#ifdef __cplusplus"); + this.emitLine("}"); + this.emitLine("#endif"); + this.ensureBlankLine(); + + /* Write include guard */ + this.emitLine( + "#endif /* __", + allUpperWordStyle( + this.currentFilename.replace( + new RegExp(/[^a-zA-Z0-9]+/, "g"), + "_", + ), + ), + "__ */", + ); + this.ensureBlankLine(); + + /* Close file */ + super.finishFile(defined(this.currentFilename)); + this.currentFilename = undefined; + } + } + + /** + * Check if type need declaration before use + * @note If returning true, canBeForwardDeclared must be declared + * @return Always returns true + */ + protected get needsTypeDeclarationBeforeUse(): boolean { + return true; + } + + /** + * Check if type can be forward declared + * @return true for classes, false otherwise + */ + protected canBeForwardDeclared(type: Type): boolean { + return type.kind === "class"; + } + + /** + * Add const to wanted Sourcelike + * @return Const Sourcelike + */ + protected withConst(s: Sourcelike): Sourcelike { + return ["const ", s]; + } + + /** + * Emit include line + * @param name: filename to include + * @pram global: true if global include, false otherwise (default) + */ + protected emitIncludeLine(name: Sourcelike, global = false): void { + this.emitLine( + "#include ", + global ? "<" : '"', + name, + global ? ">" : '"', + ); + } + + /** + * Emit description block + * @param lines: description block lines + */ + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); + } + + /** + * Emit code block + * @param line: code block line + * @param f: callback function + * @param withName: name of the block as string + * @param withSemicolon: true to add semicolon at the end of the block, false otherwise + * @param withIndent: true to indent the block (default), false otherwise + */ + protected emitBlock( + line: Sourcelike, + f: () => void, + withName = "", + withSemicolon = false, + withIndent = true, + ): void { + this.emitLine(line, " {"); + this.preventBlankLine(); + if (withIndent) { + this.indent(f); + } else { + f(); + } + + this.preventBlankLine(); + if (withSemicolon) { + if (withName !== "") { + this.emitLine("} ", withName, ";"); + } else { + this.emitLine("};"); + } + } else { + if (withName !== "") { + this.emitLine("} ", withName); + } else { + this.emitLine("}"); + } + } + } + + /** + * Emit includes + * @param type: class, union or enum type + * @param filename: current file name + */ + protected emitIncludes( + type: ClassType | UnionType | EnumType, + filename: string, + ): void { + /* List required includes */ + const includes: IncludeMap = new Map(); + if (type instanceof UnionType) { + this.updateIncludes(false, includes, type); + } else if (type instanceof ClassType) { + this.forEachClassProperty( + type, + "none", + (_name, _jsonName, property) => { + this.updateIncludes(true, includes, property.type); + }, + ); + } + + /* Emit includes */ + if (includes.size !== 0) { + includes.forEach((_rec: IncludeRecord, name: string) => { + name = name.concat(".h"); + if (name !== filename) { + this.emitIncludeLine(name); + } + }); + } + + this.ensureBlankLine(); + } + + /** + * Compute includes + * @param isClassMender: true if class, false otherwise + * @param includes: include map + * @param propertyType: property type + */ + protected updateIncludes( + isClassMember: boolean, + includes: IncludeMap, + propertyType: Type, + ): void { + const propTypes = this.generatedTypes(isClassMember, propertyType); + for (const t of propTypes) { + const typeName = this.sourcelikeToString(t.name); + const propRecord: IncludeRecord = { + kind: undefined, + typeKind: undefined, + }; + if (t.type instanceof ClassType) { + /* We can NOT forward declare direct class members, e.g. a class type is included at level#0 */ + /* HOWEVER if it is not a direct class member, then we can SURELY forward declare it */ + propRecord.typeKind = "class"; + propRecord.kind = + t.level === 0 + ? IncludeKind.Include + : IncludeKind.ForwardDeclare; + if (t.forceInclude) { + propRecord.kind = IncludeKind.Include; + } + } else if (t.type instanceof EnumType) { + propRecord.typeKind = "enum"; + propRecord.kind = IncludeKind.ForwardDeclare; + } else if (t.type instanceof UnionType) { + propRecord.typeKind = "union"; + /* Recurse into the union */ + const [maybeNull] = removeNullFromUnion(t.type, true); + if (maybeNull !== undefined) { + /* Houston this is a variant, include it */ + propRecord.kind = IncludeKind.Include; + } else { + if (t.forceInclude) { + propRecord.kind = IncludeKind.Include; + } else { + propRecord.kind = IncludeKind.ForwardDeclare; + } + } + } + + if (includes.has(typeName)) { + const incKind = includes.get(typeName); + /* If we already include the type as typed include, do not write it over with forward declare */ + if ( + incKind !== undefined && + incKind.kind === IncludeKind.ForwardDeclare + ) { + includes.set(typeName, propRecord); + } + } else { + includes.set(typeName, propRecord); + } + } + } + + /** + * Compute generated types + * @param isClassMender: true if class, false otherwise + * @param type: type + * @return Type record array + */ + protected generatedTypes(isClassMember: boolean, type: Type): TypeRecord[] { + const result: TypeRecord[] = []; + const recur = ( + forceInclude: boolean, + isVariant: boolean, + l: number, + t: Type, + ) => { + if (t instanceof ArrayType) { + recur(forceInclude, isVariant, l + 1, t.items); + } else if (t instanceof ClassType) { + result.push({ + name: this.nameForNamedType(t), + type: t, + level: l, + variant: isVariant, + forceInclude, + }); + } else if (t instanceof MapType) { + recur(forceInclude, isVariant, l + 1, t.values); + } else if (t instanceof EnumType) { + result.push({ + name: this.nameForNamedType(t), + type: t, + level: l, + variant: isVariant, + forceInclude: false, + }); + } else if (t instanceof UnionType) { + /** + * If we have a union as a class member and we see it as a "named union", + * we can safely include it as-is. + * HOWEVER if we define a union on its own, we must recurse into the + * typedefinition and include all subtypes. + */ + if (this.unionNeedsName(t) && isClassMember) { + /** + * This is NOT ENOUGH. + * We have a variant member in a class, e.g. defined with a boost::variant. + * The compiler can only compile the class if IT KNOWS THE SIZES + * OF ALL MEMBERS OF THE VARIANT. + * So it means that you must include ALL SUBTYPES (practically classes only) + * AS WELL + */ + forceInclude = true; + result.push({ + name: this.nameForNamedType(t), + type: t, + level: l, + variant: true, + forceInclude, + }); + /** intentional "fall-through", add all subtypes as well - but forced include */ + } + + const [hasNull, nonNulls] = removeNullFromUnion(t); + isVariant = hasNull !== null; + /** we need to collect all the subtypes of the union */ + for (const tt of nonNulls) { + recur(forceInclude, isVariant, l + 1, tt); + } + } + }; + + recur(false, false, 0, type); + return result; + } +} diff --git a/packages/quicktype-core/src/language/CJSON/constants.ts b/packages/quicktype-core/src/language/CJSON/constants.ts new file mode 100644 index 000000000..6a0024c05 --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/constants.ts @@ -0,0 +1,122 @@ +/* Forbidden names for namespace */ +export const keywords = [ + /* C and C++ keywords */ + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "atomic_cancel", + "atomic_commit", + "atomic_noexcept", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "concept", + "const", + "constexpr", + "const_cast", + "continue", + "co_await", + "co_return", + "co_yield", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "import", + "inline", + "int", + "long", + "module", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "requires", + "restrict", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "synchronized", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "typeof", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + "override", + "final", + "transaction_safe", + "transaction_safe_dynamic", + "NULL", + /* cJSON keywords */ + "Array", + "ArrayReference", + "Bool", + "DoubleArray", + "False", + "FloatArray", + "IntArray", + "Object", + "Null", + "Number", + "Raw", + "String", + "StringArray", + "StringReference", + "True", +] as const; diff --git a/packages/quicktype-core/src/language/CJSON/index.ts b/packages/quicktype-core/src/language/CJSON/index.ts new file mode 100644 index 000000000..1534721aa --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/index.ts @@ -0,0 +1,2 @@ +export { CJSONTargetLanguage, cJSONOptions } from "./language"; +export { CJSONRenderer } from "./CJSONRenderer"; diff --git a/packages/quicktype-core/src/language/CJSON/language.ts b/packages/quicktype-core/src/language/CJSON/language.ts new file mode 100644 index 000000000..80563c040 --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/language.ts @@ -0,0 +1,169 @@ +/** + * CJSON.ts + * This file is used to generate cJSON code with quicktype + * The generated code depends of https://github.com/DaveGamble/cJSON, https://github.com/joelguittet/c-list and https://github.com/joelguittet/c-hashtable + * + * Similarly to C++ generator, it is possible to generate a single header file or multiple header files. + * To generate multiple header files, use the following option: --source-style multi-source + * + * JSON data are represented using structures, and functions in the cJSON style are created to use them. + * To parse json data from json string use the following: struct * data = cJSON_Parse(); + * To get json data from cJSON object use the following: struct * data = cJSON_GetValue(); + * To get cJSON object from json data use the following: cJSON * cjson = cJSON_Create(); + * To print json string from json data use the following: char * string = cJSON_Print(); + * To delete json data use the following: cJSON_Delete(); + * + * TODO list for future enhancements: + * - Management of Class, Union and TopLevel should be mutualized to reduce code size and to permit Union and TopLevel having recursive Array/Map + * - Types check should be added to verify unwanted inputs (for example a Number passed while a String is expected, etc) + * - Constraints should be implemented (verification of Enum values, min/max values for Numbers and min/max length for Strings, regex) + * - Support of pure Any type for example providing a callback from the application to handle these cases dynamically + * See test/languages.ts for the test cases which are not implmented/checked. + */ + +import type { RenderContext } from "../../Renderer"; +import { + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { CJSONRenderer } from "./CJSONRenderer"; + +/* Naming styles */ +const namingStyles = { + "pascal-case": "pascal", + "underscore-case": "underscore", + "camel-case": "camel", + "upper-underscore-case": "upper-underscore", + "pascal-case-upper-acronyms": "pascal-upper-acronyms", + "camel-case-upper-acronyms": "camel-upper-acronyms", +} as const; + +/* cJSON generator options */ +export const cJSONOptions = { + typeSourceStyle: new EnumOption( + "source-style", + "Source code generation type, whether to generate single or multiple source files", + { + "single-source": true, + "multi-source": false, + } as const, + "single-source", + "secondary", + ), + typeIntegerSize: new EnumOption( + "integer-size", + "Integer code generation type (int64_t by default)", + { + int8_t: "int8_t", + int16_t: "int16_t", + int32_t: "int32_t", + int64_t: "int64_t", + } as const, + "int64_t", + "secondary", + ), + hashtableSize: new StringOption( + "hashtable-size", + "Hashtable size, used when maps are created (64 by default)", + "SIZE", + "64", + ), + addTypedefAlias: new EnumOption( + "typedef-alias", + "Add typedef alias to unions, structs, and enums (no typedef by default)", + { + "no-typedef": false, + "add-typedef": true, + } as const, + "no-typedef", + "secondary", + ), + printStyle: new EnumOption( + "print-style", + "Which cJSON print should be used (formatted by default)", + { + "print-formatted": false, + "print-unformatted": true, + } as const, + "print-formatted", + "secondary", + ), + typeNamingStyle: new EnumOption( + "type-style", + "Naming style for types", + namingStyles, + "pascal-case", + ), + memberNamingStyle: new EnumOption( + "member-style", + "Naming style for members", + namingStyles, + "underscore-case", + ), + enumeratorNamingStyle: new EnumOption( + "enumerator-style", + "Naming style for enumerators", + namingStyles, + "upper-underscore-case", + ), +}; + +/* cJSON generator target language */ +export const cJSONLanguageConfig = { + displayName: "C (cJSON)", + names: ["cjson", "cJSON"], + extension: "h", +} as const; + +export class CJSONTargetLanguage extends TargetLanguage< + typeof cJSONLanguageConfig +> { + public constructor() { + super(cJSONLanguageConfig); + } + + /** + * Return cJSON generator options + * @return cJSON generator options array + */ + public getOptions(): typeof cJSONOptions { + return cJSONOptions; + } + + /** + * Indicate if language support union with both number types + * @return true + */ + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + /** + * Indicate if language support optional class properties + * @return true + */ + public get supportsOptionalClassProperties(): boolean { + return true; + } + + /** + * Create renderer + * @param renderContext: render context + * @param untypedOptionValues + * @return cJSON renderer + */ + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): CJSONRenderer { + return new CJSONRenderer( + this, + renderContext, + getOptionValues(cJSONOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/CJSON/utils.ts b/packages/quicktype-core/src/language/CJSON/utils.ts new file mode 100644 index 000000000..4a09e1c56 --- /dev/null +++ b/packages/quicktype-core/src/language/CJSON/utils.ts @@ -0,0 +1,63 @@ +import type { Name } from "../../Naming"; +import type { Sourcelike } from "../../Source"; +import { + isAscii, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, +} from "../../support/Strings"; +import type { Type, TypeKind } from "../../Type"; + +/* Function used to format names */ +export const legalizeName = legalizeCharacters( + (cp) => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp), +); + +/* Used to build forbidden global names */ +export enum GlobalNames { + ClassMemberConstraints = 1, + ClassMemberConstraintException = 2, + ValueTooLowException = 3, + ValueTooHighException = 4, + ValueTooShortException = 5, + ValueTooLongException = 6, + InvalidPatternException = 7, + CheckConstraint = 8, +} + +/* To be able to support circles in multiple files - e.g. class#A using class#B using class#A (obviously not directly) we can forward declare them */ +export enum IncludeKind { + ForwardDeclare = "ForwardDeclare", + Include = "Include", +} + +/* Used to map includes */ +export interface IncludeRecord { + kind: IncludeKind | undefined /* How to include that */; + typeKind: TypeKind | undefined /* What exactly to include */; +} + +/* Used to map includes */ +export interface TypeRecord { + forceInclude: boolean; + level: number; + name: Name; + type: Type; + variant: boolean; +} + +/* Map each and every unique type to a include kind, e.g. how to include the given type */ +export type IncludeMap = Map; + +/* cJSON type */ +export interface TypeCJSON { + addToObject: Sourcelike /* cJSON add to object function */; + cType: Sourcelike /* C type */; + cjsonType: string /* cJSON type */; + createObject: Sourcelike /* cJSON create object function */; + deleteType: Sourcelike /* cJSON delete function */; + getValue: Sourcelike /* cJSON get value function */; + isNullable: boolean /* True if the field is nullable */; + isType: Sourcelike /* cJSON check type function */; + items: TypeCJSON | undefined /* Sub-items, used for arrays and map */; + optionalQualifier: string /* C optional qualifier, empty string if not defined */; +} diff --git a/packages/quicktype-core/src/language/CPlusPlus.ts b/packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts similarity index 60% rename from packages/quicktype-core/src/language/CPlusPlus.ts rename to packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts index 510b69802..4013ebc7c 100644 --- a/packages/quicktype-core/src/language/CPlusPlus.ts +++ b/packages/quicktype-core/src/language/CPlusPlus/CPlusPlusRenderer.ts @@ -1,449 +1,84 @@ import { - setUnion, arrayIntercalate, - toReadonlyArray, - iterableFirst, iterableFind, + iterableFirst, iterableSome, - withDefault + setUnion, + toReadonlyArray, + withDefault, } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { Type, TypeKind, ClassType, ClassProperty, ArrayType, MapType, EnumType, UnionType } from "../Type"; -import { nullableFromUnion, matchType, removeNullFromUnion, isNamedType, directlyReachableTypes } from "../TypeUtils"; -import { NameStyle, Name, Namer, funPrefixNamer, DependencyName } from "../Naming"; -import { Sourcelike, maybeAnnotated } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; import { - legalizeCharacters, - isAscii, - isLetterOrUnderscoreOrDigit, + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { getAccessorName } from "../../attributes/AccessorNames"; +import { enumCaseValues } from "../../attributes/EnumValues"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import type { Declaration } from "../../DeclarationIR"; +import { + DependencyName, + type Name, + type NameStyle, + type Namer, + funPrefixNamer, +} from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { + type NamingStyle, + makeNameStyle, stringEscape, - NamingStyle, - makeNameStyle -} from "../support/Strings"; -import { defined, assertNever, panic, numberEnumValues } from "../support/Support"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { StringOption, EnumOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { assert } from "../support/Support"; -import { Declaration } from "../DeclarationIR"; -import { RenderContext } from "../Renderer"; -import { getAccessorName } from "../attributes/AccessorNames"; -import { enumCaseValues } from "../attributes/EnumValues"; -import { minMaxValueForType, minMaxLengthForType, patternForType, MinMaxConstraint } from "../attributes/Constraints"; - -const pascalValue: [string, NamingStyle] = ["pascal-case", "pascal"]; -const underscoreValue: [string, NamingStyle] = ["underscore-case", "underscore"]; -const camelValue: [string, NamingStyle] = ["camel-case", "camel"]; -const upperUnderscoreValue: [string, NamingStyle] = ["upper-underscore-case", "upper-underscore"]; -const pascalUpperAcronymsValue: [string, NamingStyle] = ["pascal-case-upper-acronyms", "pascal-upper-acronyms"]; -const camelUpperAcronymsValue: [string, NamingStyle] = ["camel-case-upper-acronyms", "camel-upper-acronyms"]; - -export const cPlusPlusOptions = { - typeSourceStyle: new EnumOption( - "source-style", - "Source code generation type, whether to generate single or multiple source files", - [ - ["single-source", true], - ["multi-source", false] - ], - "single-source", - "secondary" - ), - includeLocation: new EnumOption( - "include-location", - "Whether json.hpp is to be located globally or locally", - [ - ["local-include", true], - ["global-include", false] - ], - "local-include", - "secondary" - ), - codeFormat: new EnumOption( - "code-format", - "Generate classes with getters/setters, instead of structs", - [ - ["with-struct", false], - ["with-getter-setter", true] - ], - "with-getter-setter" - ), - wstring: new EnumOption( - "wstring", - "Store strings using Utf-16 std::wstring, rather than Utf-8 std::string", - [ - ["use-string", false], - ["use-wstring", true] - ], - "use-string" - ), - westConst: new EnumOption( - "const-style", - "Put const to the left/west (const T) or right/east (T const)", - [ - ["west-const", true], - ["east-const", false] - ], - "west-const" - ), - justTypes: new BooleanOption("just-types", "Plain types only", false), - namespace: new StringOption("namespace", "Name of the generated namespace(s)", "NAME", "quicktype"), - enumType: new StringOption("enum-type", "Type of enum class", "NAME", "int", "secondary"), - typeNamingStyle: new EnumOption("type-style", "Naming style for types", [ - pascalValue, - underscoreValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - memberNamingStyle: new EnumOption("member-style", "Naming style for members", [ - underscoreValue, - pascalValue, - camelValue, - upperUnderscoreValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - enumeratorNamingStyle: new EnumOption("enumerator-style", "Naming style for enumerators", [ - upperUnderscoreValue, - underscoreValue, - pascalValue, - camelValue, - pascalUpperAcronymsValue, - camelUpperAcronymsValue - ]), - boost: new BooleanOption("boost", "Require a dependency on boost. Without boost, C++17 is required", true), - hideNullOptional: new BooleanOption("hide-null-optional", "Hide null value for optional field", false) -}; - -export class CPlusPlusTargetLanguage extends TargetLanguage { - constructor(displayName = "C++", names: string[] = ["c++", "cpp", "cplusplus"], extension = "cpp") { - super(displayName, names, extension); - } - - protected getOptions(): Option[] { - return [ - cPlusPlusOptions.justTypes, - cPlusPlusOptions.namespace, - cPlusPlusOptions.codeFormat, - cPlusPlusOptions.wstring, - cPlusPlusOptions.westConst, - cPlusPlusOptions.typeSourceStyle, - cPlusPlusOptions.includeLocation, - cPlusPlusOptions.typeNamingStyle, - cPlusPlusOptions.memberNamingStyle, - cPlusPlusOptions.enumeratorNamingStyle, - cPlusPlusOptions.enumType, - cPlusPlusOptions.boost, - cPlusPlusOptions.hideNullOptional - ]; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): CPlusPlusRenderer { - return new CPlusPlusRenderer(this, renderContext, getOptionValues(cPlusPlusOptions, untypedOptionValues)); - } -} - -function constraintsForType(t: Type): - | { - minMax?: MinMaxConstraint; - minMaxLength?: MinMaxConstraint; - pattern?: string; - } - | undefined { - const minMax = minMaxValueForType(t); - const minMaxLength = minMaxLengthForType(t); - const pattern = patternForType(t); - if (minMax === undefined && minMaxLength === undefined && pattern === undefined) return undefined; - return { minMax, minMaxLength, pattern }; -} - -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -const keywords = [ - "alignas", - "alignof", - "and", - "and_eq", - "asm", - "atomic_cancel", - "atomic_commit", - "atomic_noexcept", - "auto", - "bitand", - "bitor", - "bool", - "break", - "case", - "catch", - "char", - "char16_t", - "char32_t", - "class", - "compl", - "concept", - "const", - "constexpr", - "const_cast", - "continue", - "co_await", - "co_return", - "co_yield", - "decltype", - "default", - "delete", - "do", - "double", - "dynamic_cast", - "else", - "enum", - "explicit", - "export", - "extern", - "false", - "float", - "for", - "friend", - "goto", - "if", - "import", - "inline", - "int", - "long", - "module", - "mutable", - "namespace", - "new", - "noexcept", - "not", - "not_eq", - "nullptr", - "operator", - "or", - "or_eq", - "private", - "protected", - "public", - "register", - "reinterpret_cast", - "requires", - "return", - "short", - "signed", - "sizeof", - "static", - "static_assert", - "static_cast", - "struct", - "switch", - "synchronized", - "template", - "this", - "thread_local", - "throw", - "true", - "try", - "typedef", - "typeid", - "typename", - "union", - "unsigned", - "using", - "virtual", - "void", - "volatile", - "wchar_t", - "while", - "xor", - "xor_eq", - "override", - "final", - "transaction_safe", - "transaction_safe_dynamic", - "NULL" -]; - -/// Type to use as an optional if cycle breaking is required -const optionalAsSharedType = "std::shared_ptr"; -/// Factory to use when creating an optional if cycle breaking is required -const optionalFactoryAsSharedType = "std::make_shared"; - -/** - * To be able to support circles in multiple files - - * e.g. class#A using class#B using class#A (obviously not directly, - * but in vector or in variant) we can forward declare them; - */ -export enum IncludeKind { - ForwardDeclare, - Include -} - -export enum GlobalNames { - ClassMemberConstraints, - ClassMemberConstraintException, - ValueTooLowException, - ValueTooHighException, - ValueTooShortException, - ValueTooLongException, - InvalidPatternException, - CheckConstraint -} - -export enum MemberNames { - MinIntValue, - GetMinIntValue, - SetMinIntValue, - MaxIntValue, - GetMaxIntValue, - SetMaxIntValue, - MinDoubleValue, - GetMinDoubleValue, - SetMinDoubleValue, - MaxDoubleValue, - GetMaxDoubleValue, - SetMaxDoubleValue, - MinLength, - GetMinLength, - SetMinLength, - MaxLength, - GetMaxLength, - SetMaxLength, - Pattern, - GetPattern, - SetPattern -} - -type ConstraintMember = { - name: MemberNames; - getter: MemberNames; - setter: MemberNames; - cppType: string; - cppConstType?: string; -}; - -export type IncludeRecord = { - kind: IncludeKind | undefined /** How to include that */; - typeKind: TypeKind | undefined /** What exactly to include */; -}; - -export type TypeRecord = { - name: Name; - type: Type; - level: number; - variant: boolean; - forceInclude: boolean; -}; - -/** - * We map each and every unique type to a include kind, e.g. how - * to include the given type - */ -export type IncludeMap = Map; - -export type TypeContext = { - needsForwardIndirection: boolean; - needsOptionalIndirection: boolean; - inJsonNamespace: boolean; -}; - -interface StringType { - getType(): string; - getConstType(): string; - getSMatch(): string; - getRegex(): string; - createStringLiteral(inner: Sourcelike): Sourcelike; - wrapToString(inner: Sourcelike): Sourcelike; - wrapEncodingChange( - qualifier: Sourcelike[], - fromType: Sourcelike, - toType: Sourcelike, - inner: Sourcelike - ): Sourcelike; - emitHelperFunctions(): void; -} - -function addQualifier(qualifier: Sourcelike, qualified: Sourcelike[]): Sourcelike[] { - if (qualified.length === 0) { - return []; - } - return [qualifier, qualified]; -} - -class WrappingCode { - constructor(private readonly start: Sourcelike[], private readonly end: Sourcelike[]) {} - - wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { - return [addQualifier(qualifier, this.start), inner, this.end]; - } -} - -class BaseString { - public _stringType: string; - public _constStringType: string; - public _smatch: string; - public _regex: string; - public _stringLiteralPrefix: string; - public _toString: WrappingCode; - public _encodingClass: Sourcelike; - public _encodingFunction: Sourcelike; - - constructor( - stringType: string, - constStringType: string, - smatch: string, - regex: string, - stringLiteralPrefix: string, - toString: WrappingCode, - encodingClass: string, - encodingFunction: string - ) { - this._stringType = stringType; - this._constStringType = constStringType; - this._smatch = smatch; - this._regex = regex; - this._stringLiteralPrefix = stringLiteralPrefix; - this._toString = toString; - this._encodingClass = encodingClass; - this._encodingFunction = encodingFunction; - } - - public getType(): string { - return this._stringType; - } - - public getConstType(): string { - return this._constStringType; - } - - public getSMatch(): string { - return this._smatch; - } - - public getRegex(): string { - return this._regex; - } - - public createStringLiteral(inner: Sourcelike): Sourcelike { - return [this._stringLiteralPrefix, '"', inner, '"']; - } - - public wrapToString(inner: Sourcelike): Sourcelike { - return this._toString.wrap([], inner); - } -} +} from "../../support/Strings"; +import { + assert, + assertNever, + defined, + numberEnumValues, + panic, +} from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + MapType, + type Type, + UnionType, +} from "../../Type"; +import { + directlyReachableTypes, + isNamedType, + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { cPlusPlusOptions } from "./language"; +import { + BaseString, + type ConstraintMember, + GlobalNames, + IncludeKind, + type IncludeMap, + type IncludeRecord, + MemberNames, + type StringType, + type TypeContext, + type TypeRecord, + WrappingCode, + addQualifier, + constraintsForType, + legalizeName, + optionalAsSharedType, + optionalFactoryAsSharedType, +} from "./utils"; export class CPlusPlusRenderer extends ConvenienceRenderer { /** @@ -452,31 +87,51 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { private readonly _enumType: string; private readonly _generatedFiles: Set; + private _currentFilename: string | undefined; + private _allTypeNames: Set; - private readonly _gettersAndSettersForPropertyName = new Map(); - private readonly _namespaceNames: ReadonlyArray; + + private readonly _gettersAndSettersForPropertyName = new Map< + Name, + [Name, Name, Name] + >(); + + private readonly _namespaceNames: readonly string[]; + private readonly _memberNameStyle: NameStyle; + private readonly _namedTypeNameStyle: NameStyle; + private readonly _generatedGlobalNames: Map; + private readonly _generatedMemberNames: Map; + private readonly _forbiddenGlobalNames: string[]; + private readonly _memberNamingFunction: Namer; + private readonly _stringType: StringType; + /// The type to use as an optional (std::optional or std::shared) private readonly _optionalType: string; + private readonly _optionalFactory: string; + private readonly _nulloptType: string; + private readonly _variantType: string; + private readonly _variantIndexMethodName: string; protected readonly typeNamingStyle: NamingStyle; + protected readonly enumeratorNamingStyle: NamingStyle; - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); @@ -484,11 +139,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._namespaceNames = _options.namespace.split("::"); this.typeNamingStyle = _options.typeNamingStyle; - this._namedTypeNameStyle = makeNameStyle(this.typeNamingStyle, legalizeName); + this._namedTypeNameStyle = makeNameStyle( + this.typeNamingStyle, + legalizeName, + ); this.enumeratorNamingStyle = _options.enumeratorNamingStyle; - this._memberNameStyle = makeNameStyle(_options.memberNamingStyle, legalizeName); - this._memberNamingFunction = funPrefixNamer("members", this._memberNameStyle); + this._memberNameStyle = makeNameStyle( + _options.memberNamingStyle, + legalizeName, + ); + this._memberNamingFunction = funPrefixNamer( + "members", + this._memberNameStyle, + ); this._gettersAndSettersForPropertyName = new Map(); this._allTypeNames = new Set(); @@ -521,14 +185,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } // union typeguard - isUnion(t: Type | UnionType): t is UnionType { + private isUnion(t: Type | UnionType): t is UnionType { return t.kind === "union"; } // Returns true if the type can be stored in // a stack based optional type. This requires // that the type does not require forward declaration. - isOptionalAsValuePossible(t: Type): boolean { + private isOptionalAsValuePossible(t: Type): boolean { if (this.isForwardDeclaredType(t)) return false; if (this.isUnion(t)) { @@ -576,7 +240,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { // }; // // checking to see if the collapse of the variant has - // occured and then doing the isCycleBreakerType check + // occurred and then doing the isCycleBreakerType check // on the single type the variant would contain seems // to solve the problem. But does this point to a problem // with the core library or with the CPlusPlus package @@ -586,47 +250,54 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return !this.isCycleBreakerType(tt); } } + return !this.isCycleBreakerType(t); } - isImplicitCycleBreaker(t: Type): boolean { + public isImplicitCycleBreaker(t: Type): boolean { const kind = t.kind; return kind === "array" || kind === "map"; } // Is likely to return std::optional or boost::optional - optionalTypeStack(): string { + private optionalTypeStack(): string { return this._optionalType; } // Is likely to return std::make_optional or boost::optional - optionalFactoryStack(): string { + private optionalFactoryStack(): string { return this._optionalFactory; } // Is likely to return std::shared_ptr - optionalTypeHeap(): string { + private optionalTypeHeap(): string { return optionalAsSharedType; } // Is likely to return std::make_shared - optionalFactoryHeap(): string { + private optionalFactoryHeap(): string { return optionalFactoryAsSharedType; } // Returns the optional type most suitable for the given type. // Classes that don't require forward declarations can be stored // in std::optional ( or boost::optional ) - optionalType(t: Type): string { - if (this.isOptionalAsValuePossible(t)) return this.optionalTypeStack(); - else return this.optionalTypeHeap(); + private optionalType(t: Type): string { + if (this.isOptionalAsValuePossible(t)) { + return this.optionalTypeStack(); + } + + return this.optionalTypeHeap(); } // Returns a label that can be used to distinguish between // heap and stack based optional handling methods - optionalTypeLabel(t: Type): string { - if (this.isOptionalAsValuePossible(t)) return "stack"; - else return "heap"; + private optionalTypeLabel(t: Type): string { + if (this.isOptionalAsValuePossible(t)) { + return "stack"; + } + + return "heap"; } protected getConstraintMembers(): ConstraintMember[] { @@ -635,45 +306,45 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { name: MemberNames.MinIntValue, getter: MemberNames.GetMinIntValue, setter: MemberNames.SetMinIntValue, - cppType: "int64_t" + cppType: "int64_t", }, { name: MemberNames.MaxIntValue, getter: MemberNames.GetMaxIntValue, setter: MemberNames.SetMaxIntValue, - cppType: "int64_t" + cppType: "int64_t", }, { name: MemberNames.MinDoubleValue, getter: MemberNames.GetMinDoubleValue, setter: MemberNames.SetMinDoubleValue, - cppType: "double" + cppType: "double", }, { name: MemberNames.MaxDoubleValue, getter: MemberNames.GetMaxDoubleValue, setter: MemberNames.SetMaxDoubleValue, - cppType: "double" + cppType: "double", }, { name: MemberNames.MinLength, getter: MemberNames.GetMinLength, setter: MemberNames.SetMinLength, - cppType: "size_t" + cppType: "size_t", }, { name: MemberNames.MaxLength, getter: MemberNames.GetMaxLength, setter: MemberNames.SetMaxLength, - cppType: "size_t" + cppType: "size_t", }, { name: MemberNames.Pattern, getter: MemberNames.GetPattern, setter: MemberNames.SetPattern, cppType: this._stringType.getType(), - cppConstType: this._stringType.getConstType() - } + cppConstType: this._stringType.getConstType(), + }, ]; } @@ -692,13 +363,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } protected addMemberName(type: MemberNames): void { - this._generatedMemberNames.set(type, this._memberNameStyle(MemberNames[type])); + this._generatedMemberNames.set( + type, + this._memberNameStyle(MemberNames[type]), + ); } protected setupGlobalNames(): void { for (const v of numberEnumValues(GlobalNames)) { this.addGlobalName(v); } + for (const v of numberEnumValues(MemberNames)) { this.addMemberName(v); } @@ -708,11 +383,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return [...keywords, ...this._forbiddenGlobalNames]; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -729,7 +410,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enumerators", makeNameStyle(this.enumeratorNamingStyle, legalizeName)); + return funPrefixNamer( + "enumerators", + makeNameStyle(this.enumeratorNamingStyle, legalizeName), + ); } protected makeNamesForPropertyGetterAndSetter( @@ -737,15 +421,23 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { _className: Name, _p: ClassProperty, _jsonName: string, - name: Name + name: Name, ): [Name, Name, Name] { - const getterName = new DependencyName(this._memberNamingFunction, name.order, lookup => `get_${lookup(name)}`); + const getterName = new DependencyName( + this._memberNamingFunction, + name.order, + (lookup) => `get_${lookup(name)}`, + ); const mutableGetterName = new DependencyName( this._memberNamingFunction, name.order, - lookup => `getMutable_${lookup(name)}` + (lookup) => `getMutable_${lookup(name)}`, + ); + const setterName = new DependencyName( + this._memberNamingFunction, + name.order, + (lookup) => `set_${lookup(name)}`, ); - const setterName = new DependencyName(this._memberNamingFunction, name.order, lookup => `set_${lookup(name)}`); return [getterName, mutableGetterName, setterName]; } @@ -754,9 +446,15 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { className: Name, p: ClassProperty, jsonName: string, - name: Name + name: Name, ): Name[] { - const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); + const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter( + c, + className, + p, + jsonName, + name, + ); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } @@ -764,51 +462,80 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected withConst(s: Sourcelike): Sourcelike { if (this._options.westConst) { return ["const ", s]; - } else { - return [s, " const"]; } + + return [s, " const"]; } protected emitInclude(global: boolean, name: Sourcelike): void { - this.emitLine("#include ", global ? "<" : '"', name, global ? ">" : '"'); + this.emitLine( + "#include ", + global ? "<" : '"', + name, + global ? ">" : '"', + ); } protected startFile(basename: Sourcelike, includeHelper = true): void { - assert(this._currentFilename === undefined, "Previous file wasn't finished"); + assert( + this._currentFilename === undefined, + "Previous file wasn't finished", + ); if (basename !== undefined) { this._currentFilename = this.sourcelikeToString(basename); } if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); + this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { - this.emitCommentLines([" To parse this JSON data, first install", ""]); + this.emitCommentLines([ + " To parse this JSON data, first install", + "", + ]); if (this._options.boost) { this.emitCommentLines([" Boost http://www.boost.org"]); } + this.emitCommentLines([ " json.hpp https://github.com/nlohmann/json", "", " Then include this file, and then do", - "" + "", ]); if (this._options.typeSourceStyle) { this.forEachTopLevel("none", (_, topLevelName) => { - this.emitLine("// ", topLevelName, " data = nlohmann::json::parse(jsonString);"); + this.emitLine( + "// ", + topLevelName, + " data = nlohmann::json::parse(jsonString);", + ); }); } else { - this.emitLine("// ", basename, " data = nlohmann::json::parse(jsonString);"); + this.emitLine( + "// ", + basename, + " data = nlohmann::json::parse(jsonString);", + ); } + if (this._options.wstring) { this.emitLine("//"); - this.emitLine("// You can get std::wstring data back out using"); + this.emitLine( + "// You can get std::wstring data back out using", + ); this.emitLine("//"); this.forEachTopLevel("none", (_, topLevelName) => { - this.emitLine("// std::wcout << ", "wdump((nlohmann::json) ", topLevelName, ");"); + this.emitLine( + "// std::wcout << ", + "wdump((nlohmann::json) ", + topLevelName, + ");", + ); }); } } + this.ensureBlankLine(); this.emitLine("#pragma once"); @@ -821,6 +548,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitInclude(true, "optional"); } } + if (this.haveNamedUnions) { if (this._options.boost) { this.emitInclude(true, "boost/variant.hpp"); @@ -828,6 +556,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitInclude(true, "variant"); } } + if (!this._options.justTypes) { if (!this._options.includeLocation) { this.emitInclude(true, "nlohmann/json.hpp"); @@ -839,6 +568,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitInclude(false, "helper.hpp"); } } + this.ensureBlankLine(); } @@ -857,10 +587,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); } - protected emitBlock(line: Sourcelike, withSemicolon: boolean, f: () => void, withIndent = true): void { + protected emitBlock( + line: Sourcelike, + withSemicolon: boolean, + f: () => void, + withIndent = true, + ): void { this.emitLine(line, " {"); this.preventBlankLine(); if (withIndent) { @@ -868,6 +607,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } else { f(); } + this.preventBlankLine(); if (withSemicolon) { this.emitLine("};"); @@ -876,7 +616,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitNamespaces(namespaceNames: Iterable, f: () => void): void { + protected emitNamespaces( + namespaceNames: Iterable, + f: () => void, + ): void { const namesArray = toReadonlyArray(namespaceNames); const first = namesArray[0]; if (first === undefined) { @@ -886,7 +629,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ["namespace ", first], false, () => this.emitNamespaces(namesArray.slice(1), f), - namesArray.length === 1 + namesArray.length === 1, ); } } @@ -895,62 +638,81 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { nonNulls: ReadonlySet, ctx: TypeContext, withIssues: boolean, - forceNarrowString: boolean + forceNarrowString: boolean, ): Sourcelike { if (nonNulls.size === 1) { - return this.cppType(defined(iterableFirst(nonNulls)), ctx, withIssues, forceNarrowString, false); + return this.cppType( + defined(iterableFirst(nonNulls)), + ctx, + withIssues, + forceNarrowString, + false, + ); } + const typeList: Sourcelike = []; for (const t of nonNulls) { if (typeList.length !== 0) { typeList.push(", "); } + typeList.push( this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: false, - inJsonNamespace: ctx.inJsonNamespace + inJsonNamespace: ctx.inJsonNamespace, }, withIssues, false, - false - ) + false, + ), ); } + return [this._variantType, "<", typeList, ">"]; } protected variantType(u: UnionType, inJsonNamespace: boolean): Sourcelike { const [maybeNull, nonNulls] = removeNullFromUnion(u, true); - assert(nonNulls.size >= 2, "Variant not needed for less than two types."); + assert( + nonNulls.size >= 2, + "Variant not needed for less than two types.", + ); const indirection = maybeNull !== null; const variant = this.cppTypeInOptional( nonNulls, { needsForwardIndirection: !indirection, needsOptionalIndirection: !indirection, - inJsonNamespace + inJsonNamespace, }, true, - false + false, ); if (!indirection) { return variant; } + return [this.optionalType(u), "<", variant, ">"]; } protected ourQualifier(inJsonNamespace: boolean): Sourcelike { - return inJsonNamespace ? [arrayIntercalate("::", this._namespaceNames), "::"] : []; + return inJsonNamespace + ? [arrayIntercalate("::", this._namespaceNames), "::"] + : []; } protected jsonQualifier(inJsonNamespace: boolean): Sourcelike { return inJsonNamespace ? [] : "nlohmann::"; } - protected variantIndirection(type: Type, needIndirection: boolean, typeSrc: Sourcelike): Sourcelike { + protected variantIndirection( + type: Type, + needIndirection: boolean, + typeSrc: Sourcelike, + ): Sourcelike { if (!needIndirection) return typeSrc; return [this.optionalType(type), "<", typeSrc, ">"]; } @@ -960,7 +722,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ctx: TypeContext, withIssues: boolean, forceNarrowString: boolean, - isOptional: boolean + isOptional: boolean, ): Sourcelike { const inJsonNamespace = ctx.inJsonNamespace; if (isOptional && t instanceof UnionType) { @@ -972,58 +734,65 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } } + const typeSource = matchType( t, - _anyType => { + (_anyType) => { isOptional = false; return maybeAnnotated(withIssues, anyTypeIssueAnnotation, [ this.jsonQualifier(inJsonNamespace), - "json" + "json", ]); }, - _nullType => { + (_nullType) => { isOptional = false; return maybeAnnotated(withIssues, nullTypeIssueAnnotation, [ this.jsonQualifier(inJsonNamespace), - "json" + "json", ]); }, - _boolType => "bool", - _integerType => "int64_t", - _doubleType => "double", - _stringType => { + (_boolType) => "bool", + (_integerType) => "int64_t", + (_doubleType) => "double", + (_stringType) => { if (forceNarrowString) { return "std::string"; - } else { - return this._stringType.getType(); } + + return this._stringType.getType(); }, - arrayType => [ + (arrayType) => [ "std::vector<", this.cppType( arrayType.items, { needsForwardIndirection: false, needsOptionalIndirection: true, - inJsonNamespace + inJsonNamespace, }, withIssues, forceNarrowString, - false + false, ), - ">" + ">", ], - classType => + (classType) => this.variantIndirection( classType, - ctx.needsForwardIndirection && this.isForwardDeclaredType(classType) && !isOptional, - [this.ourQualifier(inJsonNamespace), this.nameForNamedType(classType)] + ctx.needsForwardIndirection && + this.isForwardDeclaredType(classType) && + !isOptional, + [ + this.ourQualifier(inJsonNamespace), + this.nameForNamedType(classType), + ], ), - mapType => { + (mapType) => { let keyType = this._stringType.getType(); if (forceNarrowString) { keyType = "std::string"; } + return [ "std::map<", keyType, @@ -1033,17 +802,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: true, - inJsonNamespace + inJsonNamespace, }, withIssues, forceNarrowString, - false + false, ), - ">" + ">", ]; }, - enumType => [this.ourQualifier(inJsonNamespace), this.nameForNamedType(enumType)], - unionType => { + (enumType) => [ + this.ourQualifier(inJsonNamespace), + this.nameForNamedType(enumType), + ], + (unionType) => { const nullable = nullableFromUnion(unionType); if (nullable !== null) { isOptional = true; @@ -1052,16 +824,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace + inJsonNamespace, }, withIssues, forceNarrowString, - false + false, ); - } else { - return [this.ourQualifier(inJsonNamespace), this.nameForNamedType(unionType)]; } - } + + return [ + this.ourQualifier(inJsonNamespace), + this.nameForNamedType(unionType), + ]; + }, ); if (!isOptional) return typeSource; return [this.optionalType(t), "<", typeSource, ">"]; @@ -1071,28 +846,36 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { * similar to cppType, it practically gathers all the generated types within * 't'. It also records, whether a given sub-type is part of a variant or not. */ - protected generatedTypes(isClassMember: boolean, theType: Type): TypeRecord[] { + protected generatedTypes( + isClassMember: boolean, + theType: Type, + ): TypeRecord[] { const result: TypeRecord[] = []; - const recur = (forceInclude: boolean, isVariant: boolean, l: number, t: Type) => { + const recur = ( + forceInclude: boolean, + isVariant: boolean, + l: number, + t: Type, + ): void => { if (t instanceof ArrayType) { - recur(forceInclude, isVariant, l + 1, t.items); + recur(true, isVariant, l + 1, t.items); } else if (t instanceof ClassType) { result.push({ name: this.nameForNamedType(t), type: t, level: l, variant: isVariant, - forceInclude + forceInclude, }); } else if (t instanceof MapType) { - recur(forceInclude, isVariant, l + 1, t.values); + recur(true, isVariant, l + 1, t.values); } else if (t instanceof EnumType) { result.push({ name: this.nameForNamedType(t), type: t, level: l, variant: isVariant, - forceInclude: false + forceInclude: false, }); } else if (t instanceof UnionType) { /** @@ -1116,7 +899,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { type: t, level: l, variant: true, - forceInclude + forceInclude, }); /** intentional "fall-through", add all subtypes as well - but forced include */ } @@ -1129,6 +912,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } }; + recur(false, false, 0, theType); return result; } @@ -1141,7 +925,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine(cppType, " ", name, ";"); } - protected emitClassMembers(c: ClassType, constraints: Map | undefined): void { + protected emitClassMembers( + c: ClassType, + constraints: Map | undefined, + ): void { if (this._options.codeFormat) { this.emitLine("private:"); @@ -1152,17 +939,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ), - name + name, ); if (constraints?.has(jsonName)) { /** FIXME!!! NameStyle will/can collide with other Names */ - const cnst = this.lookupGlobalName(GlobalNames.ClassMemberConstraints); + const cnst = this.lookupGlobalName( + GlobalNames.ClassMemberConstraints, + ); this.emitMember(cnst, this.constraintMember(jsonName)); } }); @@ -1180,28 +969,28 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ), - name + name, ); } else { const [getterName, mutableGetterName, setterName] = defined( - this._gettersAndSettersForPropertyName.get(name) + this._gettersAndSettersForPropertyName.get(name), ); const rendered = this.cppType( property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ); /** @@ -1209,12 +998,24 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { * One might as why the "this->xxx = value". Simple if we have * a member called 'value' value = value will screw up the compiler */ - const checkConst = this.lookupGlobalName(GlobalNames.CheckConstraint); + const checkConst = this.lookupGlobalName( + GlobalNames.CheckConstraint, + ); if ( - (property.type instanceof UnionType && property.type.findMember("null") !== undefined) || - (property.isOptional && property.type.kind !== "null" && property.type.kind !== "any") + (property.type instanceof UnionType && + property.type.findMember("null") !== undefined) || + (property.isOptional && + property.type.kind !== "null" && + property.type.kind !== "any") ) { - this.emitLine(rendered, " ", getterName, "() const { return ", name, "; }"); + this.emitLine( + rendered, + " ", + getterName, + "() const { return ", + name, + "; }", + ); if (constraints?.has(jsonName)) { this.emitLine( "void ", @@ -1229,14 +1030,36 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.constraintMember(jsonName), ", *value); this->", name, - " = value; }" + " = value; }", ); } else { - this.emitLine("void ", setterName, "(", rendered, " value) { this->", name, " = value; }"); + this.emitLine( + "void ", + setterName, + "(", + rendered, + " value) { this->", + name, + " = value; }", + ); } } else { - this.emitLine(this.withConst(rendered), " & ", getterName, "() const { return ", name, "; }"); - this.emitLine(rendered, " & ", mutableGetterName, "() { return ", name, "; }"); + this.emitLine( + this.withConst(rendered), + " & ", + getterName, + "() const { return ", + name, + "; }", + ); + this.emitLine( + rendered, + " & ", + mutableGetterName, + "() { return ", + name, + "; }", + ); if (constraints?.has(jsonName)) { this.emitLine( "void ", @@ -1251,7 +1074,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.constraintMember(jsonName), ", value); this->", name, - " = value; }" + " = value; }", ); } else { this.emitLine( @@ -1261,45 +1084,56 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(rendered), " & value) { this->", name, - " = value; }" + " = value; }", ); } } + this.ensureBlankLine(); } }); } - protected generateClassConstraints(c: ClassType): Map | undefined { + protected generateClassConstraints( + c: ClassType, + ): Map | undefined { const res: Map = new Map(); this.forEachClassProperty(c, "none", (_name, jsonName, property) => { const constraints = constraintsForType(property.type); if (constraints === undefined) return; const { minMax, minMaxLength, pattern } = constraints; - // TODO is there a better way to check if property.type is an interger or a number? + // TODO is there a better way to check if property.type is an integer or a number? const cppType = this.cppType( property.type, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - property.isOptional + property.isOptional, ); res.set(jsonName, [ this.constraintMember(jsonName), "(", - minMax?.[0] && cppType === "int64_t" ? String(minMax[0]) : this._nulloptType, + minMax?.[0] && cppType === "int64_t" + ? String(minMax[0]) + : this._nulloptType, ", ", - minMax?.[1] && cppType === "int64_t" ? String(minMax[1]) : this._nulloptType, + minMax?.[1] && cppType === "int64_t" + ? String(minMax[1]) + : this._nulloptType, ", ", - minMax?.[0] && cppType === "double" ? String(minMax[0]) : this._nulloptType, + minMax?.[0] && cppType === "double" + ? String(minMax[0]) + : this._nulloptType, ", ", - minMax?.[1] && cppType === "double" ? String(minMax[1]) : this._nulloptType, + minMax?.[1] && cppType === "double" + ? String(minMax[1]) + : this._nulloptType, ", ", minMaxLength?.[0] ? String(minMaxLength[0]) : this._nulloptType, ", ", @@ -1310,10 +1144,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { : [ this._stringType.getType(), "(", - this._stringType.createStringLiteral([stringEscape(pattern)]), - ")" + this._stringType.createStringLiteral([ + stringEscape(pattern), + ]), + ")", ], - ")" + ")", ]); }); @@ -1322,34 +1158,40 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected emitClass(c: ClassType, className: Name): void { this.emitDescription(this.descriptionForType(c)); - this.emitBlock([this._options.codeFormat ? "class " : "struct ", className], true, () => { - const constraints = this.generateClassConstraints(c); - if (this._options.codeFormat) { - this.emitLine("public:"); - if (constraints === undefined) { - this.emitLine(className, "() = default;"); - } else { - this.emitLine(className, "() :"); - let numEmits = 0; - constraints.forEach((initializer: Sourcelike, _propName: string) => { - numEmits++; - this.indent(() => { - if (numEmits === constraints.size) { - this.emitLine(initializer); - } else { - this.emitLine(initializer, ","); - } - }); - }); - this.emitLine("{}"); - } + this.emitBlock( + [this._options.codeFormat ? "class " : "struct ", className], + true, + () => { + const constraints = this.generateClassConstraints(c); + if (this._options.codeFormat) { + this.emitLine("public:"); + if (constraints === undefined) { + this.emitLine(className, "() = default;"); + } else { + this.emitLine(className, "() :"); + let numEmits = 0; + constraints.forEach( + (initializer: Sourcelike, _propName: string) => { + numEmits++; + this.indent(() => { + if (numEmits === constraints.size) { + this.emitLine(initializer); + } else { + this.emitLine(initializer, ","); + } + }); + }, + ); + this.emitLine("{}"); + } - this.emitLine("virtual ~", className, "() = default;"); - this.ensureBlankLine(); - } + this.emitLine("virtual ~", className, "() = default;"); + this.ensureBlankLine(); + } - this.emitClassMembers(c, constraints); - }); + this.emitClassMembers(c, constraints); + }, + ); } protected emitTopLevelHeaders(t: Type, className: Name): void { @@ -1357,26 +1199,45 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { if (t instanceof MapType && this._stringType !== this.NarrowString) { const ourQualifier = this.ourQualifier(true); - this.emitBlock(["struct adl_serializer<", ourQualifier, className, ">"], true, () => { - this.emitLine("template <>"); - this.emitLine( - "static void from_json(", - this.withConst("json"), - " & j, ", - ourQualifier, - className, - " & x);" - ); - this.emitLine("static void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);"); - }); + this.emitBlock( + ["struct adl_serializer<", ourQualifier, className, ">"], + true, + () => { + this.emitLine("template <>"); + this.emitLine( + "static void from_json(", + this.withConst("json"), + " & j, ", + ourQualifier, + className, + " & x);", + ); + this.emitLine( + "static void to_json(json & j, ", + this.withConst([ourQualifier, className]), + " & x);", + ); + }, + ); } } protected emitClassHeaders(className: Name): void { const ourQualifier = this.ourQualifier(false); - this.emitLine("void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, " & x);"); - this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x);"); + this.emitLine( + "void from_json(", + this.withConst("json"), + " & j, ", + ourQualifier, + className, + " & x);", + ); + this.emitLine( + "void to_json(json & j, ", + this.withConst([ourQualifier, className]), + " & x);", + ); } protected emitTopLevelFunction(t: Type, className: Name): void { @@ -1396,7 +1257,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " & j, ", ourQualifier, className, - "& x)" + "& x)", ], false, () => { @@ -1405,34 +1266,35 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); this.emitLine([ "x = ", - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ - "j.get<", + this._stringType.wrapEncodingChange( + [ourQualifier], cppType, - ">()" - ]), - ";" + toType, + ["j.get<", cppType, ">()"], + ), + ";", ]); - } + }, ); this.emitBlock( @@ -1442,7 +1304,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { className, ">::to_json(json & j, ", this.withConst([ourQualifier, className]), - " & x)" + " & x)", ], false, () => { @@ -1451,30 +1313,35 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); toType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); this.emitLine([ "j = ", - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, "x"), - ";" + this._stringType.wrapEncodingChange( + [ourQualifier], + cppType, + toType, + "x", + ), + ";", ]); - } + }, ); } } @@ -1485,16 +1352,28 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { let toType: Sourcelike; this.emitBlock( - ["inline void from_json(", this.withConst("json"), " & j, ", ourQualifier, className, "& x)"], + [ + "inline void from_json(", + this.withConst("json"), + " & j, ", + ourQualifier, + className, + "& x)", + ], false, () => { this.forEachClassProperty(c, "none", (name, json, p) => { - const [, , setterName] = defined(this._gettersAndSettersForPropertyName.get(name)); + const [, , setterName] = defined( + this._gettersAndSettersForPropertyName.get(name), + ); const propType = p.type; let assignment: WrappingCode; if (this._options.codeFormat) { - assignment = new WrappingCode(["x.", setterName, "("], [")"]); + assignment = new WrappingCode( + ["x.", setterName, "("], + [")"], + ); } else { assignment = new WrappingCode(["x.", name, " = "], []); } @@ -1510,25 +1389,37 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(json)])] + [ + this._stringType.createStringLiteral( + [stringEscape(json)], + ), + ], ), - ")" - ] + ")", + ], ), - ";" + ";", ); return; } + if (p.isOptional || propType instanceof UnionType) { - const [nullOrOptional, typeSet] = (function (): [boolean, ReadonlySet] { + const [nullOrOptional, typeSet] = ((): [ + boolean, + ReadonlySet, + ] => { if (propType instanceof UnionType) { - const [maybeNull, nonNulls] = removeNullFromUnion(propType, true); - return [maybeNull !== null || p.isOptional, nonNulls]; - } else { - const set = new Set(); - set.add(propType); - return [true, set]; + const [maybeNull, nonNulls] = + removeNullFromUnion(propType, true); + return [ + maybeNull !== null || p.isOptional, + nonNulls, + ]; } + + const set = new Set(); + set.add(propType); + return [true, set]; })(); if (nullOrOptional) { cppType = this.cppTypeInOptional( @@ -1536,20 +1427,20 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false + inJsonNamespace: false, }, false, - true + true, ); toType = this.cppTypeInOptional( typeSet, { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: false + inJsonNamespace: false, }, false, - false + false, ); this.emitLine( assignment.wrap( @@ -1557,8 +1448,18 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ this._stringType.wrapEncodingChange( [ourQualifier], - [this.optionalType(propType), "<", cppType, ">"], - [this.optionalType(propType), "<", toType, ">"], + [ + this.optionalType(propType), + "<", + cppType, + ">", + ], + [ + this.optionalType(propType), + "<", + toType, + ">", + ], [ ourQualifier, `get_${this.optionalTypeLabel(propType)}_optional<`, @@ -1568,65 +1469,85 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(json)])] + [ + this._stringType.createStringLiteral( + [ + stringEscape( + json, + ), + ], + ), + ], ), - ")" - ] - ) - ] + ")", + ], + ), + ], ), - ";" + ";", ); return; } } + cppType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, true, - p.isOptional + p.isOptional, ); toType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, false, - p.isOptional + p.isOptional, ); this.emitLine( assignment.wrap( [], - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ - "j.at(", - this._stringType.wrapEncodingChange( - [ourQualifier], - this._stringType.getType(), - this.NarrowString.getType(), - this._stringType.createStringLiteral([stringEscape(json)]) - ), - ").get<", + this._stringType.wrapEncodingChange( + [ourQualifier], cppType, - ">()" - ]) - ), - ";" + toType, + [ + "j.at(", + this._stringType.wrapEncodingChange( + [ourQualifier], + this._stringType.getType(), + this.NarrowString.getType(), + this._stringType.createStringLiteral([ + stringEscape(json), + ]), + ), + ").get<", + cppType, + ">()", + ], + ), + ), + ";", ); }); - } + }, ); this.ensureBlankLine(); this.emitBlock( - ["inline void to_json(json & j, ", this.withConst([ourQualifier, className]), " & x)"], + [ + "inline void to_json(json & j, ", + this.withConst([ourQualifier, className]), + " & x)", + ], false, () => { this.emitLine("j = json::object();"); @@ -1637,59 +1558,74 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, false, - p.isOptional + p.isOptional, ); toType = this.cppType( propType, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, false, true, - p.isOptional + p.isOptional, + ); + const [getterName, ,] = defined( + this._gettersAndSettersForPropertyName.get(name), ); - const [getterName, ,] = defined(this._gettersAndSettersForPropertyName.get(name)); let getter: Sourcelike[]; if (this._options.codeFormat) { getter = [getterName, "()"]; } else { getter = [name]; } + const assignment: Sourcelike[] = [ "j[", this._stringType.wrapEncodingChange( [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - this._stringType.createStringLiteral([stringEscape(json)]) + this._stringType.createStringLiteral([ + stringEscape(json), + ]), ), "] = ", - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), - ";" + this._stringType.wrapEncodingChange( + [ourQualifier], + cppType, + toType, + ["x.", getter], + ), + ";", ]; if (p.isOptional && this._options.hideNullOptional) { this.emitBlock( [ "if (", - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, ["x.", getter]), - ")" + this._stringType.wrapEncodingChange( + [ourQualifier], + cppType, + toType, + ["x.", getter], + ), + ")", ], false, () => { this.emitLine(assignment); - } + }, ); } else { this.emitLine(assignment); } }); - } + }, ); } @@ -1709,11 +1645,25 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } }); this.emitDescription(this.descriptionForType(e)); - this.emitLine("enum class ", enumName, " : ", this._enumType, " { ", caseNames, " };"); + this.emitLine( + "enum class ", + enumName, + " : ", + this._enumType, + " { ", + caseNames, + " };", + ); } protected emitUnionTypedefs(u: UnionType, unionName: Name): void { - this.emitLine("using ", unionName, " = ", this.variantType(u, false), ";"); + this.emitLine( + "using ", + unionName, + " = ", + this.variantType(u, false), + ";", + ); } protected emitUnionHeaders(u: UnionType): void { @@ -1729,17 +1679,31 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false + false, ); this.emitLine("template <>"); - this.emitBlock(["struct adl_serializer<", variantType, ">"], true, () => { - this.emitLine("static void from_json(", this.withConst("json"), " & j, ", variantType, " & x);"); - this.emitLine("static void to_json(json & j, ", this.withConst(variantType), " & x);"); - }); + this.emitBlock( + ["struct adl_serializer<", variantType, ">"], + true, + () => { + this.emitLine( + "static void from_json(", + this.withConst("json"), + " & j, ", + variantType, + " & x);", + ); + this.emitLine( + "static void to_json(json & j, ", + this.withConst(variantType), + " & x);", + ); + }, + ); } protected emitUnionFunctions(u: UnionType): void { @@ -1747,7 +1711,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { const ourQualifier = this.ourQualifier(true) as string; - const functionForKind: [string, string][] = [ + const functionForKind: Array<[string, string]> = [ ["bool", "is_boolean"], ["integer", "is_number_integer"], ["double", "is_number"], @@ -1755,7 +1719,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ["class", "is_object"], ["map", "is_object"], ["array", "is_array"], - ["enum", "is_string"] + ["enum", "is_string"], ]; const nonNulls = removeNullFromUnion(u, true)[1]; const variantType = this.cppTypeInOptional( @@ -1763,10 +1727,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false + false, ); this.emitBlock( @@ -1777,113 +1741,156 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst("json"), " & j, ", variantType, - " & x)" + " & x)", ], false, () => { let onFirst = true; for (const [kind, func] of functionForKind) { - const typeForKind = iterableFind(nonNulls, t => t.kind === kind); + const typeForKind = iterableFind( + nonNulls, + (t) => t.kind === kind, + ); if (typeForKind === undefined) continue; - this.emitLine(onFirst ? "if" : "else if", " (j.", func, "())"); + this.emitLine( + onFirst ? "if" : "else if", + " (j.", + func, + "())", + ); this.indent(() => { const cppType = this.cppType( typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); const toType = this.cppType( typeForKind, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); this.emitLine( "x = ", - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ - "j.get<", + this._stringType.wrapEncodingChange( + [ourQualifier], cppType, - ">()" - ]), - ";" + toType, + ["j.get<", cppType, ">()"], + ), + ";", ); }); onFirst = false; } - this.emitLine('else throw std::runtime_error("Could not deserialise!");'); - } + + this.emitLine( + 'else throw std::runtime_error("Could not deserialise!");', + ); + }, ); this.ensureBlankLine(); this.emitBlock( - ["inline void adl_serializer<", variantType, ">::to_json(json & j, ", this.withConst(variantType), " & x)"], + [ + "inline void adl_serializer<", + variantType, + ">::to_json(json & j, ", + this.withConst(variantType), + " & x)", + ], false, () => { - this.emitBlock(["switch (x.", this._variantIndexMethodName, "())"], false, () => { - let i = 0; - for (const t of nonNulls) { - this.emitLine("case ", i.toString(), ":"); - this.indent(() => { - const cppType = this.cppType( - t, - { - needsForwardIndirection: true, - needsOptionalIndirection: true, - inJsonNamespace: true - }, - false, - false, - false - ); - const toType = this.cppType( - t, - { - needsForwardIndirection: true, - needsOptionalIndirection: true, - inJsonNamespace: true - }, - false, - true, - false - ); - this.emitLine( - "j = ", - this._stringType.wrapEncodingChange([ourQualifier], cppType, toType, [ - this._options.boost ? "boost::get<" : "std::get<", - cppType, - ">(x)" - ]), - ";" - ); - this.emitLine("break;"); - }); - i++; - } - this.emitLine('default: throw std::runtime_error("Input JSON does not conform to schema!");'); - }); - } + this.emitBlock( + ["switch (x.", this._variantIndexMethodName, "())"], + false, + () => { + let i = 0; + for (const t of nonNulls) { + this.emitLine("case ", i.toString(), ":"); + this.indent(() => { + const cppType = this.cppType( + t, + { + needsForwardIndirection: true, + needsOptionalIndirection: true, + inJsonNamespace: true, + }, + false, + false, + false, + ); + const toType = this.cppType( + t, + { + needsForwardIndirection: true, + needsOptionalIndirection: true, + inJsonNamespace: true, + }, + false, + true, + false, + ); + this.emitLine( + "j = ", + this._stringType.wrapEncodingChange( + [ourQualifier], + cppType, + toType, + [ + this._options.boost + ? "boost::get<" + : "std::get<", + cppType, + ">(x)", + ], + ), + ";", + ); + this.emitLine("break;"); + }); + i++; + } + + this.emitLine( + 'default: throw std::runtime_error("Input JSON does not conform to schema!");', + ); + }, + ); + }, ); } protected emitEnumHeaders(enumName: Name): void { const ourQualifier = this.ourQualifier(false); - this.emitLine("void from_json(", this.withConst("json"), " & j, ", ourQualifier, enumName, " & x);"); - this.emitLine("void to_json(json & j, ", this.withConst([ourQualifier, enumName]), " & x);"); + this.emitLine( + "void from_json(", + this.withConst("json"), + " & j, ", + ourQualifier, + enumName, + " & x);", + ); + this.emitLine( + "void to_json(json & j, ", + this.withConst([ourQualifier, enumName]), + " & x);", + ); } - private isLargeEnum(e: EnumType) { + private isLargeEnum(e: EnumType): boolean { // This is just an estimation. Someone might want to do some // benchmarks to find the optimum value here return e.cases.size > 15; @@ -1893,7 +1900,14 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { const ourQualifier = this.ourQualifier(false); this.emitBlock( - ["inline void from_json(", this.withConst("json"), " & j, ", ourQualifier, enumName, " & x)"], + [ + "inline void from_json(", + this.withConst("json"), + " & j, ", + ourQualifier, + enumName, + " & x)", + ], false, () => { if (this.isLargeEnum(e)) { @@ -1904,34 +1918,48 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { ", ", ourQualifier, enumName, - "> enumValues" + "> enumValues", ], true, () => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine( - "{", - this._stringType.wrapEncodingChange( - [ourQualifier], - this._stringType.getType(), - this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])] - ), - ", ", - ourQualifier, - enumName, - "::", - name, - "}," - ); - }); - } + this.forEachEnumCase( + e, + "none", + (name, jsonName) => { + this.emitLine( + "{", + this._stringType.wrapEncodingChange( + [ourQualifier], + this._stringType.getType(), + this.NarrowString.getType(), + [ + this._stringType.createStringLiteral( + [stringEscape(jsonName)], + ), + ], + ), + ", ", + ourQualifier, + enumName, + "::", + name, + "},", + ); + }, + ); + }, ); - this.emitLine(`auto iter = enumValues.find(j.get<${this._stringType.getType()}>());`); - this.emitBlock("if (iter != enumValues.end())", false, () => { - this.emitLine("x = iter->second;"); - }); + this.emitLine( + `auto iter = enumValues.find(j.get<${this._stringType.getType()}>());`, + ); + this.emitBlock( + "if (iter != enumValues.end())", + false, + () => { + this.emitLine("x = iter->second;"); + }, + ); } else { let onFirst = true; this.forEachEnumCase(e, "none", (name, jsonName) => { @@ -1943,25 +1971,35 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])] + [ + this._stringType.createStringLiteral([ + stringEscape(jsonName), + ]), + ], ), ") x = ", ourQualifier, enumName, "::", name, - ";" + ";", ); onFirst = false; }); - this.emitLine('else { throw std::runtime_error("Input JSON does not conform to schema!"); }'); + this.emitLine( + 'else { throw std::runtime_error("Input JSON does not conform to schema!"); }', + ); } - } + }, ); this.ensureBlankLine(); this.emitBlock( - ["inline void to_json(json & j, ", this.withConst([ourQualifier, enumName]), " & x)"], + [ + "inline void to_json(json & j, ", + this.withConst([ourQualifier, enumName]), + " & x)", + ], false, () => { this.emitBlock("switch (x)", false, () => { @@ -1977,14 +2015,22 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { [ourQualifier], this._stringType.getType(), this.NarrowString.getType(), - [this._stringType.createStringLiteral([stringEscape(jsonName)])] + [ + this._stringType.createStringLiteral([ + stringEscape(jsonName), + ]), + ], ), - "; break;" + "; break;", ); }); - this.emitLine('default: throw std::runtime_error("This should not happen");'); + this.emitLine( + `default: throw std::runtime_error("Unexpected value in enumeration \\"`, + enumName, + `\\": " + std::to_string(static_cast(x)));`, + ); }); - } + }, ); } @@ -1998,53 +2044,53 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: false + inJsonNamespace: false, }, true, false, - false + false, ), - ";" + ";", ); } protected emitAllUnionFunctions(): void { this.forEachUniqueUnion( "leading-and-interposing", - u => + (u) => this.sourcelikeToString( this.cppTypeInOptional( removeNullFromUnion(u, true)[1], { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false - ) + false, + ), ), - (u: UnionType) => this.emitUnionFunctions(u) + (u: UnionType) => this.emitUnionFunctions(u), ); } protected emitAllUnionHeaders(): void { this.forEachUniqueUnion( "interposing", - u => + (u) => this.sourcelikeToString( this.cppTypeInOptional( removeNullFromUnion(u, true)[1], { needsForwardIndirection: false, needsOptionalIndirection: false, - inJsonNamespace: true + inJsonNamespace: true, }, false, - false - ) + false, + ), ), - (u: UnionType) => this.emitUnionHeaders(u) + (u: UnionType) => this.emitUnionHeaders(u), ); } @@ -2053,32 +2099,52 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine("#define NLOHMANN_OPT_HELPER"); this.emitNamespaces(["nlohmann"], () => { - const emitAdlStruct = (optType: string, factory: string) => { + const emitAdlStruct = (optType: string, factory: string): void => { this.emitLine("template "); - this.emitBlock(["struct adl_serializer<", optType, ">"], true, () => { - this.emitBlock( - ["static void to_json(json & j, ", this.withConst([optType, ""]), " & opt)"], - false, - () => { - this.emitLine("if (!opt) j = nullptr; else j = *opt;"); - } - ); + this.emitBlock( + ["struct adl_serializer<", optType, ">"], + true, + () => { + this.emitBlock( + [ + "static void to_json(json & j, ", + this.withConst([optType, ""]), + " & opt)", + ], + false, + () => { + this.emitLine( + "if (!opt) j = nullptr; else j = *opt;", + ); + }, + ); - this.ensureBlankLine(); + this.ensureBlankLine(); - this.emitBlock( - ["static ", optType, " from_json(", this.withConst("json"), " & j)"], - false, - () => { - this.emitLine( - `if (j.is_null()) return ${factory}(); else return ${factory}(j.get());` - ); - } - ); - }); + this.emitBlock( + [ + "static ", + optType, + " from_json(", + this.withConst("json"), + " & j)", + ], + false, + () => { + this.emitLine( + `if (j.is_null()) return ${factory}(); else return ${factory}(j.get());`, + ); + }, + ); + }, + ); }; + emitAdlStruct(this.optionalTypeHeap(), this.optionalFactoryHeap()); - emitAdlStruct(this.optionalTypeStack(), this.optionalFactoryStack()); + emitAdlStruct( + this.optionalTypeStack(), + this.optionalFactoryStack(), + ); }); this.emitLine("#endif"); @@ -2108,9 +2174,32 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitGetterSetter(t: string, getterName: string, setterName: string, memberName: string): void { - this.emitLine("void ", setterName, "(", t, " ", memberName, ") { this->", memberName, " = ", memberName, "; }"); - this.emitLine("auto ", getterName, "() const { return ", memberName, "; }"); + protected emitGetterSetter( + t: string, + getterName: string, + setterName: string, + memberName: string, + ): void { + this.emitLine( + "void ", + setterName, + "(", + t, + " ", + memberName, + ") { this->", + memberName, + " = ", + memberName, + "; }", + ); + this.emitLine( + "auto ", + getterName, + "() const { return ", + memberName, + "; }", + ); } protected emitNumericCheckConstraints( @@ -2118,7 +2207,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { classConstraint: string, getterMinValue: string, getterMaxValue: string, - cppType: string + cppType: string, ): void { this.emitBlock( [ @@ -2130,19 +2219,31 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(classConstraint), " & c, ", cppType, - " value)" + " value)", ], false, () => { this.emitBlock( - ["if (c.", getterMinValue, "() != ", this._nulloptType, " && value < *c.", getterMinValue, "())"], + [ + "if (c.", + getterMinValue, + "() != ", + this._nulloptType, + " && value < *c.", + getterMinValue, + "())", + ], false, () => { this.emitLine( "throw ", - this.lookupGlobalName(GlobalNames.ValueTooLowException), + this.lookupGlobalName( + GlobalNames.ValueTooLowException, + ), " (", - this._stringType.createStringLiteral(["Value too low for "]), + this._stringType.createStringLiteral([ + "Value too low for ", + ]), " + name + ", this._stringType.createStringLiteral([" ("]), " + ", @@ -2150,24 +2251,40 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " + ", this._stringType.createStringLiteral(["<"]), " + ", - this._stringType.wrapToString(["*c.", getterMinValue, "()"]), + this._stringType.wrapToString([ + "*c.", + getterMinValue, + "()", + ]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); this.emitBlock( - ["if (c.", getterMaxValue, "() != ", this._nulloptType, " && value > *c.", getterMaxValue, "())"], + [ + "if (c.", + getterMaxValue, + "() != ", + this._nulloptType, + " && value > *c.", + getterMaxValue, + "())", + ], false, () => { this.emitLine( "throw ", - this.lookupGlobalName(GlobalNames.ValueTooHighException), + this.lookupGlobalName( + GlobalNames.ValueTooHighException, + ), " (", - this._stringType.createStringLiteral(["Value too high for "]), + this._stringType.createStringLiteral([ + "Value too high for ", + ]), " + name + ", this._stringType.createStringLiteral([" ("]), " + ", @@ -2175,15 +2292,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " + ", this._stringType.createStringLiteral([">"]), " + ", - this._stringType.wrapToString(["*c.", getterMaxValue, "()"]), + this._stringType.wrapToString([ + "*c.", + getterMaxValue, + "()", + ]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); - } + }, ); this.ensureBlankLine(); } @@ -2191,29 +2312,55 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { protected emitConstraintClasses(): void { const ourQualifier = this.ourQualifier(false) as string; - const getterMinIntValue = this.lookupMemberName(MemberNames.GetMinIntValue); - const getterMaxIntValue = this.lookupMemberName(MemberNames.GetMaxIntValue); - const getterMinDoubleValue = this.lookupMemberName(MemberNames.GetMinDoubleValue); - const getterMaxDoubleValue = this.lookupMemberName(MemberNames.GetMaxDoubleValue); + const getterMinIntValue = this.lookupMemberName( + MemberNames.GetMinIntValue, + ); + const getterMaxIntValue = this.lookupMemberName( + MemberNames.GetMaxIntValue, + ); + const getterMinDoubleValue = this.lookupMemberName( + MemberNames.GetMinDoubleValue, + ); + const getterMaxDoubleValue = this.lookupMemberName( + MemberNames.GetMaxDoubleValue, + ); const getterMinLength = this.lookupMemberName(MemberNames.GetMinLength); const getterMaxLength = this.lookupMemberName(MemberNames.GetMaxLength); const getterPattern = this.lookupMemberName(MemberNames.GetPattern); - const classConstraint = this.lookupGlobalName(GlobalNames.ClassMemberConstraints); + const classConstraint = this.lookupGlobalName( + GlobalNames.ClassMemberConstraints, + ); this.emitBlock(["class ", classConstraint], true, () => { this.emitLine("private:"); - const constraintMembers: ConstraintMember[] = this.getConstraintMembers(); + const constraintMembers: ConstraintMember[] = + this.getConstraintMembers(); for (const member of constraintMembers) { - this.emitMember([this._optionalType, "<", member.cppType, ">"], this.lookupMemberName(member.name)); + this.emitMember( + [this._optionalType, "<", member.cppType, ">"], + this.lookupMemberName(member.name), + ); } + this.ensureBlankLine(); this.emitLine("public:"); this.emitLine(classConstraint, "("); this.indent(() => { - this.iterableForEach(constraintMembers, ({ name, cppType }, pos) => { - const comma = pos === "first" || pos === "middle" ? "," : []; - this.emitLine(this._optionalType, "<", cppType, "> ", this.lookupMemberName(name), comma); - }); + this.iterableForEach( + constraintMembers, + ({ name, cppType }, pos) => { + const comma = + pos === "first" || pos === "middle" ? "," : []; + this.emitLine( + this._optionalType, + "<", + cppType, + "> ", + this.lookupMemberName(name), + comma, + ); + }, + ); }); const args = constraintMembers.map(({ name }) => { @@ -2230,29 +2377,35 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { withDefault(member.cppConstType, member.cppType), this.lookupMemberName(member.getter), this.lookupMemberName(member.setter), - this.lookupMemberName(member.name) + this.lookupMemberName(member.name), ); } }); this.ensureBlankLine(); - const classConstEx = this.lookupGlobalName(GlobalNames.ClassMemberConstraintException); - this.emitBlock(["class ", classConstEx, " : public std::runtime_error"], true, () => { - this.emitLine("public:"); - this.emitLine( - classConstEx, - "(", - this._stringType.getConstType(), - " msg) : std::runtime_error(", - this._stringType.wrapEncodingChange( - [ourQualifier], - this._stringType.getType(), - this.NarrowString.getType(), - ["msg"] - ), - ") {}" - ); - }); + const classConstEx = this.lookupGlobalName( + GlobalNames.ClassMemberConstraintException, + ); + this.emitBlock( + ["class ", classConstEx, " : public std::runtime_error"], + true, + () => { + this.emitLine("public:"); + this.emitLine( + classConstEx, + "(", + this._stringType.getConstType(), + " msg) : std::runtime_error(", + this._stringType.wrapEncodingChange( + [ourQualifier], + this._stringType.getType(), + this.NarrowString.getType(), + ["msg"], + ), + ") {}", + ); + }, + ); this.ensureBlankLine(); const exceptions: GlobalNames[] = [ @@ -2260,26 +2413,43 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { GlobalNames.ValueTooHighException, GlobalNames.ValueTooShortException, GlobalNames.ValueTooLongException, - GlobalNames.InvalidPatternException + GlobalNames.InvalidPatternException, ]; for (const ex of exceptions) { const name = this.lookupGlobalName(ex); - this.emitBlock(["class ", name, " : public ", classConstEx], true, () => { - this.emitLine("public:"); - this.emitLine(name, "(", this._stringType.getConstType(), " msg) : ", classConstEx, "(msg) {}"); - }); + this.emitBlock( + ["class ", name, " : public ", classConstEx], + true, + () => { + this.emitLine("public:"); + this.emitLine( + name, + "(", + this._stringType.getConstType(), + " msg) : ", + classConstEx, + "(msg) {}", + ); + }, + ); this.ensureBlankLine(); } const checkConst = this.lookupGlobalName(GlobalNames.CheckConstraint); - this.emitNumericCheckConstraints(checkConst, classConstraint, getterMinIntValue, getterMaxIntValue, "int64_t"); + this.emitNumericCheckConstraints( + checkConst, + classConstraint, + getterMinIntValue, + getterMaxIntValue, + "int64_t", + ); this.emitNumericCheckConstraints( checkConst, classConstraint, getterMinDoubleValue, getterMaxDoubleValue, - "double" + "double", ); this.emitBlock( @@ -2292,7 +2462,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst(classConstraint), " & c, ", this._stringType.getConstType(), - " value)" + " value)", ], false, () => { @@ -2304,15 +2474,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._nulloptType, " && value.length() < *c.", getterMinLength, - "())" + "())", ], false, () => { this.emitLine( "throw ", - this.lookupGlobalName(GlobalNames.ValueTooShortException), + this.lookupGlobalName( + GlobalNames.ValueTooShortException, + ), " (", - this._stringType.createStringLiteral(["Value too short for "]), + this._stringType.createStringLiteral([ + "Value too short for ", + ]), " + name + ", this._stringType.createStringLiteral([" ("]), " + ", @@ -2320,12 +2494,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " + ", this._stringType.createStringLiteral(["<"]), " + ", - this._stringType.wrapToString(["*c.", getterMinLength, "()"]), + this._stringType.wrapToString([ + "*c.", + getterMinLength, + "()", + ]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); @@ -2337,15 +2515,19 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._nulloptType, " && value.length() > *c.", getterMaxLength, - "())" + "())", ], false, () => { this.emitLine( "throw ", - this.lookupGlobalName(GlobalNames.ValueTooLongException), + this.lookupGlobalName( + GlobalNames.ValueTooLongException, + ), " (", - this._stringType.createStringLiteral(["Value too long for "]), + this._stringType.createStringLiteral([ + "Value too long for ", + ]), " + name + ", this._stringType.createStringLiteral([" ("]), " + ", @@ -2353,44 +2535,56 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { " + ", this._stringType.createStringLiteral([">"]), " + ", - this._stringType.wrapToString(["*c.", getterMaxLength, "()"]), + this._stringType.wrapToString([ + "*c.", + getterMaxLength, + "()", + ]), " + ", this._stringType.createStringLiteral([")"]), - ");" + ");", ); - } + }, ); this.ensureBlankLine(); - this.emitBlock(["if (c.", getterPattern, "() != ", this._nulloptType, ")"], false, () => { - this.emitLine(this._stringType.getSMatch(), " result;"); - this.emitLine( - "std::regex_search(value, result, ", - this._stringType.getRegex(), - "( *c.", - getterPattern, - "() ));" - ); - this.emitBlock(["if (result.empty())"], false, () => { + this.emitBlock( + ["if (c.", getterPattern, "() != ", this._nulloptType, ")"], + false, + () => { + this.emitLine(this._stringType.getSMatch(), " result;"); this.emitLine( - "throw ", - this.lookupGlobalName(GlobalNames.InvalidPatternException), - " (", - this._stringType.createStringLiteral(["Value doesn't match pattern for "]), - " + name + ", - this._stringType.createStringLiteral([" ("]), - " + value +", - this._stringType.createStringLiteral([" != "]), - " + *c.", + "std::regex_search(value, result, ", + this._stringType.getRegex(), + "( *c.", getterPattern, - "() + ", - this._stringType.createStringLiteral([")"]), - ");" + "() ));", ); - }); - }); + this.emitBlock(["if (result.empty())"], false, () => { + this.emitLine( + "throw ", + this.lookupGlobalName( + GlobalNames.InvalidPatternException, + ), + " (", + this._stringType.createStringLiteral([ + "Value doesn't match pattern for ", + ]), + " + name + ", + this._stringType.createStringLiteral([" ("]), + " + value +", + this._stringType.createStringLiteral([" != "]), + " + *c.", + getterPattern, + "() + ", + this._stringType.createStringLiteral([")"]), + ");", + ); + }); + }, + ); this.ensureBlankLine(); - } + }, ); } @@ -2399,7 +2593,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { if ( this._options.codeFormat && - iterableSome(this.typeGraph.allTypesUnordered(), t => constraintsForType(t) !== undefined) + iterableSome( + this.typeGraph.allTypesUnordered(), + (t) => constraintsForType(t) !== undefined, + ) ) { this.emitConstraintClasses(); this.ensureBlankLine(); @@ -2409,7 +2606,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { let untypedMacroName = "NLOHMANN_UNTYPED_"; let optionalMacroName = "NLOHMANN_OPTIONAL_"; - this._namespaceNames.forEach(value => { + this._namespaceNames.forEach((value) => { // We can't use upper name, because namespaces are case sensitive untypedMacroName += value; untypedMacroName += "_"; @@ -2425,24 +2622,38 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine(`#define ${untypedMacroName}`); this.emitBlock( - ["inline json get_untyped(", this.withConst("json"), " & j, ", this.withConst("char"), " * property)"], + [ + "inline json get_untyped(", + this.withConst("json"), + " & j, ", + this.withConst("char"), + " * property)", + ], false, () => { - this.emitBlock(["if (j.find(property) != j.end())"], false, () => { - this.emitLine("return j.at(property).get();"); - }); + this.emitBlock( + ["if (j.find(property) != j.end())"], + false, + () => { + this.emitLine("return j.at(property).get();"); + }, + ); this.emitLine("return json();"); - } + }, ); this.ensureBlankLine(); this.emitBlock( - ["inline json get_untyped(", this.withConst("json"), " & j, std::string property)"], + [ + "inline json get_untyped(", + this.withConst("json"), + " & j, std::string property)", + ], false, () => { this.emitLine("return get_untyped(j, property.data());"); - } + }, ); this.emitLine("#endif"); @@ -2455,7 +2666,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitLine(`#ifndef ${optionalMacroName}`); this.emitLine(`#define ${optionalMacroName}`); - const emitGetOptional = (optionalType: string, label: string): void => { + const emitGetOptional = ( + optionalType: string, + label: string, + ): void => { this.emitLine("template "); this.emitBlock( [ @@ -2465,16 +2679,24 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.withConst("json"), " & j, ", this.withConst("char"), - " * property)" + " * property)", ], false, () => { this.emitLine(["auto it = j.find(property);"]); - this.emitBlock(["if (it != j.end() && !it->is_null())"], false, () => { - this.emitLine("return j.at(property).get<", optionalType, ">();"); - }); + this.emitBlock( + ["if (it != j.end() && !it->is_null())"], + false, + () => { + this.emitLine( + "return j.at(property).get<", + optionalType, + ">();", + ); + }, + ); this.emitLine("return ", optionalType, "();"); - } + }, ); this.ensureBlankLine(); @@ -2486,14 +2708,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { optionalType, ` get_${label}_optional(`, this.withConst("json"), - " & j, std::string property)" + " & j, std::string property)", ], false, () => { - this.emitLine(`return get_${label}_optional(j, property.data());`); - } + this.emitLine( + `return get_${label}_optional(j, property.data());`, + ); + }, ); }; + emitGetOptional(this.optionalTypeHeap(), "heap"); emitGetOptional(this.optionalTypeStack(), "stack"); @@ -2512,6 +2737,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } else { this.emitInclude(true, "optional"); } + this.emitInclude(true, "stdexcept"); this.emitInclude(true, "regex"); } @@ -2522,7 +2748,11 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } // Include unordered_map if contains large enums - if (Array.from(this.enums).some(enumType => this.isLargeEnum(enumType))) { + if ( + Array.from(this.enums).some((enumType) => + this.isLargeEnum(enumType), + ) + ) { this.emitInclude(true, "unordered_map"); } @@ -2556,29 +2786,39 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.ensureBlankLine(); this.emitHelperFunctions(); } - this.forEachDeclaration("interposing", decl => this.emitDeclaration(decl)); + + this.forEachDeclaration("interposing", (decl) => + this.emitDeclaration(decl), + ); if (this._options.justTypes) return; this.forEachTopLevel( "leading", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); } protected gatherUserNamespaceForwardDecls(): Sourcelike[] { return this.gatherSource(() => { - this.forEachObject("leading-and-interposing", (_: any, className: Name) => - this.emitClassHeaders(className) + this.forEachObject( + "leading-and-interposing", + (_: unknown, className: Name) => + this.emitClassHeaders(className), ); - this.forEachEnum("leading-and-interposing", (_: any, enumName: Name) => this.emitEnumHeaders(enumName)); + this.forEachEnum( + "leading-and-interposing", + (_: unknown, enumName: Name) => this.emitEnumHeaders(enumName), + ); }); } protected gatherNlohmannNamespaceForwardDecls(): Sourcelike[] { return this.gatherSource(() => { - this.forEachTopLevel("leading-and-interposing", (t: Type, className: Name) => - this.emitTopLevelHeaders(t, className) + this.forEachTopLevel( + "leading-and-interposing", + (t: Type, className: Name) => + this.emitTopLevelHeaders(t, className), ); this.ensureBlankLine(); @@ -2588,12 +2828,16 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } protected emitUserNamespaceImpls(): void { - this.forEachObject("leading-and-interposing", (c: ClassType, className: Name) => - this.emitClassFunctions(c, className) + this.forEachObject( + "leading-and-interposing", + (c: ClassType, className: Name) => + this.emitClassFunctions(c, className), ); - this.forEachEnum("leading-and-interposing", (e: EnumType, enumName: Name) => - this.emitEnumFunctions(e, enumName) + this.forEachEnum( + "leading-and-interposing", + (e: EnumType, enumName: Name) => + this.emitEnumFunctions(e, enumName), ); } @@ -2601,7 +2845,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading-and-interposing", (t: Type, name: Name) => this.emitTopLevelFunction(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); this.ensureBlankLine(); @@ -2616,30 +2860,42 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.emitNamespaces(this._namespaceNames, () => { didEmit = this.forEachTopLevel( "none", - (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + (t: Type, name: Name) => + this.emitTopLevelTypedef(t, name), + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); - }) + }), ); if (didEmit) { this.emitGatheredSource(gathered); this.ensureBlankLine(); } } else { - const userNamespaceForwardDecls = this.gatherUserNamespaceForwardDecls(); - const nlohmannNamespaceForwardDecls = this.gatherNlohmannNamespaceForwardDecls(); - - if (userNamespaceForwardDecls.length === 0 && nlohmannNamespaceForwardDecls.length > 0) { + const userNamespaceForwardDecls = + this.gatherUserNamespaceForwardDecls(); + const nlohmannNamespaceForwardDecls = + this.gatherNlohmannNamespaceForwardDecls(); + + if ( + userNamespaceForwardDecls.length === 0 && + nlohmannNamespaceForwardDecls.length > 0 + ) { this.emitNamespaces(["nlohmann"], () => { this.emitGatheredSource(nlohmannNamespaceForwardDecls); this.emitNlohmannNamespaceImpls(); }); - } else if (userNamespaceForwardDecls.length > 0 && nlohmannNamespaceForwardDecls.length === 0) { + } else if ( + userNamespaceForwardDecls.length > 0 && + nlohmannNamespaceForwardDecls.length === 0 + ) { this.emitNamespaces(this._namespaceNames, () => { this.emitGatheredSource(userNamespaceForwardDecls); this.emitUserNamespaceImpls(); }); - } else if (userNamespaceForwardDecls.length > 0 && nlohmannNamespaceForwardDecls.length > 0) { + } else if ( + userNamespaceForwardDecls.length > 0 && + nlohmannNamespaceForwardDecls.length > 0 + ) { this.emitNamespaces(this._namespaceNames, () => { this.emitGatheredSource(userNamespaceForwardDecls); }); @@ -2665,10 +2921,15 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { if (this._options.justTypes) { this.emitTypes(); } else { - if (!this._options.justTypes && this.haveNamedTypes && (this.haveUnions || this.haveOptionalProperties)) { + if ( + !this._options.justTypes && + this.haveNamedTypes && + (this.haveUnions || this.haveOptionalProperties) + ) { this.emitOptionalHelpers(); this.ensureBlankLine(); } + this.emitNamespaces(this._namespaceNames, () => this.emitTypes()); } @@ -2679,13 +2940,21 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.finishFile(); } - protected updateIncludes(isClassMember: boolean, includes: IncludeMap, propertyType: Type, _defName: string): void { + protected updateIncludes( + isClassMember: boolean, + includes: IncludeMap, + propertyType: Type, + _defName: string, + ): void { const propTypes = this.generatedTypes(isClassMember, propertyType); for (const t of propTypes) { const typeName = this.sourcelikeToString(t.name); - const propRecord: IncludeRecord = { kind: undefined, typeKind: undefined }; + const propRecord: IncludeRecord = { + kind: undefined, + typeKind: undefined, + }; if (t.type instanceof ClassType) { /** @@ -2694,7 +2963,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { * - level > 0 - then we can SURELY forward declare it. */ propRecord.typeKind = "class"; - propRecord.kind = t.level === 0 ? IncludeKind.Include : IncludeKind.ForwardDeclare; + propRecord.kind = + t.level === 0 + ? IncludeKind.Include + : IncludeKind.ForwardDeclare; if (t.forceInclude) { propRecord.kind = IncludeKind.Include; } @@ -2723,7 +2995,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { * If we already include the type as typed include, * do not write it over with forward declare */ - if (incKind !== undefined && incKind.kind === IncludeKind.ForwardDeclare) { + if ( + incKind !== undefined && + incKind.kind === IncludeKind.ForwardDeclare + ) { includes.set(typeName, propRecord); } } else { @@ -2732,7 +3007,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitIncludes(c: ClassType | UnionType | EnumType, defName: string): void { + protected emitIncludes( + c: ClassType | UnionType | EnumType, + defName: string, + ): void { /** * Need to generate "includes", in terms 'c' has members, which * are defined by others @@ -2742,9 +3020,13 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { if (c instanceof UnionType) { this.updateIncludes(false, includes, c, defName); } else if (c instanceof ClassType) { - this.forEachClassProperty(c, "none", (_name, _jsonName, property) => { - this.updateIncludes(true, includes, property.type, defName); - }); + this.forEachClassProperty( + c, + "none", + (_name, _jsonName, property) => { + this.updateIncludes(true, includes, property.type, defName); + }, + ); } if (includes.size !== 0) { @@ -2780,16 +3062,27 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { return; } - if (rec.typeKind === "class" || rec.typeKind === "union") { + if ( + rec.typeKind === "class" || + rec.typeKind === "union" + ) { if (this._options.codeFormat) { this.emitLine("class ", name, ";"); } else { this.emitLine("struct ", name, ";"); } } else if (rec.typeKind === "enum") { - this.emitLine("enum class ", name, " : ", this._enumType, ";"); + this.emitLine( + "enum class ", + name, + " : ", + this._enumType, + ";", + ); } else { - panic(`Invalid type "${rec.typeKind}" to forward declare`); + panic( + `Invalid type "${rec.typeKind}" to forward declare`, + ); } }); }); @@ -2799,7 +3092,10 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected emitDefinition(d: ClassType | EnumType | UnionType, defName: Name): void { + protected emitDefinition( + d: ClassType | EnumType | UnionType, + defName: Name, + ): void { const name = `${this.sourcelikeToString(defName)}.hpp`; this.startFile(name, true); this._generatedFiles.add(name); @@ -2829,7 +3125,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.startFile("Generators.hpp", true); - this._allTypeNames.forEach(t => { + this._allTypeNames.forEach((t) => { this.emitInclude(false, [t, ".hpp"]); }); @@ -2849,7 +3145,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { }, (u, n) => { this.emitDefinition(u, n); - } + }, ); /** @@ -2863,7 +3159,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.startFile(proposedFilename); - this._generatedFiles.forEach(f => { + this._generatedFiles.forEach((f) => { this.emitInclude(false, f); }); @@ -2871,7 +3167,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.forEachTopLevel( "leading", (t: Type, name: Name) => this.emitTopLevelTypedef(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); }); @@ -2884,28 +3180,36 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { /** Gather all the unique/custom types used by the schema */ this._allTypeNames.clear(); - this.forEachDeclaration("none", decl => { - const definedTypes = directlyReachableTypes(decl.type, t => { - if (isNamedType(t) && (t instanceof ClassType || t instanceof EnumType || t instanceof UnionType)) { - return new Set([ - this.sourcelikeToString( - this.cppType( - t, - { - needsForwardIndirection: false, - needsOptionalIndirection: false, - inJsonNamespace: false - }, - true, - false, - false - ) - ) - ]); - } + this.forEachDeclaration("none", (decl) => { + const definedTypes = directlyReachableTypes( + decl.type, + (t) => { + if ( + isNamedType(t) && + (t instanceof ClassType || + t instanceof EnumType || + t instanceof UnionType) + ) { + return new Set([ + this.sourcelikeToString( + this.cppType( + t, + { + needsForwardIndirection: false, + needsOptionalIndirection: false, + inJsonNamespace: false, + }, + true, + false, + false, + ), + ), + ]); + } - return null; - }); + return null; + }, + ); this._allTypeNames = setUnion(definedTypes, this._allTypeNames); }); @@ -2917,17 +3221,17 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { } } - protected isConversionRequired(t: Type) { + protected isConversionRequired(t: Type): boolean { const originalType = this.cppType( t, { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, false, - false + false, ); const newType = this.cppType( @@ -2935,18 +3239,18 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { { needsForwardIndirection: true, needsOptionalIndirection: true, - inJsonNamespace: true + inJsonNamespace: true, }, false, true, - false + false, ); return originalType !== newType; } public NarrowString = new (class extends BaseString implements StringType { - constructor() { + public constructor() { super( "std::string", "const std::string & ", @@ -2955,7 +3259,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { "", new WrappingCode(["std::to_string("], [")"]), "", - "" + "", ); } @@ -2963,7 +3267,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { _qualifier: Sourcelike[], _fromType: Sourcelike, _toType: Sourcelike, - inner: Sourcelike + inner: Sourcelike, ): Sourcelike { return inner; } @@ -2974,7 +3278,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { })(); public WideString = new (class extends BaseString implements StringType { - constructor(public superThis: CPlusPlusRenderer) { + public constructor(public superThis: CPlusPlusRenderer) { super( "std::wstring", "const std::wstring & ", @@ -2983,7 +3287,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { "L", new WrappingCode(["std::to_wstring("], [")"]), "Utf16_Utf8", - "convert" + "convert", ); } @@ -2991,9 +3295,12 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { qualifier: Sourcelike[], fromType: Sourcelike, toType: Sourcelike, - inner: Sourcelike + inner: Sourcelike, ): Sourcelike { - if (this.superThis.sourcelikeToString(fromType) === this.superThis.sourcelikeToString(toType)) { + if ( + this.superThis.sourcelikeToString(fromType) === + this.superThis.sourcelikeToString(toType) + ) { return inner; } @@ -3007,7 +3314,7 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this._encodingFunction, "(", inner, - ")" + ")", ]; } @@ -3016,100 +3323,144 @@ export class CPlusPlusRenderer extends ConvenienceRenderer { this.superThis.emitLine("struct tag {};"); this.superThis.ensureBlankLine(); - this.superThis.emitLine("template"); + this.superThis.emitLine( + "template", + ); this.superThis.emitBlock(["class Utf16_Utf8"], true, () => { this.superThis.emitLine("private:"); this.superThis.emitLine("template"); this.superThis.emitBlock( - ["static toType convert(tag >, tag >, fromType ptr)"], + [ + "static toType convert(tag >, tag >, fromType ptr)", + ], false, () => { this.superThis.emitLine( - "if (ptr == nullptr) return std::unique_ptr(); else return std::unique_ptr(new TT(Utf16_Utf8::convert(*ptr)));" + "if (ptr == nullptr) return std::unique_ptr(); else return std::unique_ptr(new TT(Utf16_Utf8::convert(*ptr)));", ); - } + }, ); this.superThis.ensureBlankLine(); this.superThis.emitLine("template"); this.superThis.emitBlock( - ["static toType convert(tag >, tag >, fromType v)"], + [ + "static toType convert(tag >, tag >, fromType v)", + ], false, () => { this.superThis.emitLine("auto it = v.begin();"); - this.superThis.emitLine("auto newVector = std::vector();"); - this.superThis.emitBlock(["while (it != v.end())"], false, () => { - this.superThis.emitLine("newVector.push_back(Utf16_Utf8::convert(*it));"); - this.superThis.emitLine("it++;"); - }); + this.superThis.emitLine( + "auto newVector = std::vector();", + ); + this.superThis.emitBlock( + ["while (it != v.end())"], + false, + () => { + this.superThis.emitLine( + "newVector.push_back(Utf16_Utf8::convert(*it));", + ); + this.superThis.emitLine("it++;"); + }, + ); this.superThis.emitLine("return newVector;"); - } + }, ); this.superThis.ensureBlankLine(); - this.superThis.emitLine("template"); + this.superThis.emitLine( + "template", + ); this.superThis.emitBlock( - ["static toType convert(tag >, tag >, fromType m)"], + [ + "static toType convert(tag >, tag >, fromType m)", + ], false, () => { this.superThis.emitLine("auto it = m.begin();"); - this.superThis.emitLine("auto newMap = std::map();"); - this.superThis.emitBlock(["while (it != m.end())"], false, () => { - this.superThis.emitLine( - "newMap.insert(std::pair(Utf16_Utf8::convert(it->first), Utf16_Utf8::convert(it->second)));" - ); - this.superThis.emitLine("it++;"); - }); + this.superThis.emitLine( + "auto newMap = std::map();", + ); + this.superThis.emitBlock( + ["while (it != m.end())"], + false, + () => { + this.superThis.emitLine( + "newMap.insert(std::pair(Utf16_Utf8::convert(it->first), Utf16_Utf8::convert(it->second)));", + ); + this.superThis.emitLine("it++;"); + }, + ); this.superThis.emitLine("return newMap;"); - } + }, ); this.superThis.ensureBlankLine(); this.superThis.emitLine("template"); - this.superThis.emitBlock(["static fromType convert(tag, tag, fromType from)"], false, () => { - this.superThis.emitLine("return from;"); - }); + this.superThis.emitBlock( + [ + "static fromType convert(tag, tag, fromType from)", + ], + false, + () => { + this.superThis.emitLine("return from;"); + }, + ); this.superThis.ensureBlankLine(); this.superThis.emitBlock( - ["static std::wstring convert(tag, tag, std::string str)"], + [ + "static std::wstring convert(tag, tag, std::string str)", + ], false, () => { this.superThis.emitLine( - "return std::wstring_convert, wchar_t>{}.from_bytes(str.data());" + "return std::wstring_convert, wchar_t>{}.from_bytes(str.data());", ); - } + }, ); this.superThis.ensureBlankLine(); this.superThis.emitBlock( - ["static std::string convert(tag, tag, std::wstring str)"], + [ + "static std::string convert(tag, tag, std::wstring str)", + ], false, () => { this.superThis.emitLine( - "return std::wstring_convert, wchar_t>{}.to_bytes(str.data());" + "return std::wstring_convert, wchar_t>{}.to_bytes(str.data());", ); - } + }, ); this.superThis.ensureBlankLine(); this.superThis.emitLine("public:"); - this.superThis.emitBlock(["static toType convert(fromType in)"], false, () => { - this.superThis.emitLine("return convert(tag(), tag(), in);"); - }); + this.superThis.emitBlock( + ["static toType convert(fromType in)"], + false, + () => { + this.superThis.emitLine( + "return convert(tag(), tag(), in);", + ); + }, + ); }); this.superThis.ensureBlankLine(); this.superThis.emitLine("template"); - this.superThis.emitBlock(["std::wstring wdump(const T& j)"], false, () => { - this.superThis.emitLine("std::ostringstream s;"); - this.superThis.emitLine("s << j;"); - this.superThis.emitLine( - "return ", - this.superThis.ourQualifier(false), - "Utf16_Utf8::convert(s.str()); " - ); - }); + this.superThis.emitBlock( + ["std::wstring wdump(const T& j)"], + false, + () => { + this.superThis.emitLine("std::ostringstream s;"); + this.superThis.emitLine("s << j;"); + this.superThis.emitLine( + "return ", + this.superThis.ourQualifier(false), + "Utf16_Utf8::convert(s.str()); ", + ); + }, + ); this.superThis.ensureBlankLine(); } })(this); diff --git a/packages/quicktype-core/src/language/CPlusPlus/constants.ts b/packages/quicktype-core/src/language/CPlusPlus/constants.ts new file mode 100644 index 000000000..a8872a1cc --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/constants.ts @@ -0,0 +1,102 @@ +export const keywords = [ + "alignas", + "alignof", + "and", + "and_eq", + "asm", + "atomic_cancel", + "atomic_commit", + "atomic_noexcept", + "auto", + "bitand", + "bitor", + "bool", + "break", + "case", + "catch", + "char", + "char16_t", + "char32_t", + "class", + "compl", + "concept", + "const", + "constexpr", + "const_cast", + "continue", + "co_await", + "co_return", + "co_yield", + "decltype", + "default", + "delete", + "do", + "double", + "dynamic_cast", + "else", + "enum", + "explicit", + "export", + "extern", + "false", + "float", + "for", + "friend", + "goto", + "if", + "import", + "inline", + "int", + "long", + "module", + "mutable", + "namespace", + "new", + "noexcept", + "not", + "not_eq", + "nullptr", + "operator", + "or", + "or_eq", + "private", + "protected", + "public", + "register", + "reinterpret_cast", + "requires", + "return", + "short", + "signed", + "sizeof", + "static", + "static_assert", + "static_cast", + "struct", + "switch", + "synchronized", + "template", + "this", + "thread_local", + "throw", + "true", + "try", + "typedef", + "typeid", + "typename", + "union", + "unsigned", + "using", + "virtual", + "void", + "volatile", + "wchar_t", + "while", + "xor", + "xor_eq", + "override", + "final", + "transaction_safe", + "transaction_safe_dynamic", + "NULL", +] as const; diff --git a/packages/quicktype-core/src/language/CPlusPlus/index.ts b/packages/quicktype-core/src/language/CPlusPlus/index.ts new file mode 100644 index 000000000..8ee7d4d66 --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/index.ts @@ -0,0 +1,2 @@ +export { CPlusPlusTargetLanguage, cPlusPlusOptions } from "./language"; +export { CPlusPlusRenderer } from "./CPlusPlusRenderer"; diff --git a/packages/quicktype-core/src/language/CPlusPlus/language.ts b/packages/quicktype-core/src/language/CPlusPlus/language.ts new file mode 100644 index 000000000..c040e2e29 --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/language.ts @@ -0,0 +1,150 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { CPlusPlusRenderer } from "./CPlusPlusRenderer"; + +// FIXME: share with CJSON +const namingStyles = { + "pascal-case": "pascal", + "underscore-case": "underscore", + "camel-case": "camel", + "upper-underscore-case": "upper-underscore", + "pascal-case-upper-acronyms": "pascal-upper-acronyms", + "camel-case-upper-acronyms": "camel-upper-acronyms", +} as const; + +export const cPlusPlusOptions = { + typeSourceStyle: new EnumOption( + "source-style", + "Source code generation type, whether to generate single or multiple source files", + { + "single-source": true, + "multi-source": false, + } as const, + "single-source", + "secondary", + ), + includeLocation: new EnumOption( + "include-location", + "Whether json.hpp is to be located globally or locally", + { + "local-include": true, + "global-include": false, + } as const, + "local-include", + "secondary", + ), + codeFormat: new EnumOption( + "code-format", + "Generate classes with getters/setters, instead of structs", + { + "with-struct": false, + "with-getter-setter": true, + } as const, + "with-getter-setter", + ), + wstring: new EnumOption( + "wstring", + "Store strings using Utf-16 std::wstring, rather than Utf-8 std::string", + { + "use-string": false, + "use-wstring": true, + } as const, + "use-string", + ), + westConst: new EnumOption( + "const-style", + "Put const to the left/west (const T) or right/east (T const)", + { + "west-const": true, + "east-const": false, + } as const, + "west-const", + ), + justTypes: new BooleanOption("just-types", "Plain types only", false), + namespace: new StringOption( + "namespace", + "Name of the generated namespace(s)", + "NAME", + "quicktype", + ), + enumType: new StringOption( + "enum-type", + "Type of enum class", + "NAME", + "int", + "secondary", + ), + typeNamingStyle: new EnumOption( + "type-style", + "Naming style for types", + namingStyles, + "pascal-case", + ), + memberNamingStyle: new EnumOption( + "member-style", + "Naming style for members", + namingStyles, + "underscore-case", + ), + enumeratorNamingStyle: new EnumOption( + "enumerator-style", + "Naming style for enumerators", + namingStyles, + "upper-underscore-case", + ), + boost: new BooleanOption( + "boost", + "Require a dependency on boost. Without boost, C++17 is required", + true, + ), + hideNullOptional: new BooleanOption( + "hide-null-optional", + "Hide null value for optional field", + false, + ), +}; + +export const cPlusPlusLanguageConfig = { + displayName: "C++", + names: ["c++", "cpp", "cplusplus"], + extension: "cpp", +} as const; + +export class CPlusPlusTargetLanguage extends TargetLanguage< + typeof cPlusPlusLanguageConfig +> { + public constructor() { + super(cPlusPlusLanguageConfig); + } + + public getOptions(): typeof cPlusPlusOptions { + return cPlusPlusOptions; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): CPlusPlusRenderer { + return new CPlusPlusRenderer( + this, + renderContext, + getOptionValues(cPlusPlusOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/CPlusPlus/utils.ts b/packages/quicktype-core/src/language/CPlusPlus/utils.ts new file mode 100644 index 000000000..51a7d66cb --- /dev/null +++ b/packages/quicktype-core/src/language/CPlusPlus/utils.ts @@ -0,0 +1,222 @@ +import { + type MinMaxConstraint, + minMaxLengthForType, + minMaxValueForType, + patternForType, +} from "../../attributes/Constraints"; +import type { Name } from "../../Naming"; +import type { Sourcelike } from "../../Source"; +import { + isAscii, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, +} from "../../support/Strings"; +import type { Type, TypeKind } from "../../Type"; + +export function constraintsForType(t: Type): + | { + minMax?: MinMaxConstraint; + minMaxLength?: MinMaxConstraint; + pattern?: string; + } + | undefined { + const minMax = minMaxValueForType(t); + const minMaxLength = minMaxLengthForType(t); + const pattern = patternForType(t); + if ( + minMax === undefined && + minMaxLength === undefined && + pattern === undefined + ) + return undefined; + return { minMax, minMaxLength, pattern }; +} + +export const legalizeName = legalizeCharacters( + (cp) => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp), +); + +/// Type to use as an optional if cycle breaking is required +export const optionalAsSharedType = "std::shared_ptr"; +/// Factory to use when creating an optional if cycle breaking is required +export const optionalFactoryAsSharedType = "std::make_shared"; + +/** + * To be able to support circles in multiple files - + * e.g. class#A using class#B using class#A (obviously not directly, + * but in vector or in variant) we can forward declare them; + */ +export enum IncludeKind { + ForwardDeclare = "ForwardDeclare", + Include = "Include", +} + +// FIXME: make these string enums eventually +export enum GlobalNames { + ClassMemberConstraints = 1, + ClassMemberConstraintException = 2, + ValueTooLowException = 3, + ValueTooHighException = 4, + ValueTooShortException = 5, + ValueTooLongException = 6, + InvalidPatternException = 7, + CheckConstraint = 8, +} + +// FIXME: make these string enums eventually +export enum MemberNames { + MinIntValue = 1, + GetMinIntValue = 2, + SetMinIntValue = 3, + MaxIntValue = 4, + GetMaxIntValue = 5, + SetMaxIntValue = 6, + MinDoubleValue = 7, + GetMinDoubleValue = 8, + SetMinDoubleValue = 9, + MaxDoubleValue = 10, + GetMaxDoubleValue = 11, + SetMaxDoubleValue = 12, + MinLength = 13, + GetMinLength = 14, + SetMinLength = 15, + MaxLength = 16, + GetMaxLength = 17, + SetMaxLength = 18, + Pattern = 19, + GetPattern = 20, + SetPattern = 21, +} + +export interface ConstraintMember { + cppConstType?: string; + cppType: string; + getter: MemberNames; + name: MemberNames; + setter: MemberNames; +} + +export interface IncludeRecord { + kind: IncludeKind | undefined /** How to include that */; + typeKind: TypeKind | undefined /** What exactly to include */; +} + +export interface TypeRecord { + forceInclude: boolean; + level: number; + name: Name; + type: Type; + variant: boolean; +} + +/** + * We map each and every unique type to a include kind, e.g. how + * to include the given type + */ +export type IncludeMap = Map; + +export interface TypeContext { + inJsonNamespace: boolean; + needsForwardIndirection: boolean; + needsOptionalIndirection: boolean; +} + +export interface StringType { + createStringLiteral: (inner: Sourcelike) => Sourcelike; + emitHelperFunctions: () => void; + getConstType: () => string; + getRegex: () => string; + getSMatch: () => string; + getType: () => string; + wrapEncodingChange: ( + qualifier: Sourcelike[], + fromType: Sourcelike, + toType: Sourcelike, + inner: Sourcelike, + ) => Sourcelike; + wrapToString: (inner: Sourcelike) => Sourcelike; +} + +export function addQualifier( + qualifier: Sourcelike, + qualified: Sourcelike[], +): Sourcelike[] { + if (qualified.length === 0) { + return []; + } + + return [qualifier, qualified]; +} + +export class WrappingCode { + public constructor( + private readonly start: Sourcelike[], + private readonly end: Sourcelike[], + ) {} + + public wrap(qualifier: Sourcelike, inner: Sourcelike): Sourcelike { + return [addQualifier(qualifier, this.start), inner, this.end]; + } +} + +export class BaseString { + public _stringType: string; + + public _constStringType: string; + + public _smatch: string; + + public _regex: string; + + public _stringLiteralPrefix: string; + + public _toString: WrappingCode; + + public _encodingClass: Sourcelike; + + public _encodingFunction: Sourcelike; + + public constructor( + stringType: string, + constStringType: string, + smatch: string, + regex: string, + stringLiteralPrefix: string, + toString: WrappingCode, + encodingClass: string, + encodingFunction: string, + ) { + this._stringType = stringType; + this._constStringType = constStringType; + this._smatch = smatch; + this._regex = regex; + this._stringLiteralPrefix = stringLiteralPrefix; + this._toString = toString; + this._encodingClass = encodingClass; + this._encodingFunction = encodingFunction; + } + + public getType(): string { + return this._stringType; + } + + public getConstType(): string { + return this._constStringType; + } + + public getSMatch(): string { + return this._smatch; + } + + public getRegex(): string { + return this._regex; + } + + public createStringLiteral(inner: Sourcelike): Sourcelike { + return [this._stringLiteralPrefix, '"', inner, '"']; + } + + public wrapToString(inner: Sourcelike): Sourcelike { + return this._toString.wrap([], inner); + } +} diff --git a/packages/quicktype-core/src/language/CSharp.ts b/packages/quicktype-core/src/language/CSharp.ts deleted file mode 100644 index f58132fd6..000000000 --- a/packages/quicktype-core/src/language/CSharp.ts +++ /dev/null @@ -1,2309 +0,0 @@ -import { arrayIntercalate } from "collection-utils"; - -import { - Type, - EnumType, - UnionType, - ClassType, - ClassProperty, - ArrayType, - TransformedStringTypeKind, - PrimitiveStringTypeKind, - PrimitiveType -} from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion, directlyReachableSingleNamedType } from "../TypeUtils"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { - utf16LegalizeCharacters, - utf16StringEscape, - splitIntoWords, - combineWords, - firstUpperWordStyle, - camelCase -} from "../support/Strings"; -import { defined, assert, panic, assertNever } from "../support/Support"; -import { Name, DependencyName, Namer, funPrefixNamer, SimpleName } from "../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo, inferredNameOrder } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; -import { StringOption, EnumOption, Option, BooleanOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { StringTypeMapping } from "../TypeBuilder"; -import { - followTargetType, - transformationForType, - Transformer, - DecodingTransformer, - DecodingChoiceTransformer, - UnionInstantiationTransformer, - ChoiceTransformer, - UnionMemberMatchTransformer, - EncodingTransformer, - StringMatchTransformer, - StringProducerTransformer, - ParseStringTransformer, - StringifyTransformer, - Transformation, - ArrayDecodingTransformer, - ArrayEncodingTransformer, - MinMaxLengthCheckTransformer, - MinMaxValueTransformer -} from "../Transformers"; -import { RenderContext } from "../Renderer"; -import { minMaxLengthForType, minMaxValueForType } from "../attributes/Constraints"; -import unicode from "unicode-properties"; - -export enum Framework { - Newtonsoft, - SystemTextJson -} - -export type Version = 5 | 6; -export type OutputFeatures = { helpers: boolean; attributes: boolean }; - -export enum AccessModifier { - None, - Public, - Internal -} - -export type CSharpTypeForAny = "object" | "dynamic"; - -function noFollow(t: Type): Type { - return t; -} - -function needTransformerForType(t: Type): "automatic" | "manual" | "nullable" | "none" { - if (t instanceof UnionType) { - const maybeNullable = nullableFromUnion(t); - if (maybeNullable === null) return "automatic"; - if (needTransformerForType(maybeNullable) === "manual") return "nullable"; - return "none"; - } - if (t instanceof ArrayType) { - const itemsNeed = needTransformerForType(t.items); - if (itemsNeed === "manual" || itemsNeed === "nullable") return "automatic"; - return "none"; - } - if (t instanceof EnumType) return "automatic"; - if (t.kind === "double") return minMaxValueForType(t) !== undefined ? "manual" : "none"; - if (t.kind === "integer-string" || t.kind === "bool-string") return "manual"; - if (t.kind === "string") { - return minMaxLengthForType(t) !== undefined ? "manual" : "none"; - } - return "none"; -} - -function alwaysApplyTransformation(xf: Transformation): boolean { - const t = xf.targetType; - if (t instanceof EnumType) return true; - if (t instanceof UnionType) return nullableFromUnion(t) === null; - return false; -} - -/** - * The C# type for a given transformed string type. - */ -function csTypeForTransformedStringType(t: PrimitiveType): Sourcelike { - switch (t.kind) { - case "date-time": - return "DateTimeOffset"; - case "uuid": - return "Guid"; - case "uri": - return "Uri"; - default: - return panic(`Transformed string type ${t.kind} not supported`); - } -} - -export const cSharpOptions = { - framework: new EnumOption( - "framework", - "Serialization framework", - [ - ["NewtonSoft", Framework.Newtonsoft], - ["SystemTextJson", Framework.SystemTextJson] - ], - "NewtonSoft" - ), - useList: new EnumOption("array-type", "Use T[] or List", [ - ["array", false], - ["list", true] - ]), - dense: new EnumOption( - "density", - "Property density", - [ - ["normal", false], - ["dense", true] - ], - "normal", - "secondary" - ), - // FIXME: Do this via a configurable named eventually. - namespace: new StringOption("namespace", "Generated namespace", "NAME", "QuickType"), - version: new EnumOption( - "csharp-version", - "C# version", - [ - ["5", 5], - ["6", 6] - ], - "6", - "secondary" - ), - virtual: new BooleanOption("virtual", "Generate virtual properties", false), - typeForAny: new EnumOption( - "any-type", - 'Type to use for "any"', - [ - ["object", "object"], - ["dynamic", "dynamic"] - ], - "object", - "secondary" - ), - useDecimal: new EnumOption( - "number-type", - "Type to use for numbers", - [ - ["double", false], - ["decimal", true] - ], - "double", - "secondary" - ), - features: new EnumOption("features", "Output features", [ - ["complete", { namespaces: true, helpers: true, attributes: true }], - ["attributes-only", { namespaces: true, helpers: false, attributes: true }], - ["just-types-and-namespace", { namespaces: true, helpers: false, attributes: false }], - ["just-types", { namespaces: true, helpers: false, attributes: false }] - ]), - baseclass: new EnumOption( - "base-class", - "Base class", - [ - ["EntityData", "EntityData"], - ["Object", undefined] - ], - "Object", - "secondary" - ), - checkRequired: new BooleanOption("check-required", "Fail if required properties are missing", false) -}; - -export class CSharpTargetLanguage extends TargetLanguage { - constructor() { - super("C#", ["cs", "csharp"], "cs"); - } - - protected getOptions(): Option[] { - return [ - cSharpOptions.framework, - cSharpOptions.namespace, - cSharpOptions.version, - cSharpOptions.dense, - cSharpOptions.useList, - cSharpOptions.useDecimal, - cSharpOptions.typeForAny, - cSharpOptions.virtual, - cSharpOptions.features, - cSharpOptions.baseclass, - cSharpOptions.checkRequired - ]; - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date-time"); - mapping.set("time", "date-time"); - mapping.set("date-time", "date-time"); - mapping.set("uuid", "uuid"); - mapping.set("uri", "uri"); - mapping.set("integer-string", "integer-string"); - mapping.set("bool-string", "bool-string"); - return mapping; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - needsTransformerForType(t: Type): boolean { - const need = needTransformerForType(t); - return need !== "none" && need !== "nullable"; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { - const options = getOptionValues(cSharpOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.Newtonsoft: - return new NewtonsoftCSharpRenderer( - this, - renderContext, - getOptionValues(newtonsoftCSharpOptions, untypedOptionValues) - ); - case Framework.SystemTextJson: - return new SystemTextJsonCSharpRenderer( - this, - renderContext, - getOptionValues(systemTextJsonCSharpOptions, untypedOptionValues) - ); - default: - return assertNever(options.framework); - } - } -} - -const namingFunction = funPrefixNamer("namer", csNameStyle); - -// FIXME: Make a Named? -const denseJsonPropertyName = "J"; -const denseRequiredEnumName = "R"; -const denseNullValueHandlingEnumName = "N"; - -function isStartCharacter(utf16Unit: number): boolean { - if (unicode.isAlphabetic(utf16Unit)) { - return true; - } - return utf16Unit === 0x5f; // underscore -} - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - if (["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0) { - return true; - } - return isStartCharacter(utf16Unit); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -function csNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - firstUpperWordStyle, - firstUpperWordStyle, - "", - isStartCharacter - ); -} - -function isValueType(t: Type): boolean { - if (t instanceof UnionType) { - return nullableFromUnion(t) === null; - } - return ["integer", "double", "bool", "enum", "date-time", "uuid"].indexOf(t.kind) >= 0; -} - -export class CSharpRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _csOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["QuickType", "Type", "System", "Console", "Exception", "DateTimeOffset", "Guid", "Uri"]; - } - - protected forbiddenForObjectProperties(_: ClassType, classNamed: Name): ForbiddenWordsInfo { - return { - names: [ - classNamed, - "ToString", - "GetHashCode", - "Finalize", - "Equals", - "GetType", - "MemberwiseClone", - "ReferenceEquals" - ], - includeGlobalForbidden: false - }; - } - - protected forbiddenForUnionMembers(_: UnionType, unionNamed: Name): ForbiddenWordsInfo { - return { names: [unionNamed], includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return namingFunction; - } - - protected namerForObjectProperty(): Namer { - return namingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return namingFunction; - } - - protected makeEnumCaseNamer(): Namer { - return namingFunction; - } - - protected unionNeedsName(u: UnionType): boolean { - return nullableFromUnion(u) === null; - } - - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { - // If the top-level type doesn't contain any classes or unions - // we have to define a class just for the `FromJson` method, in - // emitFromJsonForTopLevel. - return directlyReachableSingleNamedType(type); - } - - protected emitBlock(f: () => void, semicolon = false): void { - this.emitLine("{"); - this.indent(f); - this.emitLine("}", semicolon ? ";" : ""); - } - - protected get doubleType(): string { - return this._csOptions.useDecimal ? "decimal" : "double"; - } - - protected csType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { - const actualType = follow(t); - return matchType( - actualType, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, this._csOptions.typeForAny), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, this._csOptions.typeForAny), - _boolType => "bool", - _integerType => "long", - _doubleType => this.doubleType, - _stringType => "string", - arrayType => { - const itemsType = this.csType(arrayType.items, follow, withIssues); - if (this._csOptions.useList) { - return ["List<", itemsType, ">"]; - } else { - return [itemsType, "[]"]; - } - }, - classType => this.nameForNamedType(classType), - mapType => ["Dictionary"], - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return this.nullableCSType(nullable, noFollow); - return this.nameForNamedType(unionType); - }, - transformedStringType => csTypeForTransformedStringType(transformedStringType) - ); - } - - protected nullableCSType(t: Type, follow: (t: Type) => Type = followTargetType, withIssues = false): Sourcelike { - t = followTargetType(t); - const csType = this.csType(t, follow, withIssues); - if (isValueType(t)) { - return [csType, "?"]; - } else { - return csType; - } - } - protected baseclassForType(_t: Type): Sourcelike | undefined { - return undefined; - } - protected emitType( - description: string[] | undefined, - accessModifier: AccessModifier, - declaration: Sourcelike, - name: Sourcelike, - baseclass: Sourcelike | undefined, - emitter: () => void - ): void { - switch (accessModifier) { - case AccessModifier.Public: - declaration = ["public ", declaration]; - break; - case AccessModifier.Internal: - declaration = ["internal ", declaration]; - break; - default: - break; - } - this.emitDescription(description); - if (baseclass === undefined) { - this.emitLine(declaration, " ", name); - } else { - this.emitLine(declaration, " ", name, " : ", baseclass); - } - this.emitBlock(emitter); - } - - protected attributesForProperty( - _property: ClassProperty, - _name: Name, - _c: ClassType, - _jsonName: string - ): Sourcelike[] | undefined { - return undefined; - } - - protected propertyDefinition(property: ClassProperty, name: Name, _c: ClassType, _jsonName: string): Sourcelike { - const t = property.type; - const csType = property.isOptional - ? this.nullableCSType(t, followTargetType, true) - : this.csType(t, followTargetType, true); - - const propertyArray = ["public "]; - - if (this._csOptions.virtual) propertyArray.push("virtual "); - - return [...propertyArray, csType, " ", name, " { get; set; }"]; - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - const start = "/// "; - if (this._csOptions.dense) { - this.emitLine(start, lines.join("; "), ""); - } else { - this.emitCommentLines(lines, "/// ", start, "/// "); - } - } - - protected blankLinesBetweenAttributes(): boolean { - return false; - } - - private emitClassDefinition(c: ClassType, className: Name): void { - this.emitType( - this.descriptionForType(c), - AccessModifier.Public, - "partial class", - className, - this.baseclassForType(c), - () => { - if (c.getProperties().size === 0) return; - const blankLines = this.blankLinesBetweenAttributes() ? "interposing" : "none"; - let columns: Sourcelike[][] = []; - let isFirstProperty = true; - let previousDescription: string[] | undefined = undefined; - this.forEachClassProperty(c, blankLines, (name, jsonName, p) => { - const attributes = this.attributesForProperty(p, name, c, jsonName); - const description = this.descriptionForClassProperty(c, jsonName); - const property = this.propertyDefinition(p, name, c, jsonName); - if (attributes === undefined) { - if ( - // Descriptions should be preceded by an empty line - (!isFirstProperty && description !== undefined) || - // If the previous property has a description, leave an empty line - previousDescription !== undefined - ) { - this.ensureBlankLine(); - } - this.emitDescription(description); - this.emitLine(property); - } else if (this._csOptions.dense && attributes.length > 0) { - const comment = description === undefined ? "" : ` // ${description.join("; ")}`; - columns.push([attributes, " ", property, comment]); - } else { - this.emitDescription(description); - for (const attribute of attributes) { - this.emitLine(attribute); - } - this.emitLine(property); - } - - isFirstProperty = false; - previousDescription = description; - }); - if (columns.length > 0) { - this.emitTable(columns); - } - } - ); - } - - private emitUnionDefinition(u: UnionType, unionName: Name): void { - const nonNulls = removeNullFromUnion(u, true)[1]; - this.emitType( - this.descriptionForType(u), - AccessModifier.Public, - "partial struct", - unionName, - this.baseclassForType(u), - () => { - this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { - const csType = this.nullableCSType(t); - this.emitLine("public ", csType, " ", fieldName, ";"); - }); - this.ensureBlankLine(); - const nullTests: Sourcelike[] = Array.from(nonNulls).map(t => [ - this.nameForUnionMember(u, t), - " == null" - ]); - this.ensureBlankLine(); - this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { - const csType = this.csType(t); - this.emitExpressionMember( - ["public static implicit operator ", unionName, "(", csType, " ", fieldName, ")"], - ["new ", unionName, " { ", fieldName, " = ", fieldName, " }"] - ); - }); - if (u.findMember("null") === undefined) return; - this.emitExpressionMember("public bool IsNull", arrayIntercalate(" && ", nullTests), true); - } - ); - } - - private emitEnumDefinition(e: EnumType, enumName: Name): void { - const caseNames: Sourcelike[] = []; - this.forEachEnumCase(e, "none", name => { - if (caseNames.length > 0) caseNames.push(", "); - caseNames.push(name); - }); - this.emitDescription(this.descriptionForType(e)); - this.emitLine("public enum ", enumName, " { ", caseNames, " };"); - } - - protected emitExpressionMember(declare: Sourcelike, define: Sourcelike, isProperty = false): void { - if (this._csOptions.version === 5) { - this.emitLine(declare); - this.emitBlock(() => { - const stmt = ["return ", define, ";"]; - if (isProperty) { - this.emitLine("get"); - this.emitBlock(() => this.emitLine(stmt)); - } else { - this.emitLine(stmt); - } - }); - } else { - this.emitLine(declare, " => ", define, ";"); - } - } - - protected emitTypeSwitch( - types: Iterable, - condition: (t: T) => Sourcelike, - withBlock: boolean, - withReturn: boolean, - f: (t: T) => void - ): void { - assert(!withReturn || withBlock, "Can only have return with block"); - for (const t of types) { - this.emitLine("if (", condition(t), ")"); - if (withBlock) { - this.emitBlock(() => { - f(t); - if (withReturn) { - this.emitLine("return;"); - } - }); - } else { - this.indent(() => f(t)); - } - } - } - - protected emitUsing(ns: Sourcelike): void { - this.emitLine("using ", ns, ";"); - } - - protected emitUsings(): void { - for (const ns of ["System", "System.Collections.Generic"]) { - this.emitUsing(ns); - } - } - - protected emitRequiredHelpers(): void { - return; - } - - private emitTypesAndSupport(): void { - this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitClassDefinition(c, name)); - this.forEachEnum("leading-and-interposing", (e, name) => this.emitEnumDefinition(e, name)); - this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnionDefinition(u, name)); - this.emitRequiredHelpers(); - } - - protected emitDefaultLeadingComments(): void { - return; - } - - protected emitDefaultFollowingComments(): void { - return; - } - - protected needNamespace(): boolean { - return true; - } - - protected emitSourceStructure(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else { - this.emitDefaultLeadingComments(); - } - - this.ensureBlankLine(); - if (this.needNamespace()) { - this.emitLine("namespace ", this._csOptions.namespace); - this.emitBlock(() => { - this.emitUsings(); - this.emitTypesAndSupport(); - }); - } else { - this.emitUsings(); - this.emitTypesAndSupport(); - } - - this.emitDefaultFollowingComments(); - } -} - -export const newtonsoftCSharpOptions = Object.assign({}, cSharpOptions, {}); - -export class NewtonsoftCSharpRenderer extends CSharpRenderer { - private readonly _enumExtensionsNames = new Map(); - - private readonly _needHelpers: boolean; - private readonly _needAttributes: boolean; - private readonly _needNamespaces: boolean; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext, _options); - this._needHelpers = _options.features.helpers; - this._needAttributes = _options.features.attributes; - this._needNamespaces = _options.features.namespaces; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - const forbidden = [ - "Converter", - "JsonConverter", - "JsonSerializer", - "JsonWriter", - "JsonToken", - "Serialize", - "Newtonsoft", - "MetadataPropertyHandling", - "DateParseHandling", - "FromJson", - "Required" - ]; - if (this._options.dense) { - forbidden.push("J", "R", "N"); - } - if (this._options.baseclass !== undefined) { - forbidden.push(this._options.baseclass); - } - return super.forbiddenNamesForGlobalNamespace().concat(forbidden); - } - - protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { - const result = super.forbiddenForObjectProperties(c, className); - result.names = result.names.concat(["ToJson", "FromJson", "Required"]); - return result; - } - - protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { - if (typeName === undefined) { - let xfer = xf.transformer; - if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { - xfer = xfer.consumer; - } - return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); - } - return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); - } - - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { - if (!(t instanceof EnumType)) return []; - - const extensionsName = new DependencyName( - namingFunction, - name.order + 30, - lookup => `${lookup(name)}_extensions` - ); - this._enumExtensionsNames.set(name, extensionsName); - return [extensionsName]; - } - - protected emitUsings(): void { - // FIXME: We need System.Collections.Generic whenever we have maps or use List. - if (!this._needAttributes && !this._needHelpers) return; - - super.emitUsings(); - this.ensureBlankLine(); - - for (const ns of ["System.Globalization", "Newtonsoft.Json", "Newtonsoft.Json.Converters"]) { - this.emitUsing(ns); - } - - if (this._options.dense) { - this.emitUsing([denseJsonPropertyName, " = Newtonsoft.Json.JsonPropertyAttribute"]); - this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); - this.emitUsing([denseNullValueHandlingEnumName, " = Newtonsoft.Json.NullValueHandling"]); - } - if (this._options.baseclass === "EntityData") { - this.emitUsing("Microsoft.Azure.Mobile.Server"); - } - } - protected baseclassForType(_t: Type): Sourcelike | undefined { - return this._options.baseclass; - } - protected emitDefaultLeadingComments(): void { - if (!this._needHelpers) return; - - this.emitLine("// "); - this.emitLine("//"); - this.emitLine( - "// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do", - this.topLevels.size === 1 ? "" : " one of these", - ":" - ); - this.emitLine("//"); - this.emitLine("// using ", this._options.namespace, ";"); - this.emitLine("//"); - this.forEachTopLevel("none", (t, topLevelName) => { - let rhs: Sourcelike; - if (t instanceof EnumType) { - rhs = ["JsonConvert.DeserializeObject<", topLevelName, ">(jsonString)"]; - } else { - rhs = [topLevelName, ".FromJson(jsonString)"]; - } - this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); - }); - } - - private converterForType(t: Type): Name | undefined { - let xf = transformationForType(t); - - if (xf === undefined && t instanceof UnionType) { - const maybeNullable = nullableFromUnion(t); - if (maybeNullable !== null) { - t = maybeNullable; - xf = transformationForType(t); - } - } - - if (xf === undefined) return undefined; - - if (alwaysApplyTransformation(xf)) return undefined; - - return defined(this.nameForTransformation(t)); - } - - protected attributesForProperty( - property: ClassProperty, - _name: Name, - _c: ClassType, - jsonName: string - ): Sourcelike[] | undefined { - if (!this._needAttributes) return undefined; - - const attributes: Sourcelike[] = []; - - const jsonProperty = this._options.dense ? denseJsonPropertyName : "JsonProperty"; - const escapedName = utf16StringEscape(jsonName); - const isNullable = followTargetType(property.type).isNullable; - const isOptional = property.isOptional; - const requiredClass = this._options.dense ? "R" : "Required"; - const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; - const nullValueHandling = - isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; - let required: Sourcelike; - if (!this._options.checkRequired || (isOptional && isNullable)) { - required = [nullValueHandling]; - } else if (isOptional && !isNullable) { - required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; - } else if (!isOptional && isNullable) { - required = [", Required = ", requiredClass, ".AllowNull"]; - } else { - required = [", Required = ", requiredClass, ".Always", nullValueHandling]; - } - attributes.push(["[", jsonProperty, '("', escapedName, '"', required, ")]"]); - - const converter = this.converterForType(property.type); - if (converter !== undefined) { - attributes.push(["[JsonConverter(typeof(", converter, "))]"]); - } - - return attributes; - } - - protected blankLinesBetweenAttributes(): boolean { - return this._needAttributes && !this._options.dense; - } - - // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType(t: Type): Sourcelike { - return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); - } - - private emitFromJsonForTopLevel(t: Type, name: Name): void { - if (t instanceof EnumType) return; - - let partial: string; - let typeKind: string; - const definedType = this.namedTypeToNameForTopLevel(t); - if (definedType !== undefined) { - partial = "partial "; - typeKind = definedType instanceof ClassType ? "class" : "struct"; - } else { - partial = ""; - typeKind = "class"; - } - const csType = this.topLevelResultType(t); - this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { - // FIXME: Make FromJson a Named - this.emitExpressionMember( - ["public static ", csType, " FromJson(string json)"], - ["JsonConvert.DeserializeObject<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] - ); - }); - } - - private emitDecoderSwitch(emitBody: () => void): void { - this.emitLine("switch (reader.TokenType)"); - this.emitBlock(emitBody); - } - - private emitTokenCase(tokenType: string): void { - this.emitLine("case JsonToken.", tokenType, ":"); - } - - private emitThrow(message: Sourcelike): void { - this.emitLine("throw new Exception(", message, ");"); - } - - private deserializeTypeCode(typeName: Sourcelike): Sourcelike { - return ["serializer.Deserialize<", typeName, ">(reader)"]; - } - - private serializeValueCode(value: Sourcelike): Sourcelike { - return ["serializer.Serialize(writer, ", value, ")"]; - } - - private emitSerializeClass(): void { - // FIXME: Make Serialize a Named - this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { - // Sometimes multiple top-levels will resolve to the same type, so we have to take care - // not to emit more than one extension method for the same type. - const seenTypes = new Set(); - this.forEachTopLevel("none", t => { - // FIXME: Make ToJson a Named - if (!seenTypes.has(t)) { - seenTypes.add(t); - this.emitExpressionMember( - ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonConvert.SerializeObject(self, ", this._options.namespace, ".Converter.Settings)"] - ); - } - }); - }); - } - - private emitCanConvert(expr: Sourcelike): void { - this.emitExpressionMember("public override bool CanConvert(Type t)", expr); - } - - private emitReadJson(emitBody: () => void): void { - this.emitLine( - "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)" - ); - this.emitBlock(emitBody); - } - - private emitWriteJson(variable: string, emitBody: () => void): void { - this.emitLine( - "public override void WriteJson(JsonWriter writer, object ", - variable, - ", JsonSerializer serializer)" - ); - this.emitBlock(emitBody); - } - - private converterObject(converterName: Name): Sourcelike { - // FIXME: Get a singleton - return [converterName, ".Singleton"]; - } - - private emitConverterClass(): void { - // FIXME: Make Converter a Named - const converterName: Sourcelike = ["Converter"]; - this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { - this.emitLine("public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings"); - this.emitBlock(() => { - this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); - this.emitLine("DateParseHandling = DateParseHandling.None,"); - this.emitLine("Converters ="); - this.emitLine("{"); - this.indent(() => { - for (const [t, converter] of this.typesWithNamedTransformations) { - if (alwaysApplyTransformation(defined(transformationForType(t)))) { - this.emitLine(this.converterObject(converter), ","); - } - } - this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); - }); - this.emitLine(`},`); - }, true); - }); - } - - private emitDecoderTransformerCase( - tokenCases: string[], - variableName: string, - xfer: Transformer | undefined, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): void { - if (xfer === undefined) return; - - for (const tokenCase of tokenCases) { - this.emitTokenCase(tokenCase); - } - this.indent(() => { - const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); - if (!allHandled) { - this.emitLine("break;"); - } - }); - } - - private emitConsume( - value: Sourcelike, - consumer: Transformer | undefined, - targetType: Type, - emitFinish: (variableName: Sourcelike) => void - ): boolean { - if (consumer === undefined) { - emitFinish(value); - return true; - } else { - return this.emitTransformer(value, consumer, targetType, emitFinish); - } - } - - private emitDecodeTransformer( - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void, - variableName = "value" - ): boolean { - if (xfer instanceof DecodingTransformer) { - const source = xfer.sourceType; - const converter = this.converterForType(targetType); - if (converter !== undefined) { - const typeSource = this.csType(targetType); - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine( - "var ", - variableName, - " = (", - typeSource, - ")converter.ReadJson(reader, typeof(", - typeSource, - "), null, serializer);" - ); - } else if (source.kind !== "null") { - let output = targetType.kind === "double" ? targetType : source; - this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); - } - return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof ArrayDecodingTransformer) { - // FIXME: Consume StartArray - if (!(targetType instanceof ArrayType)) { - return panic("Array decoding must produce an array type"); - } - // FIXME: handle EOF - this.emitLine("reader.Read();"); - this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); - this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); - this.emitBlock(() => { - this.emitDecodeTransformer( - xfer.itemTransformer, - xfer.itemTargetType, - v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem" - ); - // FIXME: handle EOF - this.emitLine("reader.Read();"); - }); - let result: Sourcelike = variableName; - if (!this._options.useList) { - result = [result, ".ToArray()"]; - } - emitFinish(result); - return true; - } else if (xfer instanceof DecodingChoiceTransformer) { - this.emitDecoderSwitch(() => { - const nullTransformer = xfer.nullTransformer; - if (nullTransformer !== undefined) { - this.emitTokenCase("Null"); - this.indent(() => { - const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null"); - if (!allHandled) { - this.emitLine("break"); - } - }); - } - this.emitDecoderTransformerCase( - ["Integer"], - "integerValue", - xfer.integerTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], - "doubleValue", - xfer.doubleTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase(["Boolean"], "boolValue", xfer.boolTransformer, targetType, emitFinish); - this.emitDecoderTransformerCase( - ["String", "Date"], - "stringValue", - xfer.stringTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartObject"], - "objectValue", - xfer.objectTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartArray"], - "arrayValue", - xfer.arrayTransformer, - targetType, - emitFinish - ); - }); - return false; - } else { - return panic("Unknown transformer"); - } - } - - private stringCaseValue(t: Type, stringCase: string): Sourcelike { - if (t.kind === "string") { - return ['"', utf16StringEscape(stringCase), '"']; - } else if (t instanceof EnumType) { - return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; - } - return panic(`Type ${t.kind} does not have string cases`); - } - - private emitTransformer( - variable: Sourcelike, - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): boolean { - function directTargetType(continuation: Transformer | undefined): Type { - if (continuation === undefined) { - return targetType; - } - return followTargetType(continuation.sourceType); - } - - if (xfer instanceof ChoiceTransformer) { - const caseXfers = xfer.transformers; - if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof StringMatchTransformer)) { - this.emitLine("switch (", variable, ")"); - this.emitBlock(() => { - for (const caseXfer of caseXfers) { - const matchXfer = caseXfer as StringMatchTransformer; - const value = this.stringCaseValue( - followTargetType(matchXfer.sourceType), - matchXfer.stringCase - ); - this.emitLine("case ", value, ":"); - this.indent(() => { - const allDone = this.emitTransformer( - variable, - matchXfer.transformer, - targetType, - emitFinish - ); - if (!allDone) { - this.emitLine("break;"); - } - }); - } - }); - // FIXME: Can we check for exhaustiveness? For enums it should be easy. - return false; - } else { - for (const caseXfer of caseXfers) { - this.emitTransformer(variable, caseXfer, targetType, emitFinish); - } - } - } else if (xfer instanceof UnionMemberMatchTransformer) { - const memberType = xfer.memberType; - const maybeNullable = nullableFromUnion(xfer.sourceType); - let test: Sourcelike; - let member: Sourcelike; - if (maybeNullable !== null) { - if (memberType.kind === "null") { - test = [variable, " == null"]; - member = "null"; - } else { - test = [variable, " != null"]; - member = variable; - } - } else if (memberType.kind === "null") { - test = [variable, ".IsNull"]; - member = "null"; - } else { - const memberName = this.nameForUnionMember(xfer.sourceType, memberType); - member = [variable, ".", memberName]; - test = [member, " != null"]; - } - if (memberType.kind !== "null" && isValueType(memberType)) { - member = [member, ".Value"]; - } - this.emitLine("if (", test, ")"); - this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof StringMatchTransformer) { - const value = this.stringCaseValue(followTargetType(xfer.sourceType), xfer.stringCase); - this.emitLine("if (", variable, " == ", value, ")"); - this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof EncodingTransformer) { - const converter = this.converterForType(xfer.sourceType); - if (converter !== undefined) { - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);"); - } else { - this.emitLine(this.serializeValueCode(variable), ";"); - } - emitFinish([]); - return true; - } else if (xfer instanceof ArrayEncodingTransformer) { - this.emitLine("writer.WriteStartArray();"); - const itemVariable = "arrayItem"; - this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); - this.emitBlock(() => { - this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => { - return; - }); - }); - this.emitLine("writer.WriteEndArray();"); - emitFinish([]); - return true; - } else if (xfer instanceof ParseStringTransformer) { - const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType; - switch (immediateTargetType.kind) { - case "date-time": - this.emitLine("DateTimeOffset dt;"); - this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))"); - this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish)); - break; - case "uuid": - this.emitLine("Guid guid;"); - this.emitLine("if (Guid.TryParse(", variable, ", out guid))"); - this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish)); - break; - case "uri": - this.emitLine("try"); - this.emitBlock(() => { - this.emitLine("var uri = new Uri(", variable, ");"); - this.emitConsume("uri", xfer.consumer, targetType, emitFinish); - }); - this.emitLine("catch (UriFormatException) {}"); - break; - case "integer": - this.emitLine("long l;"); - this.emitLine("if (Int64.TryParse(", variable, ", out l))"); - this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish)); - break; - case "bool": - this.emitLine("bool b;"); - this.emitLine("if (Boolean.TryParse(", variable, ", out b))"); - this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish)); - break; - default: - return panic(`Parsing string to ${immediateTargetType.kind} not supported`); - } - } else if (xfer instanceof StringifyTransformer) { - switch (xfer.sourceType.kind) { - case "date-time": - return this.emitConsume( - [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "uuid": - return this.emitConsume( - [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "integer": - case "uri": - return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); - case "bool": - this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); - return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); - default: - return panic(`Stringifying ${xfer.sourceType.kind} not supported`); - } - } else if (xfer instanceof StringProducerTransformer) { - const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result); - return this.emitConsume(value, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof MinMaxLengthCheckTransformer) { - const min = xfer.minLength; - const max = xfer.maxLength; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, ".Length >= ", min.toString()]); - } - if (max !== undefined) { - conditions.push([variable, ".Length <= ", max.toString()]); - } - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof MinMaxValueTransformer) { - const min = xfer.minimum; - const max = xfer.maximum; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, " >= ", min.toString()]); - } - if (max !== undefined) { - conditions.push([variable, " <= ", max.toString()]); - } - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof UnionInstantiationTransformer) { - if (!(targetType instanceof UnionType)) { - return panic("Union instantiation transformer must produce a union type"); - } - const maybeNullable = nullableFromUnion(targetType); - if (maybeNullable !== null) { - emitFinish(variable); - } else { - const unionName = this.nameForNamedType(targetType); - let initializer: Sourcelike; - if (xfer.sourceType.kind === "null") { - initializer = " "; - } else { - const memberName = this.nameForUnionMember(targetType, xfer.sourceType); - initializer = [" ", memberName, " = ", variable, " "]; - } - emitFinish(["new ", unionName, " {", initializer, "}"]); - } - return true; - } else { - return panic("Unknown transformer"); - } - return false; - } - - private emitTransformation(converterName: Name, t: Type): void { - const xf = defined(transformationForType(t)); - const reverse = xf.reverse; - const targetType = xf.targetType; - const xfer = xf.transformer; - this.emitType(undefined, AccessModifier.Internal, "class", converterName, "JsonConverter", () => { - const csType = this.csType(targetType); - let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; - const haveNullable = isValueType(targetType); - if (haveNullable) { - canConvertExpr = [canConvertExpr, " || t == typeof(", csType, "?)"]; - } - this.emitCanConvert(canConvertExpr); - this.ensureBlankLine(); - this.emitReadJson(() => { - // FIXME: It's unsatisfying that we need this. The reason is that we not - // only match T, but also T?. If we didn't, then the T in T? would not be - // deserialized with our converter but with the default one. Can we check - // whether the type is a nullable? - // FIXME: This could duplicate one of the cases handled below in - // `emitDecodeTransformer`. - if (haveNullable && !(targetType instanceof UnionType)) { - this.emitLine("if (reader.TokenType == JsonToken.Null) return null;"); - } - - const allHandled = this.emitDecodeTransformer(xfer, targetType, v => this.emitLine("return ", v, ";")); - if (!allHandled) { - this.emitThrow(['"Cannot unmarshal type ', csType, '"']); - } - }); - this.ensureBlankLine(); - this.emitWriteJson("untypedValue", () => { - // FIXME: See above. - if (haveNullable && !(targetType instanceof UnionType)) { - this.emitLine("if (untypedValue == null)"); - this.emitBlock(() => { - this.emitLine("serializer.Serialize(writer, null);"); - this.emitLine("return;"); - }); - } - this.emitLine("var value = (", csType, ")untypedValue;"); - const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;") - ); - if (!allHandled) { - this.emitThrow(['"Cannot marshal type ', csType, '"']); - } - }); - this.ensureBlankLine(); - this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); - }); - } - - protected emitRequiredHelpers(): void { - if (this._needHelpers) { - this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); - this.ensureBlankLine(); - this.emitSerializeClass(); - } - if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { - this.ensureBlankLine(); - this.emitConverterClass(); - this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); - } - } - - protected needNamespace(): boolean { - return this._needNamespaces; - } -} - -export const systemTextJsonCSharpOptions = Object.assign({}, cSharpOptions, {}); - -export class SystemTextJsonCSharpRenderer extends CSharpRenderer { - private readonly _enumExtensionsNames = new Map(); - - private readonly _needHelpers: boolean; - private readonly _needAttributes: boolean; - private readonly _needNamespaces: boolean; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext, _options); - this._needHelpers = _options.features.helpers; - this._needAttributes = _options.features.attributes; - this._needNamespaces = _options.features.namespaces; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - const forbidden = [ - "Converter", - "JsonConverter", - "JsonSerializer", - "JsonWriter", - "JsonToken", - "Serialize", - "JsonSerializerOptions", - // "Newtonsoft", - // "MetadataPropertyHandling", - // "DateParseHandling", - "FromJson", - "Required" - ]; - if (this._options.dense) { - forbidden.push("J", "R", "N"); - } - if (this._options.baseclass !== undefined) { - forbidden.push(this._options.baseclass); - } - return super.forbiddenNamesForGlobalNamespace().concat(forbidden); - } - - protected forbiddenForObjectProperties(c: ClassType, className: Name): ForbiddenWordsInfo { - const result = super.forbiddenForObjectProperties(c, className); - result.names = result.names.concat(["ToJson", "FromJson", "Required"]); - return result; - } - - protected makeNameForTransformation(xf: Transformation, typeName: Name | undefined): Name { - if (typeName === undefined) { - let xfer = xf.transformer; - if (xfer instanceof DecodingTransformer && xfer.consumer !== undefined) { - xfer = xfer.consumer; - } - return new SimpleName([`${xfer.kind}_converter`], namingFunction, inferredNameOrder + 30); - } - return new DependencyName(namingFunction, typeName.order + 30, lookup => `${lookup(typeName)}_converter`); - } - - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { - if (!(t instanceof EnumType)) return []; - - const extensionsName = new DependencyName( - namingFunction, - name.order + 30, - lookup => `${lookup(name)}_extensions` - ); - this._enumExtensionsNames.set(name, extensionsName); - return [extensionsName]; - } - - protected emitUsings(): void { - // FIXME: We need System.Collections.Generic whenever we have maps or use List. - if (!this._needAttributes && !this._needHelpers) return; - - super.emitUsings(); - this.ensureBlankLine(); - - for (const ns of ["System.Text.Json", "System.Text.Json.Serialization", "System.Globalization"]) { - this.emitUsing(ns); - } - - if (this._options.dense) { - this.emitUsing([denseJsonPropertyName, " = System.Text.Json.Serialization.JsonPropertyNameAttribute"]); - // this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); - this.emitUsing([denseNullValueHandlingEnumName, " = System.Text.Json.Serialization.JsonIgnoreCondition"]); - } - if (this._options.baseclass === "EntityData") { - this.emitUsing("Microsoft.Azure.Mobile.Server"); - } - } - - protected baseclassForType(_t: Type): Sourcelike | undefined { - return this._options.baseclass; - } - - protected emitDefaultFollowingComments(): void { - if (!this._needHelpers) return; - - this.emitLine("#pragma warning restore CS8618"); - this.emitLine("#pragma warning restore CS8601"); - this.emitLine("#pragma warning restore CS8603"); - } - - protected emitDefaultLeadingComments(): void { - if (!this._needHelpers) return; - - this.emitLine("// "); - this.emitLine("//"); - this.emitLine( - "// To parse this JSON data, add NuGet 'System.Text.Json' then do", - this.topLevels.size === 1 ? "" : " one of these", - ":" - ); - this.emitLine("//"); - this.emitLine("// using ", this._options.namespace, ";"); - this.emitLine("//"); - this.forEachTopLevel("none", (t, topLevelName) => { - let rhs: Sourcelike; - if (t instanceof EnumType) { - rhs = ["JsonSerializer.Deserialize<", topLevelName, ">(jsonString)"]; - } else { - rhs = [topLevelName, ".FromJson(jsonString)"]; - } - this.emitLine("// var ", modifySource(camelCase, topLevelName), " = ", rhs, ";"); - }); - - // fix: should this be an option? Or respond to an existing option? - this.emitLine("#nullable enable"); - this.emitLine("#pragma warning disable CS8618"); - this.emitLine("#pragma warning disable CS8601"); - this.emitLine("#pragma warning disable CS8603"); - } - - private converterForType(t: Type): Name | undefined { - let xf = transformationForType(t); - - if (xf === undefined && t instanceof UnionType) { - const maybeNullable = nullableFromUnion(t); - if (maybeNullable !== null) { - t = maybeNullable; - xf = transformationForType(t); - } - } - - if (xf === undefined) return undefined; - - if (alwaysApplyTransformation(xf)) return undefined; - - return defined(this.nameForTransformation(t)); - } - - protected attributesForProperty( - property: ClassProperty, - _name: Name, - _c: ClassType, - jsonName: string - ): Sourcelike[] | undefined { - if (!this._needAttributes) return undefined; - - const attributes: Sourcelike[] = []; - - const jsonPropertyName = this._options.dense ? denseJsonPropertyName : "JsonPropertyName"; - const escapedName = utf16StringEscape(jsonName); - const isNullable = followTargetType(property.type).isNullable; - const isOptional = property.isOptional; - - if (isOptional && !isNullable) { - attributes.push(["[", "JsonIgnore", "(Condition = JsonIgnoreCondition.WhenWritingNull)]"]); - } - - // const requiredClass = this._options.dense ? "R" : "Required"; - // const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; - // const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; - // let required: Sourcelike; - // if (!this._options.checkRequired || (isOptional && isNullable)) { - // required = [nullValueHandling]; - // } else if (isOptional && !isNullable) { - // required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; - // } else if (!isOptional && isNullable) { - // required = [", Required = ", requiredClass, ".AllowNull"]; - // } else { - // required = [", Required = ", requiredClass, ".Always", nullValueHandling]; - // } - - attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']); - - const converter = this.converterForType(property.type); - if (converter !== undefined) { - attributes.push(["[JsonConverter(typeof(", converter, "))]"]); - } - - return attributes; - } - - protected blankLinesBetweenAttributes(): boolean { - return this._needAttributes && !this._options.dense; - } - - // The "this" type can't be `dynamic`, so we have to force it to `object`. - private topLevelResultType(t: Type): Sourcelike { - return t.kind === "any" || t.kind === "none" ? "object" : this.csType(t); - } - - private emitFromJsonForTopLevel(t: Type, name: Name): void { - if (t instanceof EnumType) return; - - let partial: string; - let typeKind: string; - const definedType = this.namedTypeToNameForTopLevel(t); - if (definedType !== undefined) { - partial = "partial "; - typeKind = definedType instanceof ClassType ? "class" : "struct"; - } else { - partial = ""; - typeKind = "class"; - } - const csType = this.topLevelResultType(t); - this.emitType(undefined, AccessModifier.Public, [partial, typeKind], name, this.baseclassForType(t), () => { - // FIXME: Make FromJson a Named - this.emitExpressionMember( - ["public static ", csType, " FromJson(string json)"], - ["JsonSerializer.Deserialize<", csType, ">(json, ", this._options.namespace, ".Converter.Settings)"] - ); - }); - } - - private emitDecoderSwitch(emitBody: () => void): void { - this.emitLine("switch (reader.TokenType)"); - this.emitBlock(emitBody); - } - - private emitTokenCase(tokenType: string): void { - this.emitLine("case JsonTokenType.", tokenType, ":"); - } - - private emitThrow(message: Sourcelike): void { - this.emitLine("throw new Exception(", message, ");"); - } - - private deserializeTypeCode(typeName: Sourcelike): Sourcelike { - switch (typeName) { - case "bool": - return ["reader.GetBoolean()"]; - case "long": - return ["reader.GetInt64()"]; - case "decimal": - return ["reader.GetDecimal()"]; - case "double": - return ["reader.GetDouble()"]; - case "string": - return ["reader.GetString()"]; - default: - return ["JsonSerializer.Deserialize<", typeName, ">(ref reader, options)"]; - } - } - - private serializeValueCode(value: Sourcelike): Sourcelike { - if (value !== "null") return ["JsonSerializer.Serialize(writer, ", value, ", options)"]; - else return ["writer.WriteNullValue()"]; - } - - private emitSerializeClass(): void { - // FIXME: Make Serialize a Named - this.emitType(undefined, AccessModifier.Public, "static class", "Serialize", undefined, () => { - // Sometimes multiple top-levels will resolve to the same type, so we have to take care - // not to emit more than one extension method for the same type. - const seenTypes = new Set(); - this.forEachTopLevel("none", t => { - // FIXME: Make ToJson a Named - if (!seenTypes.has(t)) { - seenTypes.add(t); - this.emitExpressionMember( - ["public static string ToJson(this ", this.topLevelResultType(t), " self)"], - ["JsonSerializer.Serialize(self, ", this._options.namespace, ".Converter.Settings)"] - ); - } - }); - }); - } - - private emitCanConvert(expr: Sourcelike): void { - this.emitExpressionMember("public override bool CanConvert(Type t)", expr); - } - - private emitReadJson(emitBody: () => void, csType: Sourcelike): void { - this.emitLine( - "public override ", - csType, - " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)" - ); - this.emitBlock(emitBody); - } - - private emitWriteJson(variable: string, emitBody: () => void, csType: Sourcelike): void { - this.emitLine( - "public override void Write(Utf8JsonWriter writer, ", - csType, - " ", - variable, - ", JsonSerializerOptions options)" - ); - this.emitBlock(emitBody); - } - - private converterObject(converterName: Name): Sourcelike { - // FIXME: Get a singleton - return [converterName, ".Singleton"]; - } - - private emitConverterClass(): void { - // FIXME: Make Converter a Named - const converterName: Sourcelike = ["Converter"]; - this.emitType(undefined, AccessModifier.Internal, "static class", converterName, undefined, () => { - // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test. - this.emitLine( - "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)" - ); - this.emitBlock(() => { - // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); - // this.emitLine("DateParseHandling = DateParseHandling.None,"); - this.emitLine("Converters ="); - this.emitLine("{"); - this.indent(() => { - for (const [t, converter] of this.typesWithNamedTransformations) { - if (alwaysApplyTransformation(defined(transformationForType(t)))) { - this.emitLine(this.converterObject(converter), ","); - } - } - this.emitLine("new DateOnlyConverter(),"); - this.emitLine("new TimeOnlyConverter(),"); - this.emitLine("IsoDateTimeOffsetConverter.Singleton"); - // this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); - }); - this.emitLine(`},`); - }, true); - }); - } - - private emitDecoderTransformerCase( - tokenCases: string[], - variableName: string, - xfer: Transformer | undefined, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): void { - if (xfer === undefined) return; - - for (const tokenCase of tokenCases) { - this.emitTokenCase(tokenCase); - } - this.indent(() => { - const allHandled = this.emitDecodeTransformer(xfer, targetType, emitFinish, variableName); - if (!allHandled) { - this.emitLine("break;"); - } - }); - } - - private emitConsume( - value: Sourcelike, - consumer: Transformer | undefined, - targetType: Type, - emitFinish: (variableName: Sourcelike) => void - ): boolean { - if (consumer === undefined) { - emitFinish(value); - return true; - } else { - return this.emitTransformer(value, consumer, targetType, emitFinish); - } - } - - private emitDecodeTransformer( - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void, - variableName = "value" - ): boolean { - if (xfer instanceof DecodingTransformer) { - const source = xfer.sourceType; - const converter = this.converterForType(targetType); - if (converter !== undefined) { - const typeSource = this.csType(targetType); - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine( - "var ", - variableName, - " = (", - typeSource, - ")converter.ReadJson(reader, typeof(", - typeSource, - "), null, serializer);" - ); - } else if (source.kind !== "null") { - let output = targetType.kind === "double" ? targetType : source; - this.emitLine("var ", variableName, " = ", this.deserializeTypeCode(this.csType(output)), ";"); - } - return this.emitConsume(variableName, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof ArrayDecodingTransformer) { - // FIXME: Consume StartArray - if (!(targetType instanceof ArrayType)) { - return panic("Array decoding must produce an array type"); - } - // FIXME: handle EOF - this.emitLine("reader.Read();"); - this.emitLine("var ", variableName, " = new List<", this.csType(targetType.items), ">();"); - this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); - this.emitBlock(() => { - this.emitDecodeTransformer( - xfer.itemTransformer, - xfer.itemTargetType, - v => this.emitLine(variableName, ".Add(", v, ");"), - "arrayItem" - ); - // FIXME: handle EOF - this.emitLine("reader.Read();"); - }); - let result: Sourcelike = variableName; - if (!this._options.useList) { - result = [result, ".ToArray()"]; - } - emitFinish(result); - return true; - } else if (xfer instanceof DecodingChoiceTransformer) { - this.emitDecoderSwitch(() => { - const nullTransformer = xfer.nullTransformer; - if (nullTransformer !== undefined) { - this.emitTokenCase("Null"); - this.indent(() => { - const allHandled = this.emitDecodeTransformer(nullTransformer, targetType, emitFinish, "null"); - if (!allHandled) { - this.emitLine("break"); - } - }); - } - this.emitDecoderTransformerCase( - ["Number"], - "integerValue", - xfer.integerTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["Number"], - // xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], - "doubleValue", - xfer.doubleTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["True", "False"], - "boolValue", - xfer.boolTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - // ["String", "Date"], - ["String"], - "stringValue", - xfer.stringTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartObject"], - "objectValue", - xfer.objectTransformer, - targetType, - emitFinish - ); - this.emitDecoderTransformerCase( - ["StartArray"], - "arrayValue", - xfer.arrayTransformer, - targetType, - emitFinish - ); - }); - return false; - } else { - return panic("Unknown transformer"); - } - } - - private stringCaseValue(t: Type, stringCase: string): Sourcelike { - if (t.kind === "string") { - return ['"', utf16StringEscape(stringCase), '"']; - } else if (t instanceof EnumType) { - return [this.nameForNamedType(t), ".", this.nameForEnumCase(t, stringCase)]; - } - return panic(`Type ${t.kind} does not have string cases`); - } - - private emitTransformer( - variable: Sourcelike, - xfer: Transformer, - targetType: Type, - emitFinish: (value: Sourcelike) => void - ): boolean { - function directTargetType(continuation: Transformer | undefined): Type { - if (continuation === undefined) { - return targetType; - } - return followTargetType(continuation.sourceType); - } - - if (xfer instanceof ChoiceTransformer) { - const caseXfers = xfer.transformers; - if (caseXfers.length > 1 && caseXfers.every(caseXfer => caseXfer instanceof StringMatchTransformer)) { - this.emitLine("switch (", variable, ")"); - this.emitBlock(() => { - for (const caseXfer of caseXfers) { - const matchXfer = caseXfer as StringMatchTransformer; - const value = this.stringCaseValue( - followTargetType(matchXfer.sourceType), - matchXfer.stringCase - ); - this.emitLine("case ", value, ":"); - this.indent(() => { - const allDone = this.emitTransformer( - variable, - matchXfer.transformer, - targetType, - emitFinish - ); - if (!allDone) { - this.emitLine("break;"); - } - }); - } - }); - // FIXME: Can we check for exhaustiveness? For enums it should be easy. - return false; - } else { - for (const caseXfer of caseXfers) { - this.emitTransformer(variable, caseXfer, targetType, emitFinish); - } - } - } else if (xfer instanceof UnionMemberMatchTransformer) { - const memberType = xfer.memberType; - const maybeNullable = nullableFromUnion(xfer.sourceType); - let test: Sourcelike; - let member: Sourcelike; - if (maybeNullable !== null) { - if (memberType.kind === "null") { - test = [variable, " == null"]; - member = "null"; - } else { - test = [variable, " != null"]; - member = variable; - } - } else if (memberType.kind === "null") { - test = [variable, ".IsNull"]; - member = "null"; - } else { - const memberName = this.nameForUnionMember(xfer.sourceType, memberType); - member = [variable, ".", memberName]; - test = [member, " != null"]; - } - if (memberType.kind !== "null" && isValueType(memberType)) { - member = [member, ".Value"]; - } - this.emitLine("if (", test, ")"); - this.emitBlock(() => this.emitTransformer(member, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof StringMatchTransformer) { - const value = this.stringCaseValue(followTargetType(xfer.sourceType), xfer.stringCase); - this.emitLine("if (", variable, " == ", value, ")"); - this.emitBlock(() => this.emitTransformer(variable, xfer.transformer, targetType, emitFinish)); - } else if (xfer instanceof EncodingTransformer) { - const converter = this.converterForType(xfer.sourceType); - if (converter !== undefined) { - this.emitLine("var converter = ", this.converterObject(converter), ";"); - this.emitLine("converter.WriteJson(writer, ", variable, ", serializer);"); - } else { - this.emitLine(this.serializeValueCode(variable), ";"); - } - emitFinish([]); - return true; - } else if (xfer instanceof ArrayEncodingTransformer) { - this.emitLine("writer.WriteStartArray();"); - const itemVariable = "arrayItem"; - this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); - this.emitBlock(() => { - this.emitTransformer(itemVariable, xfer.itemTransformer, xfer.itemTargetType, () => { - return; - }); - }); - this.emitLine("writer.WriteEndArray();"); - emitFinish([]); - return true; - } else if (xfer instanceof ParseStringTransformer) { - const immediateTargetType = xfer.consumer === undefined ? targetType : xfer.consumer.sourceType; - switch (immediateTargetType.kind) { - case "date-time": - this.emitLine("DateTimeOffset dt;"); - this.emitLine("if (DateTimeOffset.TryParse(", variable, ", out dt))"); - this.emitBlock(() => this.emitConsume("dt", xfer.consumer, targetType, emitFinish)); - break; - case "uuid": - this.emitLine("Guid guid;"); - this.emitLine("if (Guid.TryParse(", variable, ", out guid))"); - this.emitBlock(() => this.emitConsume("guid", xfer.consumer, targetType, emitFinish)); - break; - case "uri": - this.emitLine("try"); - this.emitBlock(() => { - // this.emitLine("var uri = new Uri(", variable, ");"); - // The default value about:blank should never happen, but this way we avoid a null reference warning. - this.emitLine('var uri = new Uri("about:blank");'); - this.emitLine("if (!string.IsNullOrEmpty(stringValue))"); - this.emitBlock(() => { - this.emitLine("uri = new Uri(", variable, ");"); - }); - this.emitConsume("uri", xfer.consumer, targetType, emitFinish); - }); - this.emitLine("catch (UriFormatException) {}"); - break; - case "integer": - this.emitLine("long l;"); - this.emitLine("if (Int64.TryParse(", variable, ", out l))"); - this.emitBlock(() => this.emitConsume("l", xfer.consumer, targetType, emitFinish)); - break; - case "bool": - this.emitLine("bool b;"); - this.emitLine("if (Boolean.TryParse(", variable, ", out b))"); - this.emitBlock(() => this.emitConsume("b", xfer.consumer, targetType, emitFinish)); - break; - default: - return panic(`Parsing string to ${immediateTargetType.kind} not supported`); - } - } else if (xfer instanceof StringifyTransformer) { - switch (xfer.sourceType.kind) { - case "date-time": - return this.emitConsume( - [variable, '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "uuid": - return this.emitConsume( - [variable, '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)'], - xfer.consumer, - targetType, - emitFinish - ); - case "integer": - case "uri": - return this.emitConsume([variable, ".ToString()"], xfer.consumer, targetType, emitFinish); - case "bool": - this.emitLine("var boolString = ", variable, ' ? "true" : "false";'); - return this.emitConsume("boolString", xfer.consumer, targetType, emitFinish); - default: - return panic(`Stringifying ${xfer.sourceType.kind} not supported`); - } - } else if (xfer instanceof StringProducerTransformer) { - const value = this.stringCaseValue(directTargetType(xfer.consumer), xfer.result); - return this.emitConsume(value, xfer.consumer, targetType, emitFinish); - } else if (xfer instanceof MinMaxLengthCheckTransformer) { - const min = xfer.minLength; - const max = xfer.maxLength; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, ".Length >= ", min.toString()]); - } - if (max !== undefined) { - conditions.push([variable, ".Length <= ", max.toString()]); - } - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof MinMaxValueTransformer) { - const min = xfer.minimum; - const max = xfer.maximum; - const conditions: Sourcelike[] = []; - - if (min !== undefined) { - conditions.push([variable, " >= ", min.toString()]); - } - if (max !== undefined) { - conditions.push([variable, " <= ", max.toString()]); - } - this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); - this.emitBlock(() => this.emitConsume(variable, xfer.consumer, targetType, emitFinish)); - return false; - } else if (xfer instanceof UnionInstantiationTransformer) { - if (!(targetType instanceof UnionType)) { - return panic("Union instantiation transformer must produce a union type"); - } - const maybeNullable = nullableFromUnion(targetType); - if (maybeNullable !== null) { - emitFinish(variable); - } else { - const unionName = this.nameForNamedType(targetType); - let initializer: Sourcelike; - if (xfer.sourceType.kind === "null") { - initializer = " "; - } else { - const memberName = this.nameForUnionMember(targetType, xfer.sourceType); - initializer = [" ", memberName, " = ", variable, " "]; - } - emitFinish(["new ", unionName, " {", initializer, "}"]); - } - return true; - } else { - return panic("Unknown transformer"); - } - return false; - } - - private emitTransformation(converterName: Name, t: Type): void { - const xf = defined(transformationForType(t)); - const reverse = xf.reverse; - const targetType = xf.targetType; - const xfer = xf.transformer; - const csType = this.csType(targetType); - // const haveNullable = isValueType(targetType); - - // if (haveNullable) { - // converterName = ['Nullable', converterName]; - // csType = [csType, "?"]; - // } - this.emitType( - undefined, - AccessModifier.Internal, - "class", - converterName, - ["JsonConverter<", csType, ">"], - () => { - let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; - this.emitCanConvert(canConvertExpr); - this.ensureBlankLine(); - this.emitReadJson(() => { - // FIXME: It's unsatisfying that we need this. The reason is that we not - // only match T, but also T?. If we didn't, then the T in T? would not be - // deserialized with our converter but with the default one. Can we check - // whether the type is a nullable? - // FIXME: This could duplicate one of the cases handled below in - // `emitDecodeTransformer`. - // if (haveNullable && !(targetType instanceof UnionType)) { - // this.emitLine("if (reader.TokenType == JsonTokenType.Null) return null;"); - // } - - const allHandled = this.emitDecodeTransformer(xfer, targetType, v => - this.emitLine("return ", v, ";") - ); - if (!allHandled) { - this.emitThrow(['"Cannot unmarshal type ', csType, '"']); - } - }, csType); - this.ensureBlankLine(); - this.emitWriteJson( - "value", - () => { - // FIXME: See above. - // if (haveNullable && !(targetType instanceof UnionType)) { - // this.emitLine("if (value == null)"); - // this.emitBlock(() => { - // this.emitLine("writer.WriteNullValue();"); - // this.emitLine("return;"); - // }); - // } - - const allHandled = this.emitTransformer("value", reverse.transformer, reverse.targetType, () => - this.emitLine("return;") - ); - if (!allHandled) { - this.emitThrow(['"Cannot marshal type ', csType, '"']); - } - }, - csType - ); - this.ensureBlankLine(); - this.emitLine("public static readonly ", converterName, " Singleton = new ", converterName, "();"); - } - ); - } - - protected emitRequiredHelpers(): void { - if (this._needHelpers) { - this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitFromJsonForTopLevel(t, n)); - this.ensureBlankLine(); - this.emitSerializeClass(); - } - if (this._needHelpers || (this._needAttributes && (this.haveNamedUnions || this.haveEnums))) { - this.ensureBlankLine(); - this.emitConverterClass(); - this.forEachTransformation("leading-and-interposing", (n, t) => this.emitTransformation(n, t)); - this.emitMultiline(` -public class DateOnlyConverter : JsonConverter -{ - private readonly string serializationFormat; - public DateOnlyConverter() : this(null) { } - - public DateOnlyConverter(string? serializationFormat) - { - this.serializationFormat = serializationFormat ?? "yyyy-MM-dd"; - } - - public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var value = reader.GetString(); - return DateOnly.Parse(value!); - } - - public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) - => writer.WriteStringValue(value.ToString(serializationFormat)); -} - -public class TimeOnlyConverter : JsonConverter -{ - private readonly string serializationFormat; - - public TimeOnlyConverter() : this(null) { } - - public TimeOnlyConverter(string? serializationFormat) - { - this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff"; - } - - public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - var value = reader.GetString(); - return TimeOnly.Parse(value!); - } - - public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) - => writer.WriteStringValue(value.ToString(serializationFormat)); -} - -internal class IsoDateTimeOffsetConverter : JsonConverter -{ - public override bool CanConvert(Type t) => t == typeof(DateTimeOffset); - - private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; - - private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; - private string? _dateTimeFormat; - private CultureInfo? _culture; - - public DateTimeStyles DateTimeStyles - { - get => _dateTimeStyles; - set => _dateTimeStyles = value; - } - - public string? DateTimeFormat - { - get => _dateTimeFormat ?? string.Empty; - set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; - } - - public CultureInfo Culture - { - get => _culture ?? CultureInfo.CurrentCulture; - set => _culture = value; - } - - public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) - { - string text; - - - if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal - || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) - { - value = value.ToUniversalTime(); - } - - text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); - - writer.WriteStringValue(text); - } - - public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - string? dateText = reader.GetString(); - - if (string.IsNullOrEmpty(dateText) == false) - { - if (!string.IsNullOrEmpty(_dateTimeFormat)) - { - return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); - } - else - { - return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); - } - } - else - { - return default(DateTimeOffset); - } - } - - - public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter(); -}`); - } - } - - protected needNamespace(): boolean { - return this._needNamespaces; - } -} diff --git a/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts new file mode 100644 index 000000000..c8f16738f --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/CSharpRenderer.ts @@ -0,0 +1,551 @@ +import { arrayIntercalate } from "collection-utils"; + +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import type { Name, Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { assert } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { followTargetType } from "../../Transformers"; +import type { + ClassProperty, + ClassType, + EnumType, + Type, + UnionType, +} from "../../Type"; +import { + directlyReachableSingleNamedType, + matchCompoundType, + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import type { cSharpOptions } from "./language"; +import { + AccessModifier, + csTypeForTransformedStringType, + isValueType, + namingFunction, + namingFunctionKeep, + noFollow, +} from "./utils"; + +export class CSharpRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _csOptions: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + return [ + "QuickType", + "Type", + "System", + "Console", + "Exception", + "DateTimeOffset", + "Guid", + "Uri", + ]; + } + + protected forbiddenForObjectProperties( + _: ClassType, + classNamed: Name, + ): ForbiddenWordsInfo { + return { + names: [ + classNamed, + "ToString", + "GetHashCode", + "Finalize", + "Equals", + "GetType", + "MemberwiseClone", + "ReferenceEquals", + ], + includeGlobalForbidden: false, + }; + } + + protected forbiddenForUnionMembers( + _: UnionType, + unionNamed: Name, + ): ForbiddenWordsInfo { + return { names: [unionNamed], includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return namingFunction; + } + + protected namerForObjectProperty(): Namer { + return this._csOptions.keepPropertyName + ? namingFunctionKeep + : namingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return namingFunction; + } + + protected makeEnumCaseNamer(): Namer { + return namingFunction; + } + + protected unionNeedsName(u: UnionType): boolean { + return nullableFromUnion(u) === null; + } + + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + // If the top-level type doesn't contain any classes or unions + // we have to define a class just for the `FromJson` method, in + // emitFromJsonForTopLevel. + return directlyReachableSingleNamedType(type); + } + + protected emitBlock(f: () => void, semicolon = false): void { + this.emitLine("{"); + this.indent(f); + this.emitLine("}", semicolon ? ";" : ""); + } + + protected get doubleType(): string { + return this._csOptions.useDecimal ? "decimal" : "double"; + } + + protected csType( + t: Type, + follow: (t: Type) => Type = followTargetType, + withIssues = false, + ): Sourcelike { + const actualType = follow(t); + return matchType( + actualType, + (_anyType) => + maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + this._csOptions.typeForAny, + ), + (_nullType) => + maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + this._csOptions.typeForAny, + ), + (_boolType) => "bool", + (_integerType) => "long", + (_doubleType) => this.doubleType, + (_stringType) => "string", + (arrayType) => { + const itemsType = this.csType( + arrayType.items, + follow, + withIssues, + ); + if (this._csOptions.useList) { + return ["List<", itemsType, ">"]; + } else { + return [itemsType, "[]"]; + } + }, + (classType) => this.nameForNamedType(classType), + (mapType) => [ + "Dictionary", + ], + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) + return this.nullableCSType(nullable, noFollow); + return this.nameForNamedType(unionType); + }, + (transformedStringType) => + csTypeForTransformedStringType(transformedStringType), + ); + } + + protected nullableCSType( + t: Type, + follow: (t: Type) => Type = followTargetType, + withIssues = false, + ): Sourcelike { + t = followTargetType(t); + const csType = this.csType(t, follow, withIssues); + if (isValueType(t)) { + return [csType, "?"]; + } else { + return csType; + } + } + + protected baseclassForType(_t: Type): Sourcelike | undefined { + return undefined; + } + + protected emitType( + description: string[] | undefined, + accessModifier: AccessModifier, + declaration: Sourcelike, + name: Sourcelike, + baseclass: Sourcelike | undefined, + emitter: () => void, + ): void { + switch (accessModifier) { + case AccessModifier.Public: + declaration = ["public ", declaration]; + break; + case AccessModifier.Internal: + declaration = ["internal ", declaration]; + break; + default: + break; + } + + this.emitDescription(description); + if (baseclass === undefined) { + this.emitLine(declaration, " ", name); + } else { + this.emitLine(declaration, " ", name, " : ", baseclass); + } + + this.emitBlock(emitter); + } + + protected attributesForProperty( + _property: ClassProperty, + _name: Name, + _c: ClassType, + _jsonName: string, + ): Sourcelike[] | undefined { + return undefined; + } + + protected propertyDefinition( + property: ClassProperty, + name: Name, + _c: ClassType, + _jsonName: string, + ): Sourcelike { + const t = property.type; + const csType = property.isOptional + ? this.nullableCSType(t, followTargetType, true) + : this.csType(t, followTargetType, true); + + const propertyArray = ["public "]; + + if (this._csOptions.virtual) propertyArray.push("virtual "); + + return [...propertyArray, csType, " ", name, " { get; set; }"]; + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + const start = "/// "; + if (this._csOptions.dense) { + this.emitLine(start, lines.join("; "), ""); + } else { + this.emitCommentLines(lines, { + lineStart: "/// ", + beforeComment: start, + afterComment: "/// ", + }); + } + } + + protected blankLinesBetweenAttributes(): boolean { + return false; + } + + private emitClassDefinition(c: ClassType, className: Name): void { + this.emitType( + this.descriptionForType(c), + AccessModifier.Public, + "partial class", + className, + this.baseclassForType(c), + () => { + if (c.getProperties().size === 0) return; + const blankLines = this.blankLinesBetweenAttributes() + ? "interposing" + : "none"; + const columns: Sourcelike[][] = []; + let isFirstProperty = true; + let previousDescription: string[] | undefined = undefined; + this.forEachClassProperty( + c, + blankLines, + (name, jsonName, p) => { + const attributes = this.attributesForProperty( + p, + name, + c, + jsonName, + ); + const description = this.descriptionForClassProperty( + c, + jsonName, + ); + const property = this.propertyDefinition( + p, + name, + c, + jsonName, + ); + if (attributes === undefined) { + if ( + // Descriptions should be preceded by an empty line + (!isFirstProperty && + description !== undefined) || + // If the previous property has a description, leave an empty line + previousDescription !== undefined + ) { + this.ensureBlankLine(); + } + + this.emitDescription(description); + this.emitLine(property); + } else if ( + this._csOptions.dense && + attributes.length > 0 + ) { + const comment = + description === undefined + ? "" + : ` // ${description.join("; ")}`; + columns.push([attributes, " ", property, comment]); + } else { + this.emitDescription(description); + for (const attribute of attributes) { + this.emitLine(attribute); + } + + this.emitLine(property); + } + + isFirstProperty = false; + previousDescription = description; + }, + ); + if (columns.length > 0) { + this.emitTable(columns); + } + }, + ); + } + + private emitUnionDefinition(u: UnionType, unionName: Name): void { + const nonNulls = removeNullFromUnion(u, true)[1]; + this.emitType( + this.descriptionForType(u), + AccessModifier.Public, + "partial struct", + unionName, + this.baseclassForType(u), + () => { + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (fieldName, t) => { + const csType = this.nullableCSType(t); + this.emitLine("public ", csType, " ", fieldName, ";"); + }, + ); + this.ensureBlankLine(); + const nullTests: Sourcelike[] = Array.from(nonNulls).map( + (t) => [this.nameForUnionMember(u, t), " == null"], + ); + this.ensureBlankLine(); + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (fieldName, t) => { + const csType = this.csType(t); + this.emitExpressionMember( + [ + "public static implicit operator ", + unionName, + "(", + csType, + " ", + fieldName, + ")", + ], + [ + "new ", + unionName, + " { ", + fieldName, + " = ", + fieldName, + " }", + ], + ); + }, + ); + if (u.findMember("null") === undefined) return; + this.emitExpressionMember( + "public bool IsNull", + arrayIntercalate(" && ", nullTests), + true, + ); + }, + ); + } + + private emitEnumDefinition(e: EnumType, enumName: Name): void { + const caseNames: Sourcelike[] = []; + this.forEachEnumCase(e, "none", (name) => { + if (caseNames.length > 0) caseNames.push(", "); + caseNames.push(name); + }); + this.emitDescription(this.descriptionForType(e)); + this.emitLine("public enum ", enumName, " { ", caseNames, " };"); + } + + protected emitExpressionMember( + declare: Sourcelike, + define: Sourcelike, + isProperty = false, + ): void { + if (this._csOptions.version === 5) { + this.emitLine(declare); + this.emitBlock(() => { + const stmt = ["return ", define, ";"]; + if (isProperty) { + this.emitLine("get"); + this.emitBlock(() => this.emitLine(stmt)); + } else { + this.emitLine(stmt); + } + }); + } else { + this.emitLine(declare, " => ", define, ";"); + } + } + + protected emitTypeSwitch( + types: Iterable, + condition: (t: T) => Sourcelike, + withBlock: boolean, + withReturn: boolean, + f: (t: T) => void, + ): void { + assert(!withReturn || withBlock, "Can only have return with block"); + for (const t of types) { + this.emitLine("if (", condition(t), ")"); + if (withBlock) { + this.emitBlock(() => { + f(t); + if (withReturn) { + this.emitLine("return;"); + } + }); + } else { + this.indent(() => f(t)); + } + } + } + + protected emitUsing(ns: Sourcelike): void { + this.emitLine("using ", ns, ";"); + } + + protected emitUsings(): void { + for (const ns of ["System", "System.Collections.Generic"]) { + this.emitUsing(ns); + } + } + + protected emitRequiredHelpers(): void { + return; + } + + private emitTypesAndSupport(): void { + this.forEachObject( + "leading-and-interposing", + (c: ClassType, name: Name) => this.emitClassDefinition(c, name), + ); + this.forEachEnum("leading-and-interposing", (e, name) => + this.emitEnumDefinition(e, name), + ); + this.forEachUnion("leading-and-interposing", (u, name) => + this.emitUnionDefinition(u, name), + ); + this.emitRequiredHelpers(); + } + + protected emitDefaultLeadingComments(): void { + return; + } + + protected emitDefaultFollowingComments(): void { + return; + } + + protected needNamespace(): boolean { + return true; + } + + protected emitSourceStructure(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitDefaultLeadingComments(); + } + + this.ensureBlankLine(); + if (this.needNamespace()) { + this.emitLine("namespace ", this._csOptions.namespace); + this.emitBlock(() => { + this.emitUsings(); + this.emitTypesAndSupport(); + }); + } else { + this.emitUsings(); + this.emitTypesAndSupport(); + } + + this.emitDefaultFollowingComments(); + } + + protected emitDependencyUsings(): void { + let genericEmited: boolean = false; + let ensureGenericOnce = () => { + if (!genericEmited) { + this.emitUsing("System.Collections.Generic"); + genericEmited = true; + } + } + this.typeGraph.allTypesUnordered().forEach(_ => { + matchCompoundType( + _, + _arrayType => this._csOptions.useList ? ensureGenericOnce() : undefined, + _classType => { }, + _mapType => ensureGenericOnce(), + _objectType => { }, + _unionType => { } + ) + }); + } + +} diff --git a/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts new file mode 100644 index 000000000..3c3d91cc9 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/NewtonSoftCSharpRenderer.ts @@ -0,0 +1,1169 @@ +import { arrayIntercalate } from "collection-utils"; + +import { + type ForbiddenWordsInfo, + inferredNameOrder, +} from "../../ConvenienceRenderer"; +import { DependencyName, type Name, SimpleName } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { defined, panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayDecodingTransformer, + ArrayEncodingTransformer, + ChoiceTransformer, + DecodingChoiceTransformer, + DecodingTransformer, + EncodingTransformer, + MinMaxLengthCheckTransformer, + MinMaxValueTransformer, + ParseStringTransformer, + StringMatchTransformer, + StringProducerTransformer, + StringifyTransformer, + type Transformation, + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + followTargetType, + transformationForType, +} from "../../Transformers"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + type Type, + UnionType, +} from "../../Type"; +import { nullableFromUnion } from "../../Type/TypeUtils"; + +import { CSharpRenderer } from "./CSharpRenderer"; +import type { newtonsoftCSharpOptions } from "./language"; +import { + AccessModifier, + alwaysApplyTransformation, + denseJsonPropertyName, + denseNullValueHandlingEnumName, + denseRequiredEnumName, + isValueType, + namingFunction, +} from "./utils"; + +export class NewtonsoftCSharpRenderer extends CSharpRenderer { + private readonly _enumExtensionsNames = new Map(); + + private readonly _needHelpers: boolean; + + private readonly _needAttributes: boolean; + + private readonly _needNamespaces: boolean; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext, _options); + this._needHelpers = _options.features.helpers; + this._needAttributes = _options.features.attributes; + this._needNamespaces = _options.features.namespaces; + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + const forbidden = [ + "Converter", + "JsonConverter", + "JsonSerializer", + "JsonWriter", + "JsonToken", + "Serialize", + "Newtonsoft", + "MetadataPropertyHandling", + "DateParseHandling", + "FromJson", + "Required", + ]; + if (this._options.dense) { + forbidden.push("J", "R", "N"); + } + + if (this._options.baseclass !== undefined) { + forbidden.push(this._options.baseclass); + } + + return super.forbiddenNamesForGlobalNamespace().concat(forbidden); + } + + protected forbiddenForObjectProperties( + c: ClassType, + className: Name, + ): ForbiddenWordsInfo { + const result = super.forbiddenForObjectProperties(c, className); + result.names = result.names.concat(["ToJson", "FromJson", "Required"]); + return result; + } + + protected makeNameForTransformation( + xf: Transformation, + typeName: Name | undefined, + ): Name { + if (typeName === undefined) { + let xfer = xf.transformer; + if ( + xfer instanceof DecodingTransformer && + xfer.consumer !== undefined + ) { + xfer = xfer.consumer; + } + + return new SimpleName( + [`${xfer.kind}_converter`], + namingFunction, + inferredNameOrder + 30, + ); + } + + return new DependencyName( + namingFunction, + typeName.order + 30, + (lookup) => `${lookup(typeName)}_converter`, + ); + } + + protected makeNamedTypeDependencyNames( + t: Type, + name: Name, + ): DependencyName[] { + if (!(t instanceof EnumType)) return []; + + const extensionsName = new DependencyName( + namingFunction, + name.order + 30, + (lookup) => `${lookup(name)}_extensions`, + ); + this._enumExtensionsNames.set(name, extensionsName); + return [extensionsName]; + } + + protected emitUsings(): void { + if (!this._needAttributes && !this._needHelpers) { + this.emitDependencyUsings(); + return; + } + + super.emitUsings(); + this.ensureBlankLine(); + + for (const ns of [ + "System.Globalization", + "Newtonsoft.Json", + "Newtonsoft.Json.Converters", + ]) { + this.emitUsing(ns); + } + + if (this._options.dense) { + this.emitUsing([ + denseJsonPropertyName, + " = Newtonsoft.Json.JsonPropertyAttribute", + ]); + this.emitUsing([ + denseRequiredEnumName, + " = Newtonsoft.Json.Required", + ]); + this.emitUsing([ + denseNullValueHandlingEnumName, + " = Newtonsoft.Json.NullValueHandling", + ]); + } + + if (this._options.baseclass === "EntityData") { + this.emitUsing("Microsoft.Azure.Mobile.Server"); + } + } + + protected baseclassForType(_t: Type): Sourcelike | undefined { + return this._options.baseclass; + } + + protected emitDefaultLeadingComments(): void { + if (!this._needHelpers) return; + + this.emitLine("// "); + this.emitLine("//"); + this.emitLine( + "// To parse this JSON data, add NuGet 'Newtonsoft.Json' then do", + this.topLevels.size === 1 ? "" : " one of these", + ":", + ); + this.emitLine("//"); + this.emitLine("// using ", this._options.namespace, ";"); + this.emitLine("//"); + this.forEachTopLevel("none", (t, topLevelName) => { + let rhs: Sourcelike; + if (t instanceof EnumType) { + rhs = [ + "JsonConvert.DeserializeObject<", + topLevelName, + ">(jsonString)", + ]; + } else { + rhs = [topLevelName, ".FromJson(jsonString)"]; + } + + this.emitLine( + "// var ", + modifySource(camelCase, topLevelName), + " = ", + rhs, + ";", + ); + }); + } + + private converterForType(t: Type): Name | undefined { + let xf = transformationForType(t); + + if (xf === undefined && t instanceof UnionType) { + const maybeNullable = nullableFromUnion(t); + if (maybeNullable !== null) { + t = maybeNullable; + xf = transformationForType(t); + } + } + + if (xf === undefined) return undefined; + + if (alwaysApplyTransformation(xf)) return undefined; + + return defined(this.nameForTransformation(t)); + } + + protected attributesForProperty( + property: ClassProperty, + _name: Name, + _c: ClassType, + jsonName: string, + ): Sourcelike[] | undefined { + if (!this._needAttributes) return undefined; + + const attributes: Sourcelike[] = []; + + const jsonProperty = this._options.dense + ? denseJsonPropertyName + : "JsonProperty"; + const escapedName = utf16StringEscape(jsonName); + const isNullable = followTargetType(property.type).isNullable; + const isOptional = property.isOptional; + const requiredClass = this._options.dense ? "R" : "Required"; + const nullValueHandlingClass = this._options.dense + ? "N" + : "NullValueHandling"; + const nullValueHandling = + isOptional && !isNullable + ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] + : []; + let required: Sourcelike; + if (!this._options.checkRequired || (isOptional && isNullable)) { + required = [nullValueHandling]; + } else if (isOptional && !isNullable) { + required = [ + ", Required = ", + requiredClass, + ".DisallowNull", + nullValueHandling, + ]; + } else if (!isOptional && isNullable) { + required = [", Required = ", requiredClass, ".AllowNull"]; + } else { + required = [ + ", Required = ", + requiredClass, + ".Always", + nullValueHandling, + ]; + } + + attributes.push([ + "[", + jsonProperty, + '("', + escapedName, + '"', + required, + ")]", + ]); + + const converter = this.converterForType(property.type); + if (converter !== undefined) { + attributes.push(["[JsonConverter(typeof(", converter, "))]"]); + } + + return attributes; + } + + protected blankLinesBetweenAttributes(): boolean { + return this._needAttributes && !this._options.dense; + } + + // The "this" type can't be `dynamic`, so we have to force it to `object`. + private topLevelResultType(t: Type): Sourcelike { + return t.kind === "any" || t.kind === "none" + ? "object" + : this.csType(t); + } + + private emitFromJsonForTopLevel(t: Type, name: Name): void { + if (t instanceof EnumType) return; + + let partial: string; + let typeKind: string; + const definedType = this.namedTypeToNameForTopLevel(t); + if (definedType !== undefined) { + partial = "partial "; + typeKind = definedType instanceof ClassType ? "class" : "struct"; + } else { + partial = ""; + typeKind = "class"; + } + + const csType = this.topLevelResultType(t); + this.emitType( + undefined, + AccessModifier.Public, + [partial, typeKind], + name, + this.baseclassForType(t), + () => { + // FIXME: Make FromJson a Named + this.emitExpressionMember( + ["public static ", csType, " FromJson(string json)"], + [ + "JsonConvert.DeserializeObject<", + csType, + ">(json, ", + this._options.namespace, + ".Converter.Settings)", + ], + ); + }, + ); + } + + private emitDecoderSwitch(emitBody: () => void): void { + this.emitLine("switch (reader.TokenType)"); + this.emitBlock(emitBody); + } + + private emitTokenCase(tokenType: string): void { + this.emitLine("case JsonToken.", tokenType, ":"); + } + + private emitThrow(message: Sourcelike): void { + this.emitLine("throw new Exception(", message, ");"); + } + + private deserializeTypeCode(typeName: Sourcelike): Sourcelike { + return ["serializer.Deserialize<", typeName, ">(reader)"]; + } + + private serializeValueCode(value: Sourcelike): Sourcelike { + return ["serializer.Serialize(writer, ", value, ")"]; + } + + private emitSerializeClass(): void { + // FIXME: Make Serialize a Named + this.emitType( + undefined, + AccessModifier.Public, + "static class", + "Serialize", + undefined, + () => { + // Sometimes multiple top-levels will resolve to the same type, so we have to take care + // not to emit more than one extension method for the same type. + const seenTypes = new Set(); + this.forEachTopLevel("none", (t) => { + // FIXME: Make ToJson a Named + if (!seenTypes.has(t)) { + seenTypes.add(t); + this.emitExpressionMember( + [ + "public static string ToJson(this ", + this.topLevelResultType(t), + " self)", + ], + [ + "JsonConvert.SerializeObject(self, ", + this._options.namespace, + ".Converter.Settings)", + ], + ); + } + }); + }, + ); + } + + private emitCanConvert(expr: Sourcelike): void { + this.emitExpressionMember( + "public override bool CanConvert(Type t)", + expr, + ); + } + + private emitReadJson(emitBody: () => void): void { + this.emitLine( + "public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)", + ); + this.emitBlock(emitBody); + } + + private emitWriteJson(variable: string, emitBody: () => void): void { + this.emitLine( + "public override void WriteJson(JsonWriter writer, object ", + variable, + ", JsonSerializer serializer)", + ); + this.emitBlock(emitBody); + } + + private converterObject(converterName: Name): Sourcelike { + // FIXME: Get a singleton + return [converterName, ".Singleton"]; + } + + private emitConverterClass(): void { + // FIXME: Make Converter a Named + const converterName: Sourcelike = ["Converter"]; + this.emitType( + undefined, + AccessModifier.Internal, + "static class", + converterName, + undefined, + () => { + this.emitLine( + "public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings", + ); + this.emitBlock(() => { + this.emitLine( + "MetadataPropertyHandling = MetadataPropertyHandling.Ignore,", + ); + this.emitLine( + "DateParseHandling = DateParseHandling.None,", + ); + this.emitLine("Converters ="); + this.emitLine("{"); + this.indent(() => { + for (const [t, converter] of this + .typesWithNamedTransformations) { + if ( + alwaysApplyTransformation( + defined(transformationForType(t)), + ) + ) { + this.emitLine( + this.converterObject(converter), + ",", + ); + } + } + + this.emitLine( + "new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }", + ); + }); + this.emitLine("},"); + }, true); + }, + ); + } + + private emitDecoderTransformerCase( + tokenCases: string[], + variableName: string, + xfer: Transformer | undefined, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + ): void { + if (xfer === undefined) return; + + for (const tokenCase of tokenCases) { + this.emitTokenCase(tokenCase); + } + + this.indent(() => { + const allHandled = this.emitDecodeTransformer( + xfer, + targetType, + emitFinish, + variableName, + ); + if (!allHandled) { + this.emitLine("break;"); + } + }); + } + + private emitConsume( + value: Sourcelike, + consumer: Transformer | undefined, + targetType: Type, + emitFinish: (variableName: Sourcelike) => void, + ): boolean { + if (consumer === undefined) { + emitFinish(value); + return true; + } + + return this.emitTransformer(value, consumer, targetType, emitFinish); + } + + private emitDecodeTransformer( + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + variableName = "value", + ): boolean { + if (xfer instanceof DecodingTransformer) { + const source = xfer.sourceType; + const converter = this.converterForType(targetType); + if (converter !== undefined) { + const typeSource = this.csType(targetType); + this.emitLine( + "var converter = ", + this.converterObject(converter), + ";", + ); + this.emitLine( + "var ", + variableName, + " = (", + typeSource, + ")converter.ReadJson(reader, typeof(", + typeSource, + "), null, serializer);", + ); + } else if (source.kind !== "null") { + const output = + targetType.kind === "double" ? targetType : source; + this.emitLine( + "var ", + variableName, + " = ", + this.deserializeTypeCode(this.csType(output)), + ";", + ); + } + + return this.emitConsume( + variableName, + xfer.consumer, + targetType, + emitFinish, + ); + } + + if (xfer instanceof ArrayDecodingTransformer) { + // FIXME: Consume StartArray + if (!(targetType instanceof ArrayType)) { + return panic("Array decoding must produce an array type"); + } + + // FIXME: handle EOF + this.emitLine("reader.Read();"); + this.emitLine( + "var ", + variableName, + " = new List<", + this.csType(targetType.items), + ">();", + ); + this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); + this.emitBlock(() => { + this.emitDecodeTransformer( + xfer.itemTransformer, + xfer.itemTargetType, + (v) => this.emitLine(variableName, ".Add(", v, ");"), + "arrayItem", + ); + // FIXME: handle EOF + this.emitLine("reader.Read();"); + }); + let result: Sourcelike = variableName; + if (!this._options.useList) { + result = [result, ".ToArray()"]; + } + + emitFinish(result); + return true; + } + + if (xfer instanceof DecodingChoiceTransformer) { + this.emitDecoderSwitch(() => { + const nullTransformer = xfer.nullTransformer; + if (nullTransformer !== undefined) { + this.emitTokenCase("Null"); + this.indent(() => { + const allHandled = this.emitDecodeTransformer( + nullTransformer, + targetType, + emitFinish, + "null", + ); + if (!allHandled) { + this.emitLine("break"); + } + }); + } + + this.emitDecoderTransformerCase( + ["Integer"], + "integerValue", + xfer.integerTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + xfer.integerTransformer === undefined + ? ["Integer", "Float"] + : ["Float"], + "doubleValue", + xfer.doubleTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["Boolean"], + "boolValue", + xfer.boolTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["String", "Date"], + "stringValue", + xfer.stringTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["StartObject"], + "objectValue", + xfer.objectTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["StartArray"], + "arrayValue", + xfer.arrayTransformer, + targetType, + emitFinish, + ); + }); + return false; + } + + return panic("Unknown transformer"); + } + + private stringCaseValue(t: Type, stringCase: string): Sourcelike { + if (t.kind === "string") { + return ['"', utf16StringEscape(stringCase), '"']; + } + if (t instanceof EnumType) { + return [ + this.nameForNamedType(t), + ".", + this.nameForEnumCase(t, stringCase), + ]; + } + + return panic(`Type ${t.kind} does not have string cases`); + } + + private emitTransformer( + variable: Sourcelike, + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + ): boolean { + function directTargetType(continuation: Transformer | undefined): Type { + if (continuation === undefined) { + return targetType; + } + + return followTargetType(continuation.sourceType); + } + + if (xfer instanceof ChoiceTransformer) { + const caseXfers = xfer.transformers; + if ( + caseXfers.length > 1 && + caseXfers.every( + (caseXfer) => caseXfer instanceof StringMatchTransformer, + ) + ) { + this.emitLine("switch (", variable, ")"); + this.emitBlock(() => { + for (const caseXfer of caseXfers) { + const matchXfer = caseXfer as StringMatchTransformer; + const value = this.stringCaseValue( + followTargetType(matchXfer.sourceType), + matchXfer.stringCase, + ); + this.emitLine("case ", value, ":"); + this.indent(() => { + const allDone = this.emitTransformer( + variable, + matchXfer.transformer, + targetType, + emitFinish, + ); + if (!allDone) { + this.emitLine("break;"); + } + }); + } + }); + // FIXME: Can we check for exhaustiveness? For enums it should be easy. + return false; + } + + for (const caseXfer of caseXfers) { + this.emitTransformer( + variable, + caseXfer, + targetType, + emitFinish, + ); + } + } else if (xfer instanceof UnionMemberMatchTransformer) { + const memberType = xfer.memberType; + const maybeNullable = nullableFromUnion(xfer.sourceType); + let test: Sourcelike; + let member: Sourcelike; + if (maybeNullable !== null) { + if (memberType.kind === "null") { + test = [variable, " == null"]; + member = "null"; + } else { + test = [variable, " != null"]; + member = variable; + } + } else if (memberType.kind === "null") { + test = [variable, ".IsNull"]; + member = "null"; + } else { + const memberName = this.nameForUnionMember( + xfer.sourceType, + memberType, + ); + member = [variable, ".", memberName]; + test = [member, " != null"]; + } + + if (memberType.kind !== "null" && isValueType(memberType)) { + member = [member, ".Value"]; + } + + this.emitLine("if (", test, ")"); + this.emitBlock(() => + this.emitTransformer( + member, + xfer.transformer, + targetType, + emitFinish, + ), + ); + } else if (xfer instanceof StringMatchTransformer) { + const value = this.stringCaseValue( + followTargetType(xfer.sourceType), + xfer.stringCase, + ); + this.emitLine("if (", variable, " == ", value, ")"); + this.emitBlock(() => + this.emitTransformer( + variable, + xfer.transformer, + targetType, + emitFinish, + ), + ); + } else if (xfer instanceof EncodingTransformer) { + const converter = this.converterForType(xfer.sourceType); + if (converter !== undefined) { + this.emitLine( + "var converter = ", + this.converterObject(converter), + ";", + ); + this.emitLine( + "converter.WriteJson(writer, ", + variable, + ", serializer);", + ); + } else { + this.emitLine(this.serializeValueCode(variable), ";"); + } + + emitFinish([]); + return true; + } else if (xfer instanceof ArrayEncodingTransformer) { + this.emitLine("writer.WriteStartArray();"); + const itemVariable = "arrayItem"; + this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); + this.emitBlock(() => { + this.emitTransformer( + itemVariable, + xfer.itemTransformer, + xfer.itemTargetType, + () => { + return; + }, + ); + }); + this.emitLine("writer.WriteEndArray();"); + emitFinish([]); + return true; + } else if (xfer instanceof ParseStringTransformer) { + const immediateTargetType = + xfer.consumer === undefined + ? targetType + : xfer.consumer.sourceType; + switch (immediateTargetType.kind) { + case "date-time": + this.emitLine("DateTimeOffset dt;"); + this.emitLine( + "if (DateTimeOffset.TryParse(", + variable, + ", out dt))", + ); + this.emitBlock(() => + this.emitConsume( + "dt", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + case "uuid": + this.emitLine("Guid guid;"); + this.emitLine( + "if (Guid.TryParse(", + variable, + ", out guid))", + ); + this.emitBlock(() => + this.emitConsume( + "guid", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + case "uri": + this.emitLine("try"); + this.emitBlock(() => { + this.emitLine("var uri = new Uri(", variable, ");"); + this.emitConsume( + "uri", + xfer.consumer, + targetType, + emitFinish, + ); + }); + this.emitLine("catch (UriFormatException) {}"); + break; + case "integer": + this.emitLine("long l;"); + this.emitLine("if (Int64.TryParse(", variable, ", out l))"); + this.emitBlock(() => + this.emitConsume( + "l", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + case "bool": + this.emitLine("bool b;"); + this.emitLine( + "if (Boolean.TryParse(", + variable, + ", out b))", + ); + this.emitBlock(() => + this.emitConsume( + "b", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + default: + return panic( + `Parsing string to ${immediateTargetType.kind} not supported`, + ); + } + } else if (xfer instanceof StringifyTransformer) { + switch (xfer.sourceType.kind) { + case "date-time": + return this.emitConsume( + [ + variable, + '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)', + ], + xfer.consumer, + targetType, + emitFinish, + ); + case "uuid": + return this.emitConsume( + [ + variable, + '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)', + ], + xfer.consumer, + targetType, + emitFinish, + ); + case "integer": + case "uri": + return this.emitConsume( + [variable, ".ToString()"], + xfer.consumer, + targetType, + emitFinish, + ); + case "bool": + this.emitLine( + "var boolString = ", + variable, + ' ? "true" : "false";', + ); + return this.emitConsume( + "boolString", + xfer.consumer, + targetType, + emitFinish, + ); + default: + return panic( + `Stringifying ${xfer.sourceType.kind} not supported`, + ); + } + } else if (xfer instanceof StringProducerTransformer) { + const value = this.stringCaseValue( + directTargetType(xfer.consumer), + xfer.result, + ); + return this.emitConsume( + value, + xfer.consumer, + targetType, + emitFinish, + ); + } else if (xfer instanceof MinMaxLengthCheckTransformer) { + const min = xfer.minLength; + const max = xfer.maxLength; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, ".Length >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, ".Length <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => + this.emitConsume( + variable, + xfer.consumer, + targetType, + emitFinish, + ), + ); + return false; + } else if (xfer instanceof MinMaxValueTransformer) { + const min = xfer.minimum; + const max = xfer.maximum; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, " >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, " <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => + this.emitConsume( + variable, + xfer.consumer, + targetType, + emitFinish, + ), + ); + return false; + } else if (xfer instanceof UnionInstantiationTransformer) { + if (!(targetType instanceof UnionType)) { + return panic( + "Union instantiation transformer must produce a union type", + ); + } + + const maybeNullable = nullableFromUnion(targetType); + if (maybeNullable !== null) { + emitFinish(variable); + } else { + const unionName = this.nameForNamedType(targetType); + let initializer: Sourcelike; + if (xfer.sourceType.kind === "null") { + initializer = " "; + } else { + const memberName = this.nameForUnionMember( + targetType, + xfer.sourceType, + ); + initializer = [" ", memberName, " = ", variable, " "]; + } + + emitFinish(["new ", unionName, " {", initializer, "}"]); + } + + return true; + } else { + return panic("Unknown transformer"); + } + + return false; + } + + private emitTransformation(converterName: Name, t: Type): void { + const xf = defined(transformationForType(t)); + const reverse = xf.reverse; + const targetType = xf.targetType; + const xfer = xf.transformer; + this.emitType( + undefined, + AccessModifier.Internal, + "class", + converterName, + "JsonConverter", + () => { + const csType = this.csType(targetType); + let canConvertExpr: Sourcelike = ["t == typeof(", csType, ")"]; + const haveNullable = isValueType(targetType); + if (haveNullable) { + canConvertExpr = [ + canConvertExpr, + " || t == typeof(", + csType, + "?)", + ]; + } + + this.emitCanConvert(canConvertExpr); + this.ensureBlankLine(); + this.emitReadJson(() => { + // FIXME: It's unsatisfying that we need this. The reason is that we not + // only match T, but also T?. If we didn't, then the T in T? would not be + // deserialized with our converter but with the default one. Can we check + // whether the type is a nullable? + // FIXME: This could duplicate one of the cases handled below in + // `emitDecodeTransformer`. + if (haveNullable && !(targetType instanceof UnionType)) { + this.emitLine( + "if (reader.TokenType == JsonToken.Null) return null;", + ); + } + + const allHandled = this.emitDecodeTransformer( + xfer, + targetType, + (v) => this.emitLine("return ", v, ";"), + ); + if (!allHandled) { + this.emitThrow([ + '"Cannot unmarshal type ', + csType, + '"', + ]); + } + }); + this.ensureBlankLine(); + this.emitWriteJson("untypedValue", () => { + // FIXME: See above. + if (haveNullable && !(targetType instanceof UnionType)) { + this.emitLine("if (untypedValue == null)"); + this.emitBlock(() => { + this.emitLine( + "serializer.Serialize(writer, null);", + ); + this.emitLine("return;"); + }); + } + + this.emitLine("var value = (", csType, ")untypedValue;"); + const allHandled = this.emitTransformer( + "value", + reverse.transformer, + reverse.targetType, + () => this.emitLine("return;"), + ); + if (!allHandled) { + this.emitThrow(['"Cannot marshal type ', csType, '"']); + } + }); + this.ensureBlankLine(); + this.emitLine( + "public static readonly ", + converterName, + " Singleton = new ", + converterName, + "();", + ); + }, + ); + } + + protected emitRequiredHelpers(): void { + if (this._needHelpers) { + this.forEachTopLevel("leading-and-interposing", (t, n) => + this.emitFromJsonForTopLevel(t, n), + ); + this.ensureBlankLine(); + this.emitSerializeClass(); + } + + if ( + this._needHelpers || + (this._needAttributes && (this.haveNamedUnions || this.haveEnums)) + ) { + this.ensureBlankLine(); + this.emitConverterClass(); + this.forEachTransformation("leading-and-interposing", (n, t) => + this.emitTransformation(n, t), + ); + } + } + + protected needNamespace(): boolean { + return this._needNamespaces; + } +} diff --git a/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts new file mode 100644 index 000000000..3e3def7a5 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/SystemTextJsonCSharpRenderer.ts @@ -0,0 +1,1316 @@ +import { arrayIntercalate } from "collection-utils"; + +import { + type ForbiddenWordsInfo, + inferredNameOrder, +} from "../../ConvenienceRenderer"; +import { DependencyName, type Name, SimpleName } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { defined, panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayDecodingTransformer, + ArrayEncodingTransformer, + ChoiceTransformer, + DecodingChoiceTransformer, + DecodingTransformer, + EncodingTransformer, + MinMaxLengthCheckTransformer, + MinMaxValueTransformer, + ParseStringTransformer, + StringMatchTransformer, + StringProducerTransformer, + StringifyTransformer, + type Transformation, + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + followTargetType, + transformationForType, +} from "../../Transformers"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + type Type, + UnionType, +} from "../../Type"; +import { nullableFromUnion } from "../../Type/TypeUtils"; + +import { CSharpRenderer } from "./CSharpRenderer"; +import type { systemTextJsonCSharpOptions } from "./language"; +import { + AccessModifier, + alwaysApplyTransformation, + denseJsonPropertyName, + denseNullValueHandlingEnumName, + isValueType, + namingFunction, +} from "./utils"; + +export class SystemTextJsonCSharpRenderer extends CSharpRenderer { + private readonly _enumExtensionsNames = new Map(); + + private readonly _needHelpers: boolean; + + private readonly _needAttributes: boolean; + + private readonly _needNamespaces: boolean; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues< + typeof systemTextJsonCSharpOptions + >, + ) { + super(targetLanguage, renderContext, _options); + this._needHelpers = _options.features.helpers; + this._needAttributes = _options.features.attributes; + this._needNamespaces = _options.features.namespaces; + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + const forbidden = [ + "Converter", + "JsonConverter", + "JsonSerializer", + "JsonWriter", + "JsonToken", + "Serialize", + "JsonSerializerOptions", + // "Newtonsoft", + // "MetadataPropertyHandling", + // "DateParseHandling", + "FromJson", + "Required", + ]; + if (this._options.dense) { + forbidden.push("J", "R", "N"); + } + + if (this._options.baseclass !== undefined) { + forbidden.push(this._options.baseclass); + } + + return super.forbiddenNamesForGlobalNamespace().concat(forbidden); + } + + protected forbiddenForObjectProperties( + c: ClassType, + className: Name, + ): ForbiddenWordsInfo { + const result = super.forbiddenForObjectProperties(c, className); + result.names = result.names.concat(["ToJson", "FromJson", "Required"]); + return result; + } + + protected makeNameForTransformation( + xf: Transformation, + typeName: Name | undefined, + ): Name { + if (typeName === undefined) { + let xfer = xf.transformer; + if ( + xfer instanceof DecodingTransformer && + xfer.consumer !== undefined + ) { + xfer = xfer.consumer; + } + + return new SimpleName( + [`${xfer.kind}_converter`], + namingFunction, + inferredNameOrder + 30, + ); + } + + return new DependencyName( + namingFunction, + typeName.order + 30, + (lookup) => `${lookup(typeName)}_converter`, + ); + } + + protected makeNamedTypeDependencyNames( + t: Type, + name: Name, + ): DependencyName[] { + if (!(t instanceof EnumType)) return []; + + const extensionsName = new DependencyName( + namingFunction, + name.order + 30, + (lookup) => `${lookup(name)}_extensions`, + ); + this._enumExtensionsNames.set(name, extensionsName); + return [extensionsName]; + } + + protected emitUsings(): void { + if (!this._needAttributes && !this._needHelpers) { + this.emitDependencyUsings(); + return; + } + + super.emitUsings(); + this.ensureBlankLine(); + + for (const ns of [ + "System.Text.Json", + "System.Text.Json.Serialization", + "System.Globalization", + ]) { + this.emitUsing(ns); + } + + if (this._options.dense) { + this.emitUsing([ + denseJsonPropertyName, + " = System.Text.Json.Serialization.JsonPropertyNameAttribute", + ]); + // this.emitUsing([denseRequiredEnumName, " = Newtonsoft.Json.Required"]); + this.emitUsing([ + denseNullValueHandlingEnumName, + " = System.Text.Json.Serialization.JsonIgnoreCondition", + ]); + } + + if (this._options.baseclass === "EntityData") { + this.emitUsing("Microsoft.Azure.Mobile.Server"); + } + } + + protected baseclassForType(_t: Type): Sourcelike | undefined { + return this._options.baseclass; + } + + protected emitDefaultFollowingComments(): void { + if (!this._needHelpers) return; + + this.emitLine("#pragma warning restore CS8618"); + this.emitLine("#pragma warning restore CS8601"); + this.emitLine("#pragma warning restore CS8603"); + } + + protected emitDefaultLeadingComments(): void { + if (!this._needHelpers) return; + + this.emitLine("// "); + this.emitLine("//"); + this.emitLine( + "// To parse this JSON data, add NuGet 'System.Text.Json' then do", + this.topLevels.size === 1 ? "" : " one of these", + ":", + ); + this.emitLine("//"); + this.emitLine("// using ", this._options.namespace, ";"); + this.emitLine("//"); + this.forEachTopLevel("none", (t, topLevelName) => { + let rhs: Sourcelike; + if (t instanceof EnumType) { + rhs = [ + "JsonSerializer.Deserialize<", + topLevelName, + ">(jsonString)", + ]; + } else { + rhs = [topLevelName, ".FromJson(jsonString)"]; + } + + this.emitLine( + "// var ", + modifySource(camelCase, topLevelName), + " = ", + rhs, + ";", + ); + }); + + // fix: should this be an option? Or respond to an existing option? + this.emitLine("#nullable enable"); + this.emitLine("#pragma warning disable CS8618"); + this.emitLine("#pragma warning disable CS8601"); + this.emitLine("#pragma warning disable CS8603"); + } + + private converterForType(t: Type): Name | undefined { + let xf = transformationForType(t); + + if (xf === undefined && t instanceof UnionType) { + const maybeNullable = nullableFromUnion(t); + if (maybeNullable !== null) { + t = maybeNullable; + xf = transformationForType(t); + } + } + + if (xf === undefined) return undefined; + + if (alwaysApplyTransformation(xf)) return undefined; + + return defined(this.nameForTransformation(t)); + } + + protected attributesForProperty( + property: ClassProperty, + _name: Name, + _c: ClassType, + jsonName: string, + ): Sourcelike[] | undefined { + if (!this._needAttributes) return undefined; + + const attributes: Sourcelike[] = []; + + const jsonPropertyName = this._options.dense + ? denseJsonPropertyName + : "JsonPropertyName"; + const escapedName = utf16StringEscape(jsonName); + const isNullable = followTargetType(property.type).isNullable; + const isOptional = property.isOptional; + + if (isOptional && !isNullable) { + attributes.push([ + "[", + "JsonIgnore", + "(Condition = JsonIgnoreCondition.WhenWritingNull)]", + ]); + } + + // const requiredClass = this._options.dense ? "R" : "Required"; + // const nullValueHandlingClass = this._options.dense ? "N" : "NullValueHandling"; + // const nullValueHandling = isOptional && !isNullable ? [", NullValueHandling = ", nullValueHandlingClass, ".Ignore"] : []; + // let required: Sourcelike; + // if (!this._options.checkRequired || (isOptional && isNullable)) { + // required = [nullValueHandling]; + // } else if (isOptional && !isNullable) { + // required = [", Required = ", requiredClass, ".DisallowNull", nullValueHandling]; + // } else if (!isOptional && isNullable) { + // required = [", Required = ", requiredClass, ".AllowNull"]; + // } else { + // required = [", Required = ", requiredClass, ".Always", nullValueHandling]; + // } + + attributes.push(["[", jsonPropertyName, '("', escapedName, '")]']); + + const converter = this.converterForType(property.type); + if (converter !== undefined) { + attributes.push(["[JsonConverter(typeof(", converter, "))]"]); + } + + return attributes; + } + + protected blankLinesBetweenAttributes(): boolean { + return this._needAttributes && !this._options.dense; + } + + // The "this" type can't be `dynamic`, so we have to force it to `object`. + private topLevelResultType(t: Type): Sourcelike { + return t.kind === "any" || t.kind === "none" + ? "object" + : this.csType(t); + } + + private emitFromJsonForTopLevel(t: Type, name: Name): void { + if (t instanceof EnumType) return; + + let partial: string; + let typeKind: string; + const definedType = this.namedTypeToNameForTopLevel(t); + if (definedType !== undefined) { + partial = "partial "; + typeKind = definedType instanceof ClassType ? "class" : "struct"; + } else { + partial = ""; + typeKind = "class"; + } + + const csType = this.topLevelResultType(t); + this.emitType( + undefined, + AccessModifier.Public, + [partial, typeKind], + name, + this.baseclassForType(t), + () => { + // FIXME: Make FromJson a Named + this.emitExpressionMember( + ["public static ", csType, " FromJson(string json)"], + [ + "JsonSerializer.Deserialize<", + csType, + ">(json, ", + this._options.namespace, + ".Converter.Settings)", + ], + ); + }, + ); + } + + private emitDecoderSwitch(emitBody: () => void): void { + this.emitLine("switch (reader.TokenType)"); + this.emitBlock(emitBody); + } + + private emitTokenCase(tokenType: string): void { + this.emitLine("case JsonTokenType.", tokenType, ":"); + } + + private emitThrow(message: Sourcelike): void { + this.emitLine("throw new Exception(", message, ");"); + } + + private deserializeTypeCode(typeName: Sourcelike): Sourcelike { + switch (typeName) { + case "bool": + return ["reader.GetBoolean()"]; + case "long": + return ["reader.GetInt64()"]; + case "decimal": + return ["reader.GetDecimal()"]; + case "double": + return ["reader.GetDouble()"]; + case "string": + return ["reader.GetString()"]; + default: + return [ + "JsonSerializer.Deserialize<", + typeName, + ">(ref reader, options)", + ]; + } + } + + private serializeValueCode(value: Sourcelike): Sourcelike { + if (value !== "null") { + return ["JsonSerializer.Serialize(writer, ", value, ", options)"]; + } + + return ["writer.WriteNullValue()"]; + } + + private emitSerializeClass(): void { + // FIXME: Make Serialize a Named + this.emitType( + undefined, + AccessModifier.Public, + "static class", + "Serialize", + undefined, + () => { + // Sometimes multiple top-levels will resolve to the same type, so we have to take care + // not to emit more than one extension method for the same type. + const seenTypes = new Set(); + this.forEachTopLevel("none", (t) => { + // FIXME: Make ToJson a Named + if (!seenTypes.has(t)) { + seenTypes.add(t); + this.emitExpressionMember( + [ + "public static string ToJson(this ", + this.topLevelResultType(t), + " self)", + ], + [ + "JsonSerializer.Serialize(self, ", + this._options.namespace, + ".Converter.Settings)", + ], + ); + } + }); + }, + ); + } + + private emitCanConvert(expr: Sourcelike): void { + this.emitExpressionMember( + "public override bool CanConvert(Type t)", + expr, + ); + } + + private emitReadJson(emitBody: () => void, csType: Sourcelike): void { + this.emitLine( + "public override ", + csType, + " Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)", + ); + this.emitBlock(emitBody); + } + + private emitWriteJson( + variable: string, + emitBody: () => void, + csType: Sourcelike, + ): void { + this.emitLine( + "public override void Write(Utf8JsonWriter writer, ", + csType, + " ", + variable, + ", JsonSerializerOptions options)", + ); + this.emitBlock(emitBody); + } + + private converterObject(converterName: Name): Sourcelike { + // FIXME: Get a singleton + return [converterName, ".Singleton"]; + } + + private emitConverterClass(): void { + // FIXME: Make Converter a Named + const converterName: Sourcelike = ["Converter"]; + this.emitType( + undefined, + AccessModifier.Internal, + "static class", + converterName, + undefined, + () => { + // Do not use .Web as defaults. That turns on caseInsensitive property names and will fail the keywords test. + this.emitLine( + "public static readonly JsonSerializerOptions Settings = new(JsonSerializerDefaults.General)", + ); + this.emitBlock(() => { + // this.emitLine("MetadataPropertyHandling = MetadataPropertyHandling.Ignore,"); + // this.emitLine("DateParseHandling = DateParseHandling.None,"); + this.emitLine("Converters ="); + this.emitLine("{"); + this.indent(() => { + for (const [t, converter] of this + .typesWithNamedTransformations) { + if ( + alwaysApplyTransformation( + defined(transformationForType(t)), + ) + ) { + this.emitLine( + this.converterObject(converter), + ",", + ); + } + } + + this.emitLine("new DateOnlyConverter(),"); + this.emitLine("new TimeOnlyConverter(),"); + this.emitLine("IsoDateTimeOffsetConverter.Singleton"); + // this.emitLine("new IsoDateTimeConverter { DateTimeStyles = DateTimeStyles.AssumeUniversal }"); + }); + this.emitLine("},"); + }, true); + }, + ); + } + + private emitDecoderTransformerCase( + tokenCases: string[], + variableName: string, + xfer: Transformer | undefined, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + ): void { + if (xfer === undefined) return; + + for (const tokenCase of tokenCases) { + this.emitTokenCase(tokenCase); + } + + this.indent(() => { + const allHandled = this.emitDecodeTransformer( + xfer, + targetType, + emitFinish, + variableName, + ); + if (!allHandled) { + this.emitLine("break;"); + } + }); + } + + private emitConsume( + value: Sourcelike, + consumer: Transformer | undefined, + targetType: Type, + emitFinish: (variableName: Sourcelike) => void, + ): boolean { + if (consumer === undefined) { + emitFinish(value); + return true; + } + + return this.emitTransformer(value, consumer, targetType, emitFinish); + } + + private emitDecodeTransformer( + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + variableName = "value", + ): boolean { + if (xfer instanceof DecodingTransformer) { + const source = xfer.sourceType; + const converter = this.converterForType(targetType); + if (converter !== undefined) { + const typeSource = this.csType(targetType); + this.emitLine( + "var converter = ", + this.converterObject(converter), + ";", + ); + this.emitLine( + "var ", + variableName, + " = (", + typeSource, + ")converter.ReadJson(reader, typeof(", + typeSource, + "), null, serializer);", + ); + } else if (source.kind !== "null") { + const output = + targetType.kind === "double" ? targetType : source; + this.emitLine( + "var ", + variableName, + " = ", + this.deserializeTypeCode(this.csType(output)), + ";", + ); + } + + return this.emitConsume( + variableName, + xfer.consumer, + targetType, + emitFinish, + ); + } + + if (xfer instanceof ArrayDecodingTransformer) { + // FIXME: Consume StartArray + if (!(targetType instanceof ArrayType)) { + return panic("Array decoding must produce an array type"); + } + + // FIXME: handle EOF + this.emitLine("reader.Read();"); + this.emitLine( + "var ", + variableName, + " = new List<", + this.csType(targetType.items), + ">();", + ); + this.emitLine("while (reader.TokenType != JsonToken.EndArray)"); + this.emitBlock(() => { + this.emitDecodeTransformer( + xfer.itemTransformer, + xfer.itemTargetType, + (v) => this.emitLine(variableName, ".Add(", v, ");"), + "arrayItem", + ); + // FIXME: handle EOF + this.emitLine("reader.Read();"); + }); + let result: Sourcelike = variableName; + if (!this._options.useList) { + result = [result, ".ToArray()"]; + } + + emitFinish(result); + return true; + } + + if (xfer instanceof DecodingChoiceTransformer) { + this.emitDecoderSwitch(() => { + const nullTransformer = xfer.nullTransformer; + if (nullTransformer !== undefined) { + this.emitTokenCase("Null"); + this.indent(() => { + const allHandled = this.emitDecodeTransformer( + nullTransformer, + targetType, + emitFinish, + "null", + ); + if (!allHandled) { + this.emitLine("break"); + } + }); + } + + this.emitDecoderTransformerCase( + ["Number"], + "integerValue", + xfer.integerTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["Number"], + // xfer.integerTransformer === undefined ? ["Integer", "Float"] : ["Float"], + "doubleValue", + xfer.doubleTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["True", "False"], + "boolValue", + xfer.boolTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + // ["String", "Date"], + ["String"], + "stringValue", + xfer.stringTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["StartObject"], + "objectValue", + xfer.objectTransformer, + targetType, + emitFinish, + ); + this.emitDecoderTransformerCase( + ["StartArray"], + "arrayValue", + xfer.arrayTransformer, + targetType, + emitFinish, + ); + }); + return false; + } + + return panic("Unknown transformer"); + } + + private stringCaseValue(t: Type, stringCase: string): Sourcelike { + if (t.kind === "string") { + return ['"', utf16StringEscape(stringCase), '"']; + } + if (t instanceof EnumType) { + return [ + this.nameForNamedType(t), + ".", + this.nameForEnumCase(t, stringCase), + ]; + } + + return panic(`Type ${t.kind} does not have string cases`); + } + + private emitTransformer( + variable: Sourcelike, + xfer: Transformer, + targetType: Type, + emitFinish: (value: Sourcelike) => void, + ): boolean { + function directTargetType(continuation: Transformer | undefined): Type { + if (continuation === undefined) { + return targetType; + } + + return followTargetType(continuation.sourceType); + } + + if (xfer instanceof ChoiceTransformer) { + const caseXfers = xfer.transformers; + if ( + caseXfers.length > 1 && + caseXfers.every( + (caseXfer) => caseXfer instanceof StringMatchTransformer, + ) + ) { + this.emitLine("switch (", variable, ")"); + this.emitBlock(() => { + for (const caseXfer of caseXfers) { + const matchXfer = caseXfer as StringMatchTransformer; + const value = this.stringCaseValue( + followTargetType(matchXfer.sourceType), + matchXfer.stringCase, + ); + this.emitLine("case ", value, ":"); + this.indent(() => { + const allDone = this.emitTransformer( + variable, + matchXfer.transformer, + targetType, + emitFinish, + ); + if (!allDone) { + this.emitLine("break;"); + } + }); + } + }); + // FIXME: Can we check for exhaustiveness? For enums it should be easy. + return false; + } + + for (const caseXfer of caseXfers) { + this.emitTransformer( + variable, + caseXfer, + targetType, + emitFinish, + ); + } + } else if (xfer instanceof UnionMemberMatchTransformer) { + const memberType = xfer.memberType; + const maybeNullable = nullableFromUnion(xfer.sourceType); + let test: Sourcelike; + let member: Sourcelike; + if (maybeNullable !== null) { + if (memberType.kind === "null") { + test = [variable, " == null"]; + member = "null"; + } else { + test = [variable, " != null"]; + member = variable; + } + } else if (memberType.kind === "null") { + test = [variable, ".IsNull"]; + member = "null"; + } else { + const memberName = this.nameForUnionMember( + xfer.sourceType, + memberType, + ); + member = [variable, ".", memberName]; + test = [member, " != null"]; + } + + if (memberType.kind !== "null" && isValueType(memberType)) { + member = [member, ".Value"]; + } + + this.emitLine("if (", test, ")"); + this.emitBlock(() => + this.emitTransformer( + member, + xfer.transformer, + targetType, + emitFinish, + ), + ); + } else if (xfer instanceof StringMatchTransformer) { + const value = this.stringCaseValue( + followTargetType(xfer.sourceType), + xfer.stringCase, + ); + this.emitLine("if (", variable, " == ", value, ")"); + this.emitBlock(() => + this.emitTransformer( + variable, + xfer.transformer, + targetType, + emitFinish, + ), + ); + } else if (xfer instanceof EncodingTransformer) { + const converter = this.converterForType(xfer.sourceType); + if (converter !== undefined) { + this.emitLine( + "var converter = ", + this.converterObject(converter), + ";", + ); + this.emitLine( + "converter.WriteJson(writer, ", + variable, + ", serializer);", + ); + } else { + this.emitLine(this.serializeValueCode(variable), ";"); + } + + emitFinish([]); + return true; + } else if (xfer instanceof ArrayEncodingTransformer) { + this.emitLine("writer.WriteStartArray();"); + const itemVariable = "arrayItem"; + this.emitLine("foreach (var ", itemVariable, " in ", variable, ")"); + this.emitBlock(() => { + this.emitTransformer( + itemVariable, + xfer.itemTransformer, + xfer.itemTargetType, + () => { + return; + }, + ); + }); + this.emitLine("writer.WriteEndArray();"); + emitFinish([]); + return true; + } else if (xfer instanceof ParseStringTransformer) { + const immediateTargetType = + xfer.consumer === undefined + ? targetType + : xfer.consumer.sourceType; + switch (immediateTargetType.kind) { + case "date-time": + this.emitLine("DateTimeOffset dt;"); + this.emitLine( + "if (DateTimeOffset.TryParse(", + variable, + ", out dt))", + ); + this.emitBlock(() => + this.emitConsume( + "dt", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + case "uuid": + this.emitLine("Guid guid;"); + this.emitLine( + "if (Guid.TryParse(", + variable, + ", out guid))", + ); + this.emitBlock(() => + this.emitConsume( + "guid", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + case "uri": + this.emitLine("try"); + this.emitBlock(() => { + // this.emitLine("var uri = new Uri(", variable, ");"); + // The default value about:blank should never happen, but this way we avoid a null reference warning. + this.emitLine('var uri = new Uri("about:blank");'); + this.emitLine( + "if (!string.IsNullOrEmpty(stringValue))", + ); + this.emitBlock(() => { + this.emitLine("uri = new Uri(", variable, ");"); + }); + this.emitConsume( + "uri", + xfer.consumer, + targetType, + emitFinish, + ); + }); + this.emitLine("catch (UriFormatException) {}"); + break; + case "integer": + this.emitLine("long l;"); + this.emitLine("if (Int64.TryParse(", variable, ", out l))"); + this.emitBlock(() => + this.emitConsume( + "l", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + case "bool": + this.emitLine("bool b;"); + this.emitLine( + "if (Boolean.TryParse(", + variable, + ", out b))", + ); + this.emitBlock(() => + this.emitConsume( + "b", + xfer.consumer, + targetType, + emitFinish, + ), + ); + break; + default: + return panic( + `Parsing string to ${immediateTargetType.kind} not supported`, + ); + } + } else if (xfer instanceof StringifyTransformer) { + switch (xfer.sourceType.kind) { + case "date-time": + return this.emitConsume( + [ + variable, + '.ToString("o", System.Globalization.CultureInfo.InvariantCulture)', + ], + xfer.consumer, + targetType, + emitFinish, + ); + case "uuid": + return this.emitConsume( + [ + variable, + '.ToString("D", System.Globalization.CultureInfo.InvariantCulture)', + ], + xfer.consumer, + targetType, + emitFinish, + ); + case "integer": + case "uri": + return this.emitConsume( + [variable, ".ToString()"], + xfer.consumer, + targetType, + emitFinish, + ); + case "bool": + this.emitLine( + "var boolString = ", + variable, + ' ? "true" : "false";', + ); + return this.emitConsume( + "boolString", + xfer.consumer, + targetType, + emitFinish, + ); + default: + return panic( + `Stringifying ${xfer.sourceType.kind} not supported`, + ); + } + } else if (xfer instanceof StringProducerTransformer) { + const value = this.stringCaseValue( + directTargetType(xfer.consumer), + xfer.result, + ); + return this.emitConsume( + value, + xfer.consumer, + targetType, + emitFinish, + ); + } else if (xfer instanceof MinMaxLengthCheckTransformer) { + const min = xfer.minLength; + const max = xfer.maxLength; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, ".Length >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, ".Length <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => + this.emitConsume( + variable, + xfer.consumer, + targetType, + emitFinish, + ), + ); + return false; + } else if (xfer instanceof MinMaxValueTransformer) { + const min = xfer.minimum; + const max = xfer.maximum; + const conditions: Sourcelike[] = []; + + if (min !== undefined) { + conditions.push([variable, " >= ", min.toString()]); + } + + if (max !== undefined) { + conditions.push([variable, " <= ", max.toString()]); + } + + this.emitLine("if (", arrayIntercalate([" && "], conditions), ")"); + this.emitBlock(() => + this.emitConsume( + variable, + xfer.consumer, + targetType, + emitFinish, + ), + ); + return false; + } else if (xfer instanceof UnionInstantiationTransformer) { + if (!(targetType instanceof UnionType)) { + return panic( + "Union instantiation transformer must produce a union type", + ); + } + + const maybeNullable = nullableFromUnion(targetType); + if (maybeNullable !== null) { + emitFinish(variable); + } else { + const unionName = this.nameForNamedType(targetType); + let initializer: Sourcelike; + if (xfer.sourceType.kind === "null") { + initializer = " "; + } else { + const memberName = this.nameForUnionMember( + targetType, + xfer.sourceType, + ); + initializer = [" ", memberName, " = ", variable, " "]; + } + + emitFinish(["new ", unionName, " {", initializer, "}"]); + } + + return true; + } else { + return panic("Unknown transformer"); + } + + return false; + } + + private emitTransformation(converterName: Name, t: Type): void { + const xf = defined(transformationForType(t)); + const reverse = xf.reverse; + const targetType = xf.targetType; + const xfer = xf.transformer; + const csType = this.csType(targetType); + // const haveNullable = isValueType(targetType); + + // if (haveNullable) { + // converterName = ['Nullable', converterName]; + // csType = [csType, "?"]; + // } + this.emitType( + undefined, + AccessModifier.Internal, + "class", + converterName, + ["JsonConverter<", csType, ">"], + () => { + const canConvertExpr: Sourcelike = [ + "t == typeof(", + csType, + ")", + ]; + this.emitCanConvert(canConvertExpr); + this.ensureBlankLine(); + this.emitReadJson(() => { + // FIXME: It's unsatisfying that we need this. The reason is that we not + // only match T, but also T?. If we didn't, then the T in T? would not be + // deserialized with our converter but with the default one. Can we check + // whether the type is a nullable? + // FIXME: This could duplicate one of the cases handled below in + // `emitDecodeTransformer`. + // if (haveNullable && !(targetType instanceof UnionType)) { + // this.emitLine("if (reader.TokenType == JsonTokenType.Null) return null;"); + // } + + const allHandled = this.emitDecodeTransformer( + xfer, + targetType, + (v) => this.emitLine("return ", v, ";"), + ); + if (!allHandled) { + this.emitThrow([ + '"Cannot unmarshal type ', + csType, + '"', + ]); + } + }, csType); + this.ensureBlankLine(); + this.emitWriteJson( + "value", + () => { + // FIXME: See above. + // if (haveNullable && !(targetType instanceof UnionType)) { + // this.emitLine("if (value == null)"); + // this.emitBlock(() => { + // this.emitLine("writer.WriteNullValue();"); + // this.emitLine("return;"); + // }); + // } + + const allHandled = this.emitTransformer( + "value", + reverse.transformer, + reverse.targetType, + () => this.emitLine("return;"), + ); + if (!allHandled) { + this.emitThrow([ + '"Cannot marshal type ', + csType, + '"', + ]); + } + }, + csType, + ); + this.ensureBlankLine(); + this.emitLine( + "public static readonly ", + converterName, + " Singleton = new ", + converterName, + "();", + ); + }, + ); + } + + protected emitRequiredHelpers(): void { + if (this._needHelpers) { + this.forEachTopLevel("leading-and-interposing", (t, n) => + this.emitFromJsonForTopLevel(t, n), + ); + this.ensureBlankLine(); + this.emitSerializeClass(); + } + + if ( + this._needHelpers || + (this._needAttributes && (this.haveNamedUnions || this.haveEnums)) + ) { + this.ensureBlankLine(); + this.emitConverterClass(); + this.forEachTransformation("leading-and-interposing", (n, t) => + this.emitTransformation(n, t), + ); + this.emitMultiline(` +public class DateOnlyConverter : JsonConverter +{ + private readonly string serializationFormat; + public DateOnlyConverter() : this(null) { } + + public DateOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "yyyy-MM-dd"; + } + + public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return DateOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); +} + +public class TimeOnlyConverter : JsonConverter +{ + private readonly string serializationFormat; + + public TimeOnlyConverter() : this(null) { } + + public TimeOnlyConverter(string? serializationFormat) + { + this.serializationFormat = serializationFormat ?? "HH:mm:ss.fff"; + } + + public override TimeOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetString(); + return TimeOnly.Parse(value!); + } + + public override void Write(Utf8JsonWriter writer, TimeOnly value, JsonSerializerOptions options) + => writer.WriteStringValue(value.ToString(serializationFormat)); +} + +internal class IsoDateTimeOffsetConverter : JsonConverter +{ + public override bool CanConvert(Type t) => t == typeof(DateTimeOffset); + + private const string DefaultDateTimeFormat = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; + + private DateTimeStyles _dateTimeStyles = DateTimeStyles.RoundtripKind; + private string? _dateTimeFormat; + private CultureInfo? _culture; + + public DateTimeStyles DateTimeStyles + { + get => _dateTimeStyles; + set => _dateTimeStyles = value; + } + + public string? DateTimeFormat + { + get => _dateTimeFormat ?? string.Empty; + set => _dateTimeFormat = (string.IsNullOrEmpty(value)) ? null : value; + } + + public CultureInfo Culture + { + get => _culture ?? CultureInfo.CurrentCulture; + set => _culture = value; + } + + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + string text; + + + if ((_dateTimeStyles & DateTimeStyles.AdjustToUniversal) == DateTimeStyles.AdjustToUniversal + || (_dateTimeStyles & DateTimeStyles.AssumeUniversal) == DateTimeStyles.AssumeUniversal) + { + value = value.ToUniversalTime(); + } + + text = value.ToString(_dateTimeFormat ?? DefaultDateTimeFormat, Culture); + + writer.WriteStringValue(text); + } + + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + string? dateText = reader.GetString(); + + if (string.IsNullOrEmpty(dateText) == false) + { + if (!string.IsNullOrEmpty(_dateTimeFormat)) + { + return DateTimeOffset.ParseExact(dateText, _dateTimeFormat, Culture, _dateTimeStyles); + } + else + { + return DateTimeOffset.Parse(dateText, Culture, _dateTimeStyles); + } + } + else + { + return default(DateTimeOffset); + } + } + + + public static readonly IsoDateTimeOffsetConverter Singleton = new IsoDateTimeOffsetConverter(); +}`); + } + } + + protected needNamespace(): boolean { + return this._needNamespaces; + } +} diff --git a/packages/quicktype-core/src/language/CSharp/constants.ts b/packages/quicktype-core/src/language/CSharp/constants.ts new file mode 100644 index 000000000..0fafc49e8 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/constants.ts @@ -0,0 +1,79 @@ +export const keywords = [ + "abstract", + "as", + "base", + "bool", + "break", + "byte", + "case", + "catch", + "char", + "checked", + "class", + "const", + "continue", + "decimal", + "default", + "delegate", + "do", + "double", + "else", + "enum", + "event", + "explicit", + "extern", + "false", + "finally", + "fixed", + "float", + "for", + "foreach", + "goto", + "if", + "implicit", + "in", + "int", + "interface", + "internal", + "is", + "lock", + "long", + "namespace", + "new", + "null", + "object", + "operator", + "out", + "override", + "params", + "private", + "protected", + "public", + "readonly", + "ref", + "return", + "sbyte", + "sealed", + "short", + "sizeof", + "stackalloc", + "static", + "string", + "struct", + "switch", + "this", + "throw", + "true", + "try", + "typeof", + "uint", + "ulong", + "unchecked", + "unsafe", + "ushort", + "using", + "virtual", + "void", + "volatile", + "while", +] as const; diff --git a/packages/quicktype-core/src/language/CSharp/index.ts b/packages/quicktype-core/src/language/CSharp/index.ts new file mode 100644 index 000000000..83dd8afda --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/index.ts @@ -0,0 +1,9 @@ +export { + CSharpTargetLanguage, + cSharpOptions, + newtonsoftCSharpOptions, + systemTextJsonCSharpOptions, +} from "./language"; +export { CSharpRenderer } from "./CSharpRenderer"; +export { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer"; +export { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer"; diff --git a/packages/quicktype-core/src/language/CSharp/language.ts b/packages/quicktype-core/src/language/CSharp/language.ts new file mode 100644 index 000000000..79562aa27 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/language.ts @@ -0,0 +1,218 @@ +import type { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, + Type, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { NewtonsoftCSharpRenderer } from "./NewtonSoftCSharpRenderer"; +import { SystemTextJsonCSharpRenderer } from "./SystemTextJsonCSharpRenderer"; +import { needTransformerForType } from "./utils"; + +export interface OutputFeatures { + attributes: boolean; + helpers: boolean; +} + +export type CSharpTypeForAny = "object" | "dynamic"; + +export const cSharpOptions = { + framework: new EnumOption( + "framework", + "Serialization framework", + { + NewtonSoft: "NewtonSoft", + SystemTextJson: "SystemTextJson", + } as const, + "NewtonSoft", + ), + useList: new EnumOption( + "array-type", + "Use T[] or List", + { + array: false, + list: true, + }, + "array", + ), + dense: new EnumOption( + "density", + "Property density", + { + normal: false, + dense: true, + } as const, + "normal", + "secondary", + ), + // FIXME: Do this via a configurable named eventually. + namespace: new StringOption( + "namespace", + "Generated namespace", + "NAME", + "QuickType", + ), + version: new EnumOption( + "csharp-version", + "C# version", + { + "5": 5, + "6": 6, + } as const, + "6", + "secondary", + ), + virtual: new BooleanOption("virtual", "Generate virtual properties", false), + typeForAny: new EnumOption( + "any-type", + 'Type to use for "any"', + { + object: "object", + dynamic: "dynamic", + } as const, + "object", + "secondary", + ), + useDecimal: new EnumOption( + "number-type", + "Type to use for numbers", + { + double: false, + decimal: true, + } as const, + "double", + "secondary", + ), + features: new EnumOption( + "features", + "Output features", + { + complete: { namespaces: true, helpers: true, attributes: true }, + "attributes-only": { + namespaces: true, + helpers: false, + attributes: true, + }, + "just-types-and-namespace": { + namespaces: true, + helpers: false, + attributes: false, + }, + "just-types": { + namespaces: true, + helpers: false, + attributes: false, + }, + } as const, + "complete", + ), + baseclass: new EnumOption( + "base-class", + "Base class", + { + EntityData: "EntityData", + Object: undefined, + } as const, + "Object", + "secondary", + ), + checkRequired: new BooleanOption( + "check-required", + "Fail if required properties are missing", + false, + ), + keepPropertyName: new BooleanOption( + "keep-property-name", + "Keep original field name generate", + false, + ), +} as const; + +export const newtonsoftCSharpOptions = Object.assign({}, cSharpOptions, {}); + +export const systemTextJsonCSharpOptions = Object.assign({}, cSharpOptions, {}); + +export const cSharpLanguageConfig = { + displayName: "C#", + names: ["cs", "csharp"], + extension: "cs", +} as const; + +export class CSharpTargetLanguage extends TargetLanguage< + typeof cSharpLanguageConfig +> { + public constructor() { + super(cSharpLanguageConfig); + } + + public getOptions(): typeof cSharpOptions { + return cSharpOptions; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + mapping.set("date", "date-time"); + mapping.set("time", "date-time"); + mapping.set("date-time", "date-time"); + mapping.set("uuid", "uuid"); + mapping.set("uri", "uri"); + mapping.set("integer-string", "integer-string"); + mapping.set("bool-string", "bool-string"); + return mapping; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public needsTransformerForType(t: Type): boolean { + const need = needTransformerForType(t); + return need !== "none" && need !== "nullable"; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ConvenienceRenderer { + const options = getOptionValues(cSharpOptions, untypedOptionValues); + + switch (options.framework) { + case "NewtonSoft": + return new NewtonsoftCSharpRenderer( + this, + renderContext, + getOptionValues( + newtonsoftCSharpOptions, + untypedOptionValues, + ), + ); + case "SystemTextJson": + return new SystemTextJsonCSharpRenderer( + this, + renderContext, + getOptionValues( + systemTextJsonCSharpOptions, + untypedOptionValues, + ), + ); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/CSharp/utils.ts b/packages/quicktype-core/src/language/CSharp/utils.ts new file mode 100644 index 000000000..94e9e1ea0 --- /dev/null +++ b/packages/quicktype-core/src/language/CSharp/utils.ts @@ -0,0 +1,164 @@ +import unicode from "unicode-properties"; + +import { + minMaxLengthForType, + minMaxValueForType, +} from "../../attributes/Constraints"; +import { funPrefixNamer } from "../../Naming"; +import type { Sourcelike } from "../../Source"; +import { + type WordInName, + combineWords, + firstUpperWordStyle, + splitIntoWords, + utf16LegalizeCharacters, +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import type { Transformation } from "../../Transformers"; +import { + ArrayType, + EnumType, + type PrimitiveType, + type Type, + UnionType, +} from "../../Type"; +import { nullableFromUnion } from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; + +export enum AccessModifier { + None = "None", + Public = "Public", + Internal = "Internal", +} + +export function noFollow(t: Type): Type { + return t; +} + +export function needTransformerForType( + t: Type, +): "automatic" | "manual" | "nullable" | "none" { + if (t instanceof UnionType) { + const maybeNullable = nullableFromUnion(t); + if (maybeNullable === null) return "automatic"; + if (needTransformerForType(maybeNullable) === "manual") + return "nullable"; + return "none"; + } + + if (t instanceof ArrayType) { + const itemsNeed = needTransformerForType(t.items); + if (itemsNeed === "manual" || itemsNeed === "nullable") + return "automatic"; + return "none"; + } + + if (t instanceof EnumType) return "automatic"; + if (t.kind === "double") + return minMaxValueForType(t) !== undefined ? "manual" : "none"; + if (t.kind === "integer-string" || t.kind === "bool-string") + return "manual"; + if (t.kind === "string") { + return minMaxLengthForType(t) !== undefined ? "manual" : "none"; + } + + return "none"; +} + +export function alwaysApplyTransformation(xf: Transformation): boolean { + const t = xf.targetType; + if (t instanceof EnumType) return true; + if (t instanceof UnionType) return nullableFromUnion(t) === null; + return false; +} + +/** + * The C# type for a given transformed string type. + */ +export function csTypeForTransformedStringType(t: PrimitiveType): Sourcelike { + switch (t.kind) { + case "date-time": + return "DateTimeOffset"; + case "uuid": + return "Guid"; + case "uri": + return "Uri"; + default: + return panic(`Transformed string type ${t.kind} not supported`); + } +} + +export const namingFunction = funPrefixNamer("namer", csNameStyle); +export const namingFunctionKeep = funPrefixNamer("namerKeep", csNameStyleKeep); + +// FIXME: Make a Named? +export const denseJsonPropertyName = "J"; +export const denseRequiredEnumName = "R"; +export const denseNullValueHandlingEnumName = "N"; + +export function isStartCharacter(utf16Unit: number): boolean { + if (unicode.isAlphabetic(utf16Unit)) { + return true; + } + + return utf16Unit === 0x5f; // underscore +} + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + if (["Nd", "Pc", "Mn", "Mc"].includes(category)) { + return true; + } + + return isStartCharacter(utf16Unit); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export function csNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + firstUpperWordStyle, + firstUpperWordStyle, + "", + isStartCharacter, + ); +} + +function csNameStyleKeep(original: string): string { + const words: WordInName[] = [ + { + word: original, + isAcronym: false, + }, + ]; + + const result = combineWords( + words, + legalizeName, + (x) => x, + (x) => x, + (x) => x, + (x) => x, + "", + isStartCharacter, + ); + + // @ts-expect-error needs strong type + return keywords.includes(result) ? `@${result}` : result; +} + +export function isValueType(t: Type): boolean { + if (t instanceof UnionType) { + return nullableFromUnion(t) === null; + } + + return ["integer", "double", "bool", "enum", "date-time", "uuid"].includes( + t.kind, + ); +} diff --git a/packages/quicktype-core/src/language/Crystal.ts b/packages/quicktype-core/src/language/Crystal.ts deleted file mode 100644 index 461b8fe30..000000000 --- a/packages/quicktype-core/src/language/Crystal.ts +++ /dev/null @@ -1,426 +0,0 @@ -import { TargetLanguage } from "../TargetLanguage"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { - legalizeCharacters, - splitIntoWords, - isLetterOrUnderscoreOrDigit, - combineWords, - allLowerWordStyle, - firstUpperWordStyle, - intToHex, - utf32ConcatMap, - escapeNonPrintableMapper, - isPrintable, - isAscii, - isLetterOrUnderscore -} from "../support/Strings"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { UnionType, Type, ClassType, EnumType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Sourcelike, maybeAnnotated } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { Option } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; - -export class CrystalTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext): CrystalRenderer { - return new CrystalRenderer(this, renderContext); - } - - constructor() { - super("Crystal", ["crystal", "cr", "crystallang"], "cr"); - } - - protected get defaultIndentation(): string { - return " "; - } - - protected getOptions(): Option[] { - return []; - } -} - -const keywords = [ - "Any", - "Array", - "Atomic", - "Bool", - "Channel", - "Char", - "Class", - "Enum", - "Enumerable", - "Event", - "Extern", - "Exception", - "File", - "Float", - "Float32", - "Float64", - "GC", - "GZip", - "Hash", - "HTML", - "HTTP", - "Int", - "Int128", - "Int16", - "Int32", - "Int64", - "Int8", - "Iterable", - "Link", - "Logger", - "Math", - "Mutex", - "Nil", - "Number", - "JSON", - "IO", - "Object", - "Pointer", - "Proc", - "Process", - "Range", - "Random", - "Regex", - "Reference", - "Set", - "Signal", - "Slice", - "Spec", - "StaticArray", - "String", - "Struct", - "Symbol", - "System", - "TCPServer", - "TCPSocket", - "Socket", - "Tempfile", - "Termios", - "Time", - "Tuple", - "ThreadLocal", - "UDPSocket", - "UInt128", - "UInt16", - "UInt32", - "UInt64", - "UInt8", - "Union", - "UNIXServer", - "UNIXSocket", - "UUID", - "URI", - "VaList", - "Value", - "Void", - "WeakRef", - "XML", - "YAML", - "Zip", - "Zlib", - "abstract", - "alias", - "as", - "as?", - "asm", - "begin", - "break", - "case", - "class", - "def", - "do", - "else", - "elsif", - "end", - "ensure", - "enum", - "extend", - "false", - "for", - "fun", - "if", - "in", - "include", - "instance_sizeof", - "is_a?", - "lib", - "macro", - "module", - "next", - "nil", - "nil?", - "of", - "out", - "pointerof", - "private", - "protected", - "require", - "rescue", - "return", - "select", - "self", - "sizeof", - "struct", - "super", - "then", - "true", - "type", - "typeof", - "uninitialized", - "union", - "unless", - "until", - "when", - "while", - "with", - "yield" -]; - -function isAsciiLetterOrUnderscoreOrDigit(codePoint: number): boolean { - if (!isAscii(codePoint)) { - return false; - } - return isLetterOrUnderscoreOrDigit(codePoint); -} - -function isAsciiLetterOrUnderscore(codePoint: number): boolean { - if (!isAscii(codePoint)) { - return false; - } - return isLetterOrUnderscore(codePoint); -} - -const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); - -function crystalStyle(original: string, isSnakeCase: boolean): string { - const words = splitIntoWords(original); - - const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; - - const combined = combineWords( - words, - legalizeName, - wordStyle, - wordStyle, - wordStyle, - wordStyle, - isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore - ); - - return combined === "_" ? "_underscore" : combined; -} - -const snakeNamingFunction = funPrefixNamer("default", (original: string) => crystalStyle(original, true)); -const camelNamingFunction = funPrefixNamer("camel", (original: string) => crystalStyle(original, false)); - -function standardUnicodeCrystalEscape(codePoint: number): string { - if (codePoint <= 0xffff) { - return "\\u{" + intToHex(codePoint, 4) + "}"; - } else { - return "\\u{" + intToHex(codePoint, 6) + "}"; - } -} - -const crystalStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape)); - -export class CrystalRenderer extends ConvenienceRenderer { - constructor(targetLanguage: TargetLanguage, renderContext: RenderContext) { - super(targetLanguage, renderContext); - } - - protected makeNamedTypeNamer(): Namer { - return camelNamingFunction; - } - - protected namerForObjectProperty(): Namer | null { - return snakeNamingFunction; - } - - protected makeUnionMemberNamer(): Namer | null { - return camelNamingFunction; - } - - protected makeEnumCaseNamer(): Namer | null { - return camelNamingFunction; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected get commentLineStart(): string { - return "# "; - } - - private nullableCrystalType(t: Type, withIssues: boolean): Sourcelike { - return [this.crystalType(t, withIssues), "?"]; - } - - protected isImplicitCycleBreaker(t: Type): boolean { - const kind = t.kind; - return kind === "array" || kind === "map"; - } - - private crystalType(t: Type, withIssues = false): Sourcelike { - return matchType( - t, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "JSON::Any?"), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Nil"), - _boolType => "Bool", - _integerType => "Int32", - _doubleType => "Float64", - _stringType => "String", - arrayType => ["Array(", this.crystalType(arrayType.items, withIssues), ")"], - classType => this.nameForNamedType(classType), - mapType => ["Hash(String, ", this.crystalType(mapType.values, withIssues), ")"], - _enumType => "String", - unionType => { - const nullable = nullableFromUnion(unionType); - - if (nullable !== null) return this.nullableCrystalType(nullable, withIssues); - - const [hasNull] = removeNullFromUnion(unionType); - - const name = this.nameForNamedType(unionType); - - return hasNull !== null ? ([name, "?"] as Sourcelike) : name; - } - ); - } - - private breakCycle(t: Type, withIssues: boolean): Sourcelike { - return this.crystalType(t, withIssues); - } - - private emitRenameAttribute(propName: Name, jsonName: string): void { - const escapedName = crystalStringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - if (namesDiffer) { - this.emitLine('@[JSON::Field(key: "', escapedName, '")]'); - } - } - - protected emitStructDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - - const structBody = () => - this.forEachClassProperty(c, "none", (name, jsonName, prop) => { - this.ensureBlankLine(); - this.emitDescription(this.descriptionForClassProperty(c, jsonName)); - this.emitRenameAttribute(name, jsonName); - this.emitLine("property ", name, " : ", this.crystalType(prop.type, true)); - }); - - this.emitBlock(["class ", className], structBody); - } - - protected emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line); - this.indent(() => { - this.emitLine("include JSON::Serializable"); - }); - this.ensureBlankLine(); - this.indent(f); - this.emitLine("end"); - } - - protected emitEnum(line: Sourcelike, f: () => void): void { - this.emitLine(line); - this.indent(f); - this.emitLine("end"); - } - - protected emitUnion(u: UnionType, unionName: Name): void { - const isMaybeWithSingleType = nullableFromUnion(u); - - if (isMaybeWithSingleType !== null) { - return; - } - - this.emitDescription(this.descriptionForType(u)); - - const [, nonNulls] = removeNullFromUnion(u); - - let types: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (_name, t) => { - const crystalType = this.breakCycle(t, true); - types.push([crystalType]); - }); - - this.emitLine([ - "alias ", - unionName, - " = ", - types.map(r => r.map(sl => this.sourcelikeToString(sl))).join(" | ") - ]); - } - - protected emitTopLevelAlias(t: Type, name: Name): void { - this.emitLine("alias ", name, " = ", this.crystalType(t)); - } - - protected emitLeadingComments(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - return; - } - - this.emitMultiline( - `# Example code that deserializes and serializes the model: -# -# require "json" -# -# class Location -# include JSON::Serializable -# -# @[JSON::Field(key: "lat")] -# property latitude : Float64 -# -# @[JSON::Field(key: "lng")] -# property longitude : Float64 -# end -# -# class House -# include JSON::Serializable -# property address : String -# property location : Location? -# end -# -# house = House.from_json(%({"address": "Crystal Road 1234", "location": {"lat": 12.3, "lng": 34.5}})) -# house.address # => "Crystal Road 1234" -# house.location # => # -` - ); - } - - protected emitSourceStructure(): void { - this.emitLeadingComments(); - this.ensureBlankLine(); - this.emitLine('require "json"'); - - this.forEachTopLevel( - "leading", - (t, name) => this.emitTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined - ); - - this.forEachObject("leading-and-interposing", (c: ClassType, name: Name) => this.emitStructDefinition(c, name)); - this.forEachUnion("leading-and-interposing", (u, name) => this.emitUnion(u, name)); - } -} diff --git a/packages/quicktype-core/src/language/Crystal/CrystalRenderer.ts b/packages/quicktype-core/src/language/Crystal/CrystalRenderer.ts new file mode 100644 index 000000000..80b27fe57 --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/CrystalRenderer.ts @@ -0,0 +1,242 @@ +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import type { Name, Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import type { TargetLanguage } from "../../TargetLanguage"; +import type { + ClassType, + EnumType, + Type, + UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import { + camelNamingFunction, + crystalStringEscape, + snakeNamingFunction, +} from "./utils"; + +export class CrystalRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + ) { + super(targetLanguage, renderContext); + } + + protected makeNamedTypeNamer(): Namer { + return camelNamingFunction; + } + + protected namerForObjectProperty(): Namer | null { + return snakeNamingFunction; + } + + protected makeUnionMemberNamer(): Namer | null { + return camelNamingFunction; + } + + protected makeEnumCaseNamer(): Namer | null { + return camelNamingFunction; + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected get commentLineStart(): string { + return "# "; + } + + private nullableCrystalType(t: Type, withIssues: boolean): Sourcelike { + return [this.crystalType(t, withIssues), "?"]; + } + + protected isImplicitCycleBreaker(t: Type): boolean { + const kind = t.kind; + return kind === "array" || kind === "map"; + } + + private crystalType(t: Type, withIssues = false): Sourcelike { + return matchType( + t, + (_anyType) => + maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + "JSON::Any?", + ), + (_nullType) => + maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Nil"), + (_boolType) => "Bool", + (_integerType) => "Int32", + (_doubleType) => "Float64", + (_stringType) => "String", + (arrayType) => [ + "Array(", + this.crystalType(arrayType.items, withIssues), + ")", + ], + (classType) => this.nameForNamedType(classType), + (mapType) => [ + "Hash(String, ", + this.crystalType(mapType.values, withIssues), + ")", + ], + (_enumType) => "String", + (unionType) => { + const nullable = nullableFromUnion(unionType); + + if (nullable !== null) + return this.nullableCrystalType(nullable, withIssues); + + const [hasNull] = removeNullFromUnion(unionType); + + const name = this.nameForNamedType(unionType); + + return hasNull !== null ? ([name, "?"] as Sourcelike) : name; + }, + ); + } + + private breakCycle(t: Type, withIssues: boolean): Sourcelike { + return this.crystalType(t, withIssues); + } + + private emitRenameAttribute(propName: Name, jsonName: string): void { + const escapedName = crystalStringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + if (namesDiffer) { + this.emitLine('@[JSON::Field(key: "', escapedName, '")]'); + } + } + + protected emitStructDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + + const structBody = (): void => + this.forEachClassProperty(c, "none", (name, jsonName, prop) => { + this.ensureBlankLine(); + this.emitDescription( + this.descriptionForClassProperty(c, jsonName), + ); + this.emitRenameAttribute(name, jsonName); + this.emitLine( + "property ", + name, + " : ", + this.crystalType(prop.type, true), + ); + }); + + this.emitBlock(["class ", className], structBody); + } + + protected emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line); + this.indent(() => { + this.emitLine("include JSON::Serializable"); + }); + this.ensureBlankLine(); + this.indent(f); + this.emitLine("end"); + } + + protected emitEnum(line: Sourcelike, f: () => void): void { + this.emitLine(line); + this.indent(f); + this.emitLine("end"); + } + + protected emitUnion(u: UnionType, unionName: Name): void { + const isMaybeWithSingleType = nullableFromUnion(u); + + if (isMaybeWithSingleType !== null) { + return; + } + + this.emitDescription(this.descriptionForType(u)); + + const [, nonNulls] = removeNullFromUnion(u); + + const types: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_name, t) => { + const crystalType = this.breakCycle(t, true); + types.push([crystalType]); + }); + + this.emitLine([ + "alias ", + unionName, + " = ", + types + .map((r) => r.map((sl) => this.sourcelikeToString(sl))) + .join(" | "), + ]); + } + + protected emitTopLevelAlias(t: Type, name: Name): void { + this.emitLine("alias ", name, " = ", this.crystalType(t)); + } + + protected emitLeadingComments(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + return; + } + } + + protected emitSourceStructure(): void { + this.emitLeadingComments(); + this.ensureBlankLine(); + this.emitLine('require "json"'); + + this.forEachTopLevel( + "leading", + (t, name) => this.emitTopLevelAlias(t, name), + (t) => this.namedTypeToNameForTopLevel(t) === undefined, + ); + + this.forEachObject( + "leading-and-interposing", + (c: ClassType, name: Name) => this.emitStructDefinition(c, name), + ); + this.forEachUnion("leading-and-interposing", (u, name) => + this.emitUnion(u, name), + ); + } +} diff --git a/packages/quicktype-core/src/language/Crystal/constants.ts b/packages/quicktype-core/src/language/Crystal/constants.ts new file mode 100644 index 000000000..06ff747c2 --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/constants.ts @@ -0,0 +1,138 @@ +export const keywords = [ + "Any", + "Array", + "Atomic", + "Bool", + "Channel", + "Char", + "Class", + "Enum", + "Enumerable", + "Event", + "Extern", + "Exception", + "File", + "Float", + "Float32", + "Float64", + "GC", + "GZip", + "Hash", + "HTML", + "HTTP", + "Int", + "Int128", + "Int16", + "Int32", + "Int64", + "Int8", + "Iterable", + "Link", + "Logger", + "Math", + "Mutex", + "Nil", + "Number", + "JSON", + "IO", + "Object", + "Pointer", + "Proc", + "Process", + "Range", + "Random", + "Regex", + "Reference", + "Set", + "Signal", + "Slice", + "Spec", + "StaticArray", + "String", + "Struct", + "Symbol", + "System", + "TCPServer", + "TCPSocket", + "Socket", + "Tempfile", + "Termios", + "Time", + "Tuple", + "ThreadLocal", + "UDPSocket", + "UInt128", + "UInt16", + "UInt32", + "UInt64", + "UInt8", + "Union", + "UNIXServer", + "UNIXSocket", + "UUID", + "URI", + "VaList", + "Value", + "Void", + "WeakRef", + "XML", + "YAML", + "Zip", + "Zlib", + "abstract", + "alias", + "as", + "as?", + "asm", + "begin", + "break", + "case", + "class", + "def", + "do", + "else", + "elsif", + "end", + "ensure", + "enum", + "extend", + "false", + "for", + "fun", + "if", + "in", + "include", + "instance_sizeof", + "is_a?", + "lib", + "macro", + "module", + "next", + "nil", + "nil?", + "of", + "out", + "pointerof", + "private", + "protected", + "require", + "rescue", + "return", + "select", + "self", + "sizeof", + "struct", + "super", + "then", + "true", + "type", + "typeof", + "uninitialized", + "union", + "unless", + "until", + "when", + "while", + "with", + "yield", +] as const; diff --git a/packages/quicktype-core/src/language/Crystal/index.ts b/packages/quicktype-core/src/language/Crystal/index.ts new file mode 100644 index 000000000..d6b0ce5bc --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/index.ts @@ -0,0 +1,2 @@ +export { CrystalTargetLanguage } from "./language"; +export { CrystalRenderer } from "./CrystalRenderer"; diff --git a/packages/quicktype-core/src/language/Crystal/language.ts b/packages/quicktype-core/src/language/Crystal/language.ts new file mode 100644 index 000000000..85772f2ec --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/language.ts @@ -0,0 +1,30 @@ +import type { RenderContext } from "../../Renderer"; +import { TargetLanguage } from "../../TargetLanguage"; + +import { CrystalRenderer } from "./CrystalRenderer"; + +export const crystalLanguageConfig = { + displayName: "Crystal", + names: ["crystal", "cr", "crystallang"], + extension: "cr", +} as const; + +export class CrystalTargetLanguage extends TargetLanguage< + typeof crystalLanguageConfig +> { + public constructor() { + super(crystalLanguageConfig); + } + + protected makeRenderer(renderContext: RenderContext): CrystalRenderer { + return new CrystalRenderer(this, renderContext); + } + + protected get defaultIndentation(): string { + return " "; + } + + public getOptions(): {} { + return {}; + } +} diff --git a/packages/quicktype-core/src/language/Crystal/utils.ts b/packages/quicktype-core/src/language/Crystal/utils.ts new file mode 100644 index 000000000..1a0c9a27b --- /dev/null +++ b/packages/quicktype-core/src/language/Crystal/utils.ts @@ -0,0 +1,72 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap, +} from "../../support/Strings"; + +function isAsciiLetterOrUnderscoreOrDigit(codePoint: number): boolean { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscoreOrDigit(codePoint); +} + +function isAsciiLetterOrUnderscore(codePoint: number): boolean { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscore(codePoint); +} + +const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); + +function crystalStyle(original: string, isSnakeCase: boolean): string { + const words = splitIntoWords(original); + + const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; + + const combined = combineWords( + words, + legalizeName, + wordStyle, + wordStyle, + wordStyle, + wordStyle, + isSnakeCase ? "_" : "", + isAsciiLetterOrUnderscore, + ); + + return combined === "_" ? "_underscore" : combined; +} + +export const snakeNamingFunction = funPrefixNamer( + "default", + (original: string) => crystalStyle(original, true), +); +export const camelNamingFunction = funPrefixNamer("camel", (original: string) => + crystalStyle(original, false), +); + +function standardUnicodeCrystalEscape(codePoint: number): string { + if (codePoint <= 0xffff) { + return "\\u{" + intToHex(codePoint, 4) + "}"; + } else { + return "\\u{" + intToHex(codePoint, 6) + "}"; + } +} + +export const crystalStringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, standardUnicodeCrystalEscape), +); diff --git a/packages/quicktype-core/src/language/Dart.ts b/packages/quicktype-core/src/language/Dart/DartRenderer.ts similarity index 55% rename from packages/quicktype-core/src/language/Dart.ts rename to packages/quicktype-core/src/language/Dart/DartRenderer.ts index 1dd8032cd..e81524ba9 100644 --- a/packages/quicktype-core/src/language/Dart.ts +++ b/packages/quicktype-core/src/language/Dart/DartRenderer.ts @@ -1,246 +1,77 @@ import { - ClassProperty, - ClassType, + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../../Source"; +import { decapitalize, snakeCase } from "../../support/Strings"; +import { defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + type ClassProperty, + type ClassType, EnumType, - PrimitiveStringTypeKind, - TransformedStringTypeKind, - Type, - UnionType -} from "../Type"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; -import { maybeAnnotated, modifySource, Sourcelike } from "../Source"; + type Type, + type UnionType, +} from "../../Type"; import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - decapitalize, - escapeNonPrintableMapper, - firstUpperWordStyle, - isAscii, - isDigit, - isLetter, - isPrintable, - snakeCase, - splitIntoWords, - standardUnicodeHexEscape, - utf16ConcatMap, - utf16LegalizeCharacters -} from "../support/Strings"; - -import { StringTypeMapping } from "../TypeBuilder"; - -import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; -import { BooleanOption, getOptionValues, Option, OptionValues, StringOption } from "../RendererOptions"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { defined } from "../support/Support"; -import { RenderContext } from "../Renderer"; - -export const dartOptions = { - nullSafety: new BooleanOption("null-safety", "Null Safety", true), - justTypes: new BooleanOption("just-types", "Types only", false), - codersInClass: new BooleanOption("coders-in-class", "Put encoder & decoder in Class", false), - methodNamesWithMap: new BooleanOption("from-map", "Use method names fromMap() & toMap()", false, "secondary"), - requiredProperties: new BooleanOption("required-props", "Make all properties required", false), - finalProperties: new BooleanOption("final-props", "Make all properties final", false), - generateCopyWith: new BooleanOption("copy-with", "Generate CopyWith method", false), - useFreezed: new BooleanOption( - "use-freezed", - "Generate class definitions with @freezed compatibility", - false, - "secondary" - ), - useHive: new BooleanOption("use-hive", "Generate annotations for Hive type adapters", false, "secondary"), - useJsonAnnotation: new BooleanOption( - "use-json-annotation", - "Generate annotations for json_serializable", - false, - "secondary" - ), - partName: new StringOption("part-name", "Use this name in `part` directive", "NAME", "", "secondary") -}; - -export class DartTargetLanguage extends TargetLanguage { - constructor() { - super("Dart", ["dart"], "dart"); - } - - protected getOptions(): Option[] { - return [ - dartOptions.nullSafety, - dartOptions.justTypes, - dartOptions.codersInClass, - dartOptions.methodNamesWithMap, - dartOptions.requiredProperties, - dartOptions.finalProperties, - dartOptions.generateCopyWith, - dartOptions.useFreezed, - dartOptions.useHive, - dartOptions.useJsonAnnotation, - dartOptions.partName - ]; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date"); - mapping.set("date-time", "date-time"); - return mapping; - } + directlyReachableSingleNamedType, + matchType, + nullableFromUnion, +} from "../../Type/TypeUtils"; - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): DartRenderer { - const options = getOptionValues(dartOptions, untypedOptionValues); - return new DartRenderer(this, renderContext, options); - } -} - -const keywords = [ - "abstract", - "do", - "import", - "super", - "as", - "dynamic", - "in", - "switch", - "assert", - "else", - "interface", - "sync*", - "async", - "enum", - "is", - "this", - "async*", - "export", - "library", - "throw", - "await", - "external", - "mixin", - "true", - "break", - "extends", - "new", - "try", - "case", - "factory", - "null", - "typedef", - "catch", - "false", - "operator", - "var", - "class", - "final", - "part", - "void", - "const", - "finally", - "rethrow", - "while", - "continue", - "for", - "return", - "with", - "covariant", - "get", - "set", - "yield", - "default", - "if", - "static", - "yield*", - "deferred", - "implements", - "int", - "double", - "bool", - "Map", - "List", - "String", - "File", - "fromJson", - "toJson", - "fromMap", - "toMap" -]; - -const typeNamingFunction = funPrefixNamer("types", n => dartNameStyle(true, false, n)); -const propertyNamingFunction = funPrefixNamer("properties", n => dartNameStyle(false, false, n)); -const enumCaseNamingFunction = funPrefixNamer("enum-cases", n => dartNameStyle(true, true, n)); - -// Escape the dollar sign, which is used in string interpolation -const stringEscape = utf16ConcatMap( - escapeNonPrintableMapper(cp => isPrintable(cp) && cp !== 0x24, standardUnicodeHexEscape) -); - -function isStartCharacter(codePoint: number): boolean { - if (codePoint === 0x5f) return false; // underscore - return isAscii(codePoint) && isLetter(codePoint); -} - -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -// FIXME: Handle acronyms consistently. In particular, that means that -// we have to use namers to produce the getter and setter names - we can't -// just capitalize and concatenate. -// https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations -function dartNameStyle(startWithUpper: boolean, upperUnderscore: boolean, original: string): string { - const words = splitIntoWords(original); - const firstWordStyle = upperUnderscore - ? allUpperWordStyle - : startWithUpper - ? firstUpperWordStyle - : allLowerWordStyle; - const restWordStyle = upperUnderscore ? allUpperWordStyle : firstUpperWordStyle; - return combineWords( - words, - legalizeName, - firstWordStyle, - restWordStyle, - firstWordStyle, - restWordStyle, - upperUnderscore ? "_" : "", - isStartCharacter - ); -} +import { keywords } from "./constants"; +import type { dartOptions } from "./language"; +import { + enumCaseNamingFunction, + propertyNamingFunction, + stringEscape, + typeNamingFunction, +} from "./utils"; -type TopLevelDependents = { - encoder: Name; +interface TopLevelDependents { decoder: Name; -}; + encoder: Name; +} export class DartRenderer extends ConvenienceRenderer { - private readonly _gettersAndSettersForPropertyName = new Map(); + private readonly _gettersAndSettersForPropertyName = new Map< + Name, + [Name, Name] + >(); + private _needEnumValues = false; + private classCounter = 0; + private classPropertyCounter = 0; + private readonly _topLevelDependents = new Map(); + private readonly _enumValues = new Map(); - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return keywords; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -279,16 +110,19 @@ export class DartRenderer extends ConvenienceRenderer { return `from${this._options.methodNamesWithMap ? "Map" : "Json"}`; } - protected makeTopLevelDependencyNames(_t: Type, name: Name): DependencyName[] { + protected makeTopLevelDependencyNames( + _t: Type, + name: Name, + ): DependencyName[] { const encoder = new DependencyName( propertyNamingFunction, name.order, - lookup => `${lookup(name)}_${this.toJson}` + (lookup) => `${lookup(name)}_${this.toJson}`, ); const decoder = new DependencyName( propertyNamingFunction, name.order, - lookup => `${lookup(name)}_${this.fromJson}` + (lookup) => `${lookup(name)}_${this.fromJson}`, ); this._topLevelDependents.set(name, { encoder, decoder }); return [encoder, decoder]; @@ -299,10 +133,18 @@ export class DartRenderer extends ConvenienceRenderer { _className: Name, _p: ClassProperty, _jsonName: string, - name: Name + name: Name, ): [Name, Name] { - const getterName = new DependencyName(propertyNamingFunction, name.order, lookup => `get_${lookup(name)}`); - const setterName = new DependencyName(propertyNamingFunction, name.order, lookup => `set_${lookup(name)}`); + const getterName = new DependencyName( + propertyNamingFunction, + name.order, + (lookup) => `get_${lookup(name)}`, + ); + const setterName = new DependencyName( + propertyNamingFunction, + name.order, + (lookup) => `set_${lookup(name)}`, + ); return [getterName, setterName]; } @@ -311,23 +153,36 @@ export class DartRenderer extends ConvenienceRenderer { className: Name, p: ClassProperty, jsonName: string, - name: Name + name: Name, ): Name[] { - const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); + const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter( + c, + className, + p, + jsonName, + name, + ); this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); return getterAndSetterNames; } - protected makeNamedTypeDependencyNames(t: Type, name: Name): DependencyName[] { + protected makeNamedTypeDependencyNames( + t: Type, + name: Name, + ): DependencyName[] { if (!(t instanceof EnumType)) return []; - const enumValue = new DependencyName(propertyNamingFunction, name.order, lookup => `${lookup(name)}_values`); + const enumValue = new DependencyName( + propertyNamingFunction, + name.order, + (lookup) => `${lookup(name)}_values`, + ); this._enumValues.set(t, enumValue); return [enumValue]; } protected emitFileHeader(): void { if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); + this.emitComments(this.leadingComments); } if (this._options.justTypes) return; @@ -337,7 +192,13 @@ export class DartRenderer extends ConvenienceRenderer { this.emitLine("//"); this.forEachTopLevel("none", (_t, name) => { const { decoder } = defined(this._topLevelDependents.get(name)); - this.emitLine("// final ", modifySource(decapitalize, name), " = ", decoder, "(jsonString);"); + this.emitLine( + "// final ", + modifySource(decapitalize, name), + " = ", + decoder, + "(jsonString);", + ); }); } @@ -345,29 +206,43 @@ export class DartRenderer extends ConvenienceRenderer { if (this._options.requiredProperties) { this.emitLine("import 'package:meta/meta.dart';"); } + if (this._options.useFreezed) { - this.emitLine("import 'package:freezed_annotation/freezed_annotation.dart';"); + this.emitLine( + "import 'package:freezed_annotation/freezed_annotation.dart';", + ); } + if (this._options.useHive) { this.emitLine("import 'package:hive/hive.dart';"); } + if (this._options.useJsonAnnotation && !this._options.useFreezed) { // The freezed annotatation import already provides the import for json_annotation - this.emitLine("import 'package:json_annotation/json_annotation.dart';"); + this.emitLine( + "import 'package:json_annotation/json_annotation.dart';", + ); } this.emitLine("import 'dart:convert';"); - if (this._options.useFreezed || this._options.useHive || this._options.useJsonAnnotation) { + if ( + this._options.useFreezed || + this._options.useHive || + this._options.useJsonAnnotation + ) { this.ensureBlankLine(); const optionNameIsEmpty = this._options.partName.length === 0; // FIXME: This should use a `Name`, not `modifySource` const name = modifySource( snakeCase, - optionNameIsEmpty ? [...this.topLevels.keys()][0] : this._options.partName + optionNameIsEmpty + ? [...this.topLevels.keys()][0] + : this._options.partName, ); if (this._options.useFreezed) { this.emitLine("part '", name, ".freezed.dart';"); } + if (!this._options.justTypes) { this.emitLine("part '", name, ".g.dart';"); } @@ -375,7 +250,7 @@ export class DartRenderer extends ConvenienceRenderer { } protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, "///", ""); + this.emitCommentLines(lines, { lineStart: "///", beforeComment: "" }); } protected emitBlock(line: Sourcelike, f: () => void): void { @@ -384,30 +259,51 @@ export class DartRenderer extends ConvenienceRenderer { this.emitLine("}"); } - protected dartType(t: Type, withIssues = false, forceNullable = false): Sourcelike { + protected dartType( + t: Type, + withIssues = false, + forceNullable = false, + ): Sourcelike { const nullable = - forceNullable || (this._options.nullSafety && t.isNullable && !this._options.requiredProperties); - const withNullable = (s: Sourcelike): Sourcelike => (nullable ? [s, "?"] : s); + forceNullable || + (this._options.nullSafety && + t.isNullable && + !this._options.requiredProperties); + const withNullable = (s: Sourcelike): Sourcelike => + nullable ? [s, "?"] : s; return matchType( t, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "dynamic"), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "dynamic"), - _boolType => withNullable("bool"), - _integerType => withNullable("int"), - _doubleType => withNullable("double"), - _stringType => withNullable("String"), - arrayType => withNullable(["List<", this.dartType(arrayType.items, withIssues), ">"]), - classType => withNullable(this.nameForNamedType(classType)), - mapType => withNullable(["Map"]), - enumType => withNullable(this.nameForNamedType(enumType)), - unionType => { + (_anyType) => + maybeAnnotated(withIssues, anyTypeIssueAnnotation, "dynamic"), + (_nullType) => + maybeAnnotated(withIssues, nullTypeIssueAnnotation, "dynamic"), + (_boolType) => withNullable("bool"), + (_integerType) => withNullable("int"), + (_doubleType) => withNullable("double"), + (_stringType) => withNullable("String"), + (arrayType) => + withNullable([ + "List<", + this.dartType(arrayType.items, withIssues), + ">", + ]), + (classType) => withNullable(this.nameForNamedType(classType)), + (mapType) => + withNullable([ + "Map", + ]), + (enumType) => withNullable(this.nameForNamedType(enumType)), + (unionType) => { const maybeNullable = nullableFromUnion(unionType); if (maybeNullable === null) { return "dynamic"; } + return withNullable(this.dartType(maybeNullable, withIssues)); }, - transformedStringType => { + (transformedStringType) => { switch (transformedStringType.kind) { case "date-time": case "date": @@ -415,26 +311,88 @@ export class DartRenderer extends ConvenienceRenderer { default: return withNullable("String"); } - } + }, ); } - protected mapList(isNullable: boolean, itemType: Sourcelike, list: Sourcelike, mapper: Sourcelike): Sourcelike { - if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { - return [list, " == null ? [] : ", "List<", itemType, ">.from(", list, "!.map((x) => ", mapper, "))"]; + protected mapList( + isNullable: boolean, + itemType: Sourcelike, + list: Sourcelike, + mapper: Sourcelike, + ): Sourcelike { + if ( + this._options.nullSafety && + isNullable && + !this._options.requiredProperties + ) { + return [ + list, + " == null ? [] : ", + "List<", + itemType, + ">.from(", + list, + "!.map((x) => ", + mapper, + "))", + ]; } - return ["List<", itemType, ">.from(", list, ".map((x) => ", mapper, "))"]; + + return [ + "List<", + itemType, + ">.from(", + list, + ".map((x) => ", + mapper, + "))", + ]; } - protected mapMap(isNullable: boolean, valueType: Sourcelike, map: Sourcelike, valueMapper: Sourcelike): Sourcelike { - if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { - return ["Map.from(", map, "!).map((k, v) => MapEntry(k, ", valueMapper, "))"]; + protected mapMap( + isNullable: boolean, + valueType: Sourcelike, + map: Sourcelike, + valueMapper: Sourcelike, + ): Sourcelike { + if ( + this._options.nullSafety && + isNullable && + !this._options.requiredProperties + ) { + return [ + "Map.from(", + map, + "!).map((k, v) => MapEntry(k, ", + valueMapper, + "))", + ]; } - return ["Map.from(", map, ").map((k, v) => MapEntry(k, ", valueMapper, "))"]; + + return [ + "Map.from(", + map, + ").map((k, v) => MapEntry(k, ", + valueMapper, + "))", + ]; } - protected mapClass(isNullable: boolean, classType: ClassType, dynamic: Sourcelike) { - if (this._options.nullSafety && isNullable && !this._options.requiredProperties) { + protected mapClass( + isNullable: boolean, + classType: ClassType, + dynamic: Sourcelike, + ): Sourcelike { + if ( + this._options.nullSafety && + isNullable && + !this._options.requiredProperties + ) { return [ dynamic, " == null ? null : ", @@ -443,55 +401,90 @@ export class DartRenderer extends ConvenienceRenderer { this.fromJson, "(", dynamic, - ")" + ")", ]; } - return [this.nameForNamedType(classType), ".", this.fromJson, "(", dynamic, ")"]; + + return [ + this.nameForNamedType(classType), + ".", + this.fromJson, + "(", + dynamic, + ")", + ]; } - //If the first time is the unionType type, after nullableFromUnion conversion, - //the isNullable property will become false, which is obviously wrong, - //so add isNullable property - protected fromDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { + // FIXME: refactor this + // If the first time is the unionType type, after nullableFromUnion conversion, + // the isNullable property will become false, which is obviously wrong, + // so add isNullable property + // eslint-disable-next-line @typescript-eslint/default-param-last + protected fromDynamicExpression( + isNullable = false, + t: Type, + ...dynamic: Sourcelike[] + ): Sourcelike { return matchType( t, - _anyType => dynamic, - _nullType => dynamic, // FIXME: check null - _boolType => dynamic, - _integerType => dynamic, - _doubleType => [dynamic, this._options.nullSafety ? "?.toDouble()" : ".toDouble()"], - _stringType => dynamic, - arrayType => + (_anyType) => dynamic, + (_nullType) => dynamic, // FIXME: check null + (_boolType) => dynamic, + (_integerType) => dynamic, + (_doubleType) => [ + dynamic, + this._options.nullSafety ? "?.toDouble()" : ".toDouble()", + ], + (_stringType) => dynamic, + (arrayType) => this.mapList( isNullable || arrayType.isNullable, this.dartType(arrayType.items), dynamic, - this.fromDynamicExpression(arrayType.items.isNullable, arrayType.items, "x") + this.fromDynamicExpression( + arrayType.items.isNullable, + arrayType.items, + "x", + ), + ), + (classType) => + this.mapClass( + isNullable || classType.isNullable, + classType, + dynamic, ), - classType => this.mapClass(isNullable || classType.isNullable, classType, dynamic), - mapType => + (mapType) => this.mapMap( mapType.isNullable || isNullable, this.dartType(mapType.values), dynamic, - this.fromDynamicExpression(mapType.values.isNullable, mapType.values, "v") + this.fromDynamicExpression( + mapType.values.isNullable, + mapType.values, + "v", + ), ), - enumType => { + (enumType) => { return [ defined(this._enumValues.get(enumType)), ".map[", dynamic, - this._options.nullSafety ? "]!" : "]" + this._options.nullSafety ? "]!" : "]", ]; }, - unionType => { + (unionType) => { const maybeNullable = nullableFromUnion(unionType); if (maybeNullable === null) { return dynamic; } - return this.fromDynamicExpression(unionType.isNullable, maybeNullable, dynamic); + + return this.fromDynamicExpression( + unionType.isNullable, + maybeNullable, + dynamic, + ); }, - transformedStringType => { + (transformedStringType) => { switch (transformedStringType.kind) { case "date-time": case "date": @@ -500,36 +493,53 @@ export class DartRenderer extends ConvenienceRenderer { !this._options.requiredProperties && this._options.nullSafety ) { - return [dynamic, " == null ? null : ", "DateTime.parse(", dynamic, ")"]; + return [ + dynamic, + " == null ? null : ", + "DateTime.parse(", + dynamic, + ")", + ]; } + return ["DateTime.parse(", dynamic, ")"]; default: return dynamic; } - } + }, ); } - //If the first time is the unionType type, after nullableFromUnion conversion, - //the isNullable property will become false, which is obviously wrong, - //so add isNullable property - protected toDynamicExpression(isNullable: boolean = false, t: Type, ...dynamic: Sourcelike[]): Sourcelike { + // FIXME: refactor this + // If the first time is the unionType type, after nullableFromUnion conversion, + // the isNullable property will become false, which is obviously wrong, + // so add isNullable property + // eslint-disable-next-line @typescript-eslint/default-param-last + protected toDynamicExpression( + isNullable = false, + t: Type, + ...dynamic: Sourcelike[] + ): Sourcelike { return matchType( t, - _anyType => dynamic, - _nullType => dynamic, - _boolType => dynamic, - _integerType => dynamic, - _doubleType => dynamic, - _stringType => dynamic, - arrayType => + (_anyType) => dynamic, + (_nullType) => dynamic, + (_boolType) => dynamic, + (_integerType) => dynamic, + (_doubleType) => dynamic, + (_stringType) => dynamic, + (arrayType) => this.mapList( arrayType.isNullable || isNullable, "dynamic", dynamic, - this.toDynamicExpression(arrayType.items.isNullable, arrayType.items, "x") + this.toDynamicExpression( + arrayType.items.isNullable, + arrayType.items, + "x", + ), ), - _classType => { + (_classType) => { if ( this._options.nullSafety && (_classType.isNullable || isNullable) && @@ -537,26 +547,41 @@ export class DartRenderer extends ConvenienceRenderer { ) { return [dynamic, "?.", this.toJson, "()"]; } + return [dynamic, ".", this.toJson, "()"]; }, - mapType => + (mapType) => this.mapMap( mapType.isNullable || isNullable, "dynamic", dynamic, - this.toDynamicExpression(mapType.values.isNullable, mapType.values, "v") + this.toDynamicExpression( + mapType.values.isNullable, + mapType.values, + "v", + ), ), - enumType => { - return [defined(this._enumValues.get(enumType)), ".reverse[", dynamic, "]"]; + (enumType) => { + return [ + defined(this._enumValues.get(enumType)), + ".reverse[", + dynamic, + "]", + ]; }, - unionType => { + (unionType) => { const maybeNullable = nullableFromUnion(unionType); if (maybeNullable === null) { return dynamic; } - return this.toDynamicExpression(unionType.isNullable, maybeNullable, dynamic); + + return this.toDynamicExpression( + unionType.isNullable, + maybeNullable, + dynamic, + ); }, - transformedStringType => { + (transformedStringType) => { switch (transformedStringType.kind) { case "date-time": if ( @@ -566,6 +591,7 @@ export class DartRenderer extends ConvenienceRenderer { ) { return [dynamic, "?.toIso8601String()"]; } + return [dynamic, ".toIso8601String()"]; case "date": if ( @@ -581,9 +607,10 @@ export class DartRenderer extends ConvenienceRenderer { dynamic, "!.month.toString().padLeft(2, '0')}-${", dynamic, - "!.day.toString().padLeft(2, '0')}\"" + "!.day.toString().padLeft(2, '0')}\"", ]; } + return [ '"${', dynamic, @@ -592,12 +619,12 @@ export class DartRenderer extends ConvenienceRenderer { dynamic, ".month.toString().padLeft(2, '0')}-${", dynamic, - ".day.toString().padLeft(2, '0')}\"" + ".day.toString().padLeft(2, '0')}\"", ]; default: return dynamic; } - } + }, ); } @@ -611,7 +638,8 @@ export class DartRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, _, prop) => { const required = this._options.requiredProperties || - (this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional)); + (this._options.nullSafety && + (!prop.type.isNullable || !prop.isOptional)); this.emitLine(required ? "required " : "", "this.", name, ","); }); }); @@ -636,7 +664,13 @@ export class DartRenderer extends ConvenienceRenderer { this.emitLine(`@JsonKey(name: "${jsonName}")`); } - this.emitLine(this._options.finalProperties ? "final " : "", this.dartType(p.type, true), " ", name, ";"); + this.emitLine( + this._options.finalProperties ? "final " : "", + this.dartType(p.type, true), + " ", + name, + ";", + ); }); } @@ -645,7 +679,12 @@ export class DartRenderer extends ConvenienceRenderer { this.emitLine(className, " copyWith({"); this.indent(() => { this.forEachClassProperty(c, "none", (name, _, _p) => { - this.emitLine(this.dartType(_p.type, true, true), " ", name, ","); + this.emitLine( + this.dartType(_p.type, true, true), + " ", + name, + ",", + ); }); }); this.emitLine("}) => "); @@ -671,22 +710,32 @@ export class DartRenderer extends ConvenienceRenderer { className, ".", this.fromJson, - "(json.decode(str));" + "(json.decode(str));", ); this.ensureBlankLine(); this.emitLine( "String ", - this._options.methodNamesWithMap ? "toJson() => " : "toRawJson() => ", + this._options.methodNamesWithMap + ? "toJson() => " + : "toRawJson() => ", "json.encode(", this.toJson, - "());" + "());", ); } private _emitMapEncoderDecoder(c: ClassType, className: Name): void { this.ensureBlankLine(); - this.emitLine("factory ", className, ".", this.fromJson, "(Map json) => ", className, "("); + this.emitLine( + "factory ", + className, + ".", + this.fromJson, + "(Map json) => ", + className, + "(", + ); this.indent(() => { this.forEachClassProperty(c, "none", (name, jsonName, property) => { this.emitLine( @@ -697,9 +746,9 @@ export class DartRenderer extends ConvenienceRenderer { property.type, 'json["', stringEscape(jsonName), - '"]' + '"]', ), - "," + ",", ); }); }); @@ -714,8 +763,12 @@ export class DartRenderer extends ConvenienceRenderer { '"', stringEscape(jsonName), '": ', - this.toDynamicExpression(property.type.isNullable, property.type, name), - "," + this.toDynamicExpression( + property.type.isNullable, + property.type, + name, + ), + ",", ); }); }); @@ -729,9 +782,11 @@ export class DartRenderer extends ConvenienceRenderer { this.emitLine(`@HiveType(typeId: ${this.classCounter})`); this.classPropertyCounter = 0; } + if (this._options.useJsonAnnotation) { - this.emitLine(`@JsonSerializable()`); + this.emitLine("@JsonSerializable()"); } + this.emitBlock(["class ", className], () => { if (c.getProperties().size === 0) { this._emitEmptyConstructor(className); @@ -754,7 +809,7 @@ export class DartRenderer extends ConvenienceRenderer { ".fromJson(Map json) => ", "_$", className, - "FromJson(json);" + "FromJson(json);", ); this.ensureBlankLine(); @@ -763,7 +818,7 @@ export class DartRenderer extends ConvenienceRenderer { "Map toJson() => ", "_$", className, - "ToJson(this);" + "ToJson(this);", ); } else { if (this._options.justTypes) return; @@ -783,20 +838,45 @@ export class DartRenderer extends ConvenienceRenderer { this.emitLine("@freezed"); this.emitBlock(["class ", className, " with _$", className], () => { if (c.getProperties().size === 0) { - this.emitLine("const factory ", className, "() = _", className, ";"); + this.emitLine( + "const factory ", + className, + "() = _", + className, + ";", + ); } else { this.emitLine("const factory ", className, "({"); this.indent(() => { - this.forEachClassProperty(c, "none", (name, jsonName, prop) => { - const required = - this._options.requiredProperties || - (this._options.nullSafety && (!prop.type.isNullable || !prop.isOptional)); - if (this._options.useJsonAnnotation) { - this.classPropertyCounter++; - this.emitLine(`@JsonKey(name: "${jsonName}")`); - } - this.emitLine(required ? "required " : "", this.dartType(prop.type, true), " ", name, ","); - }); + this.forEachClassProperty( + c, + "none", + (name, jsonName, prop) => { + const description = + this.descriptionForClassProperty(c, jsonName); + if (description !== undefined) { + this.emitDescription(description); + } + + const required = + this._options.requiredProperties || + (this._options.nullSafety && + (!prop.type.isNullable || + !prop.isOptional)); + if (this._options.useJsonAnnotation) { + this.classPropertyCounter++; + this.emitLine(`@JsonKey(name: "${jsonName}")`); + } + + this.emitLine( + required ? "required " : "", + this.dartType(prop.type, true), + " ", + name, + ",", + ); + }, + ); }); this.emitLine("}) = _", className, ";"); } @@ -811,7 +891,7 @@ export class DartRenderer extends ConvenienceRenderer { ".fromJson(Map json) => ", "_$", className, - "FromJson(json);" + "FromJson(json);", ); }); } @@ -825,6 +905,7 @@ export class DartRenderer extends ConvenienceRenderer { if (this._options.useJsonAnnotation) { this.emitLine('@JsonValue("', stringEscape(jsonName), '")'); } + this.emitLine(name, comma); }); }); @@ -833,11 +914,23 @@ export class DartRenderer extends ConvenienceRenderer { if (this._options.justTypes) return; this.ensureBlankLine(); - this.emitLine("final ", defined(this._enumValues.get(e)), " = EnumValues({"); + this.emitLine( + "final ", + defined(this._enumValues.get(e)), + " = EnumValues({", + ); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName, pos) => { const comma = pos === "first" || pos === "middle" ? "," : []; - this.emitLine('"', stringEscape(jsonName), '": ', enumName, ".", name, comma); + this.emitLine( + '"', + stringEscape(jsonName), + '": ', + enumName, + ".", + name, + comma, + ); }); }); this.emitLine("});"); @@ -848,21 +941,23 @@ export class DartRenderer extends ConvenienceRenderer { protected emitEnumValues(): void { this.ensureBlankLine(); this.emitMultiline(`class EnumValues { - Map map; - late Map reverseMap; + Map map; + late Map reverseMap; - EnumValues(this.map); + EnumValues(this.map); - Map get reverse { - reverseMap = map.map((k, v) => MapEntry(v, k)); - return reverseMap; - } + Map get reverse { + reverseMap = map.map((k, v) => MapEntry(v, k)); + return reverseMap; + } }`); } private _emitTopLvlEncoderDecoder(): void { this.forEachTopLevel("leading-and-interposing", (t, name) => { - const { encoder, decoder } = defined(this._topLevelDependents.get(name)); + const { encoder, decoder } = defined( + this._topLevelDependents.get(name), + ); this.emitLine( this.dartType(t), @@ -870,7 +965,7 @@ export class DartRenderer extends ConvenienceRenderer { decoder, "(String str) => ", this.fromDynamicExpression(t.isNullable, t, "json.decode(str)"), - ";" + ";", ); this.ensureBlankLine(); @@ -882,7 +977,7 @@ export class DartRenderer extends ConvenienceRenderer { this.dartType(t), " data) => json.encode(", this.toDynamicExpression(t.isNullable, t, "data"), - ");" + ");", ); // this.emitBlock(["String ", encoder, "(", this.dartType(t), " data)"], () => { @@ -901,11 +996,13 @@ export class DartRenderer extends ConvenienceRenderer { this.forEachNamedType( "leading-and-interposing", (c: ClassType, n: Name) => - this._options.useFreezed ? this.emitFreezedClassDefinition(c, n) : this.emitClassDefinition(c, n), + this._options.useFreezed + ? this.emitFreezedClassDefinition(c, n) + : this.emitClassDefinition(c, n), (e, n) => this.emitEnumDefinition(e, n), (_e, _n) => { // We don't support this yet. - } + }, ); if (this._needEnumValues) { diff --git a/packages/quicktype-core/src/language/Dart/constants.ts b/packages/quicktype-core/src/language/Dart/constants.ts new file mode 100644 index 000000000..6aef1d3cb --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/constants.ts @@ -0,0 +1,71 @@ +export const keywords = [ + "abstract", + "do", + "import", + "super", + "as", + "dynamic", + "in", + "switch", + "assert", + "else", + "interface", + "sync*", + "async", + "enum", + "is", + "this", + "async*", + "export", + "library", + "throw", + "await", + "external", + "mixin", + "true", + "break", + "extends", + "new", + "try", + "case", + "factory", + "null", + "typedef", + "catch", + "false", + "operator", + "var", + "class", + "final", + "part", + "void", + "const", + "finally", + "rethrow", + "while", + "continue", + "for", + "return", + "with", + "covariant", + "get", + "set", + "yield", + "default", + "if", + "static", + "yield*", + "deferred", + "implements", + "int", + "double", + "bool", + "Map", + "List", + "String", + "File", + "fromJson", + "toJson", + "fromMap", + "toMap", +] as const; diff --git a/packages/quicktype-core/src/language/Dart/index.ts b/packages/quicktype-core/src/language/Dart/index.ts new file mode 100644 index 000000000..3820d5ad9 --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/index.ts @@ -0,0 +1,2 @@ +export { DartTargetLanguage, dartOptions } from "./language"; +export { DartRenderer } from "./DartRenderer"; diff --git a/packages/quicktype-core/src/language/Dart/language.ts b/packages/quicktype-core/src/language/Dart/language.ts new file mode 100644 index 000000000..cc80a8b6d --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/language.ts @@ -0,0 +1,109 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { DartRenderer } from "./DartRenderer"; + +export const dartOptions = { + nullSafety: new BooleanOption("null-safety", "Null Safety", true), + justTypes: new BooleanOption("just-types", "Types only", false), + codersInClass: new BooleanOption( + "coders-in-class", + "Put encoder & decoder in Class", + false, + ), + methodNamesWithMap: new BooleanOption( + "from-map", + "Use method names fromMap() & toMap()", + false, + "secondary", + ), + requiredProperties: new BooleanOption( + "required-props", + "Make all properties required", + false, + ), + finalProperties: new BooleanOption( + "final-props", + "Make all properties final", + false, + ), + generateCopyWith: new BooleanOption( + "copy-with", + "Generate CopyWith method", + false, + ), + useFreezed: new BooleanOption( + "use-freezed", + "Generate class definitions with @freezed compatibility", + false, + "secondary", + ), + useHive: new BooleanOption( + "use-hive", + "Generate annotations for Hive type adapters", + false, + "secondary", + ), + useJsonAnnotation: new BooleanOption( + "use-json-annotation", + "Generate annotations for json_serializable", + false, + "secondary", + ), + partName: new StringOption( + "part-name", + "Use this name in `part` directive", + "NAME", + "", + "secondary", + ), +}; + +export const dartLanguageConfig = { + displayName: "Dart", + names: ["dart"], + extension: "dart", +} as const; + +export class DartTargetLanguage extends TargetLanguage< + typeof dartLanguageConfig +> { + public constructor() { + super(dartLanguageConfig); + } + + public getOptions(): typeof dartOptions { + return dartOptions; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + mapping.set("date", "date"); + mapping.set("date-time", "date-time"); + return mapping; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): DartRenderer { + const options = getOptionValues(dartOptions, untypedOptionValues); + return new DartRenderer(this, renderContext, options); + } +} diff --git a/packages/quicktype-core/src/language/Dart/utils.ts b/packages/quicktype-core/src/language/Dart/utils.ts new file mode 100644 index 000000000..0a2825b4a --- /dev/null +++ b/packages/quicktype-core/src/language/Dart/utils.ts @@ -0,0 +1,78 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + isAscii, + isDigit, + isLetter, + isPrintable, + splitIntoWords, + standardUnicodeHexEscape, + utf16ConcatMap, + utf16LegalizeCharacters, +} from "../../support/Strings"; + +export const typeNamingFunction = funPrefixNamer("types", (n) => + dartNameStyle(true, false, n), +); +export const propertyNamingFunction = funPrefixNamer("properties", (n) => + dartNameStyle(false, false, n), +); +export const enumCaseNamingFunction = funPrefixNamer("enum-cases", (n) => + dartNameStyle(true, true, n), +); + +// Escape the dollar sign, which is used in string interpolation +export const stringEscape = utf16ConcatMap( + escapeNonPrintableMapper( + (cp) => isPrintable(cp) && cp !== 0x24, + standardUnicodeHexEscape, + ), +); + +function isStartCharacter(codePoint: number): boolean { + if (codePoint === 0x5f) return false; // underscore + return isAscii(codePoint) && isLetter(codePoint); +} + +function isPartCharacter(codePoint: number): boolean { + return ( + isStartCharacter(codePoint) || + (isAscii(codePoint) && isDigit(codePoint)) + ); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +// FIXME: Handle acronyms consistently. In particular, that means that +// we have to use namers to produce the getter and setter names - we can't +// just capitalize and concatenate. +// https://stackoverflow.com/questions/8277355/naming-convention-for-upper-case-abbreviations +export function dartNameStyle( + startWithUpper: boolean, + upperUnderscore: boolean, + original: string, +): string { + const words = splitIntoWords(original); + const firstWordStyle = upperUnderscore + ? allUpperWordStyle + : startWithUpper + ? firstUpperWordStyle + : allLowerWordStyle; + const restWordStyle = upperUnderscore + ? allUpperWordStyle + : firstUpperWordStyle; + return combineWords( + words, + legalizeName, + firstWordStyle, + restWordStyle, + firstWordStyle, + restWordStyle, + upperUnderscore ? "_" : "", + isStartCharacter, + ); +} diff --git a/packages/quicktype-core/src/language/Elixir/ElixirRenderer.ts b/packages/quicktype-core/src/language/Elixir/ElixirRenderer.ts new file mode 100644 index 000000000..c35ea00b3 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/ElixirRenderer.ts @@ -0,0 +1,1223 @@ +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import type { Sourcelike } from "../../Source"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + ClassType, + EnumType, + MapType, + PrimitiveType, + type Type, + UnionType, +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../Type/TypeUtils"; + +import { forbiddenModuleNames, reservedWords } from "./constants"; +import type { elixirOptions } from "./language"; +import { + capitalizeFirstLetter, + escapeDoubleQuotes, + escapeNewLines, + memberNameStyle, + simpleNameStyle, + stringEscape, +} from "./utils"; + +export class ElixirRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected get commentLineStart(): string { + return "# "; + } + + protected get needsTypeDeclarationBeforeUse(): boolean { + return true; + } + + protected canBeForwardDeclared(t: Type): boolean { + return "class" === t.kind; + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + return [ + ...forbiddenModuleNames, + ...reservedWords.map((word) => capitalizeFirstLetter(word)), + ]; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { + names: reservedWords as unknown as string[], + includeGlobalForbidden: true, + }; + } + + protected makeNamedTypeNamer(): Namer { + return new Namer("types", (n) => simpleNameStyle(n, true), []); + } + + protected namerForObjectProperty(): Namer { + return new Namer("properties", memberNameStyle, []); + } + + protected makeUnionMemberNamer(): Namer { + return new Namer("properties", memberNameStyle, []); + } + + protected makeEnumCaseNamer(): Namer { + return new Namer("enum-cases", (n) => simpleNameStyle(n, true), []); + } + + private nameForNamedTypeWithNamespace(t: Type): Sourcelike { + if (this._options.namespace) { + return [this._options.namespace, ".", this.nameForNamedType(t)]; + } + + return [this.nameForNamedType(t)]; + } + + private nameWithNamespace(n: Name): Sourcelike { + if (this._options.namespace) { + return [this._options.namespace, ".", n]; + } + + return [n]; + } + + private elixirType(t: Type, isOptional = false): Sourcelike { + const optional = isOptional ? " | nil" : ""; + return matchType( + t, + (_anyType) => ["any()", optional], + (_nullType) => ["nil"], + (_boolType) => ["boolean()", optional], + (_integerType) => ["integer()", optional], + (_doubleType) => ["float()", optional], + (_stringType) => ["String.t()", optional], + (arrayType) => [ + "[", + this.elixirType(arrayType.items), + "]", + optional, + ], + (classType) => [ + this.nameForNamedTypeWithNamespace(classType), + ".t()", + optional, + ], + (mapType) => [ + "%{String.t() => ", + this.elixirType(mapType.values), + "}", + optional, + ], + (enumType) => [ + this.nameForNamedTypeWithNamespace(enumType), + ".t()", + optional, + ], + (unionType) => { + const children = [...unionType.getChildren()].map((ut) => + this.elixirType(ut), + ); + return [ + children.flatMap((element, index) => + index === children.length - 1 + ? element + : [element, " | "], + ), + optional, + ]; + }, + ); + } + + private patternMatchClauseDecode( + t: Type, + attributeName: Sourcelike, + suffix = "", + ): Sourcelike { + return matchType( + t, + (_anyType) => [], + (_nullType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_nil(value), do: value", + ], + (_boolType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_boolean(value), do: value", + ], + (_integerType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_integer(value), do: value", + ], + (_doubleType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_float(value), do: value\n", + "def decode_", + attributeName, + suffix, + "(value) when is_integer(value), do: value", + ], + (_stringType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_binary(value), do: value", + ], + (_arrayType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_list(value), do: value", + ], + (classType) => { + const requiredAttributeArgs: Sourcelike[] = []; + this.forEachClassProperty( + classType, + "none", + (_name, jsonName, p) => { + if (!p.isOptional) { + requiredAttributeArgs.push([ + '"', + jsonName, + '" => _,', + ]); + } + }, + ); + return [ + "def decode_", + attributeName, + suffix, + "(%{", + requiredAttributeArgs, + "} = value), do: ", + this.nameForNamedTypeWithNamespace(classType), + ".from_map(value)", + ]; + }, + (_mapType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_map(value), do: value", + ], + (enumType) => [ + "def decode_", + attributeName, + suffix, + "(value) when is_binary(value)", + ", do: ", + this.nameForNamedTypeWithNamespace(enumType), + ".decode(value)", + ], + (_unionType) => [], + ); + } + + private patternMatchClauseEncode( + t: Type, + attributeName: Sourcelike, + suffix = "", + ): Sourcelike { + return matchType( + t, + (_anyType) => [], + (_nullType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_nil(value), do: value", + ], + (_boolType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_boolean(value), do: value", + ], + (_integerType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_integer(value), do: value", + ], + (_doubleType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_float(value), do: value\n", + "def encode_", + attributeName, + suffix, + "(value) when is_integer(value), do: value", + ], + (_stringType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_binary(value), do: value", + ], + (_arrayType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_list(value), do: value", + ], + (classType) => { + const requiredAttributeArgs: Sourcelike[] = []; + this.forEachClassProperty( + classType, + "none", + (_name, jsonName, p) => { + if (!p.isOptional) { + requiredAttributeArgs.push([ + '"', + jsonName, + '" => _,', + ]); + } + }, + ); + return [ + "def encode_", + attributeName, + suffix, + "(%", + this.nameForNamedTypeWithNamespace(classType), + "{} = value), do: ", + this.nameForNamedTypeWithNamespace(classType), + ".to_map(value)", + ]; + }, + (_mapType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_map(value), do: value", + ], + (enumType) => [ + "def encode_", + attributeName, + suffix, + "(value) when is_atom(value)", + ", do: ", + this.nameForNamedTypeWithNamespace(enumType), + ".encode(value)", + ], + (_unionType) => [], + ); + } + + private sortAndFilterPatternMatchTypes(types: Type[]): Type[] { + return types + .filter((type) => !(type instanceof UnionType)) + .sort((a, b) => { + if (a instanceof ClassType && !(b instanceof ClassType)) { + return -1; + } + if (b instanceof ClassType && !(a instanceof ClassType)) { + return 1; + } + if (a.kind === "bool" && b.kind !== "bool") { + return -1; + } + if (b.kind === "bool" && a.kind !== "bool") { + return 1; + } + if (a instanceof EnumType && !(b instanceof EnumType)) { + return -1; + } + if (b instanceof EnumType && !(a instanceof EnumType)) { + return 1; + } + if (a.isPrimitive() && !b.isPrimitive()) { + return -1; + } + if (b.isPrimitive() && !a.isPrimitive()) { + return 1; + } + + return 0; + }); + } + + protected emitPatternMatches( + types: Type[], + name: Sourcelike, + parentName: Sourcelike, + suffix = "", + optional = false, + ): void { + this.ensureBlankLine(); + + let typesToMatch = this.sortAndFilterPatternMatchTypes(types); + if (typesToMatch.length < 2) { + return; + } + + if (typesToMatch.find((type) => type.kind === "double")) { + typesToMatch = typesToMatch.filter( + (type) => type.kind !== "integer", + ); + } + + typesToMatch.forEach((type) => { + this.emitLine(this.patternMatchClauseDecode(type, name, suffix)); + }); + + if (optional && !typesToMatch.find((type) => type.kind === "null")) { + this.emitLine( + "def decode_", + name, + suffix, + "(value) when is_nil(value), do: value", + ); + } + + this.emitLine( + "def decode_", + name, + suffix, + '(_), do: {:error, "Unexpected type when decoding ', + parentName, + ".", + name, + '"}', + ); + + this.ensureBlankLine(); + + typesToMatch.forEach((type) => { + this.emitLine(this.patternMatchClauseEncode(type, name, suffix)); + }); + + if (optional && !typesToMatch.find((type) => type.kind === "null")) { + this.emitLine( + "def encode_", + name, + suffix, + "(value) when is_nil(value), do: value", + ); + } + + this.emitLine( + "def encode_", + name, + suffix, + '(_), do: {:error, "Unexpected type when encoding ', + parentName, + ".", + name, + '"}', + ); + + this.ensureBlankLine(); + } + + private nameOfTransformFunction( + t: Type, + name: Name | Sourcelike, + encode = false, + prefix = "", + ): Sourcelike { + let mode = "decode"; + if (encode) { + mode = "encode"; + } + + return matchType( + t, + (_anyType) => [], + (_nullType) => [], + (_boolType) => [], + (_integerType) => [], + (_doubleType) => [], + (_stringType) => [], + (_arrayType) => [], + (classType) => [ + this.nameForNamedTypeWithNamespace(classType), + `.${encode ? "to" : "from"}_map`, + ], + (_mapType) => [], + (enumType) => { + return [ + this.nameForNamedTypeWithNamespace(enumType), + `.${mode}`, + ]; + }, + (_unionType) => { + return [`${mode}_`, name, prefix]; + }, + ); + } + + private fromDynamic( + t: Type, + jsonName: string, + name: Name, + optional = false, + ): Sourcelike { + const primitive = ['m["', jsonName, '"]']; + + return matchType( + t, + (_anyType) => primitive, + (_nullType) => primitive, + (_boolType) => primitive, + (_integerType) => primitive, + (_doubleType) => primitive, + (_stringType) => primitive, + (arrayType) => { + const arrayElement = arrayType.items; + if (arrayElement instanceof ArrayType) { + return primitive; + } + if (arrayElement.isPrimitive()) { + return primitive; + } + if (arrayElement instanceof MapType) { + return primitive; + } + + if (optional) { + return [ + "m", + '["', + jsonName, + '"] && Enum.map(m["', + jsonName, + '"], &', + this.nameOfTransformFunction( + arrayElement, + name, + false, + "_element", + ), + "/1)", + ]; + } + + return [ + 'Enum.map(m["', + jsonName, + '"], &', + this.nameOfTransformFunction( + arrayElement, + name, + false, + "_element", + ), + "/1)", + ]; + }, + (classType) => [ + optional ? [primitive, " && "] : "", + this.nameForNamedTypeWithNamespace(classType), + ".from_map(", + primitive, + ")", + ], + (mapType) => { + const mapValueTypes = [...mapType.values.getChildren()]; + const mapValueTypesNotPrimitive = mapValueTypes.filter( + (type) => !(type instanceof PrimitiveType), + ); + if (mapValueTypesNotPrimitive.length === 0) { + return [primitive]; + } + + if (mapType.values.kind === "union") { + return [ + 'm["', + jsonName, + '"]\n|> Map.new(fn {key, value} -> {key, ', + this.nameOfTransformFunction( + mapType.values, + jsonName, + false, + ), + "_value(value)} end)", + ]; + } + if ( + mapType.values instanceof EnumType || + mapType.values instanceof ClassType + ) { + return [ + 'm["', + jsonName, + '"]\n|> Map.new(fn {key, value} -> {key, ', + this.nameOfTransformFunction( + mapType.values, + jsonName, + false, + ), + "(value)} end)", + ]; + } + + return [primitive]; + }, + (enumType) => { + return [ + optional ? [primitive, " && "] : "", + this.nameOfTransformFunction(enumType, name), + "(", + primitive, + ")", + ]; + }, + (unionType) => { + const unionTypes = [...unionType.getChildren()]; + const unionPrimitiveTypes = unionTypes.filter((type) => + type.isPrimitive(), + ); + if (unionTypes.length === unionPrimitiveTypes.length) { + return ['m["', jsonName, '"]']; + } + + const nullable = nullableFromUnion(unionType); + + if (nullable !== null) { + if (nullable instanceof ClassType) { + return this.fromDynamic(nullable, jsonName, name, true); + } + + const nullableTypes = [...nullable.getChildren()]; + if (nullableTypes.length < 2) { + return this.fromDynamic(nullable, jsonName, name, true); + } + + return [ + 'm["', + jsonName, + '"] && decode_', + name, + '(m["', + jsonName, + '"])', + ]; + } + + return ["decode_", name, '(m["', jsonName, '"])']; + }, + ); + } + + private toDynamic(t: Type, e: Sourcelike, optional = false): Sourcelike { + const expression = ["struct.", e]; + return matchType( + t, + (_anyType) => expression, + (_nullType) => expression, + (_boolType) => expression, + (_integerType) => expression, + (_doubleType) => expression, + (_stringType) => expression, + (arrayType) => { + const arrayElement = arrayType.items; + if (arrayElement instanceof ArrayType) { + return expression; + } + + if (arrayElement.isPrimitive()) { + return expression; + } + if (arrayElement instanceof MapType) { + return expression; + } + + if (arrayElement.kind === "array") { + return expression; + } + + if (optional) { + return [ + "struct.", + e, + " && Enum.map(struct.", + e, + ", &", + this.nameOfTransformFunction( + arrayElement, + e, + true, + "_element", + ), + "/1)", + ]; + } + + return [ + "struct.", + e, + " && Enum.map(struct.", + e, + ", &", + this.nameOfTransformFunction( + arrayElement, + e, + true, + "_element", + ), + "/1)", + ]; + }, + (classType) => [ + optional ? ["struct.", e, " && "] : "", + this.nameForNamedTypeWithNamespace(classType), + ".to_map(", + "struct.", + e, + ")", + ], + (mapType) => { + const mapValueTypes = [...mapType.values.getChildren()]; + const mapValueTypesNotPrimitive = mapValueTypes.filter( + (type) => !(type instanceof PrimitiveType), + ); + if (mapValueTypesNotPrimitive.length === 0) { + return [expression]; + } + + if (mapType.values.kind === "union") { + return [ + "struct.", + e, + "\n|> Map.new(fn {key, value} -> {key, ", + this.nameOfTransformFunction(mapType.values, e, true), + "_value(value)} end)", + ]; + } + if ( + mapType.values instanceof EnumType || + mapType.values instanceof ClassType + ) { + return [ + "struct.", + e, + "\n|> Map.new(fn {key, value} -> {key, ", + this.nameOfTransformFunction(mapType.values, e, true), + "(value)} end)", + ]; + } + + return [expression]; + }, + (enumType) => { + return [ + optional ? ["struct.", e, " && "] : "", + this.nameForNamedTypeWithNamespace(enumType), + ".encode(struct.", + e, + ")", + ]; + }, + (unionType) => { + const unionTypes = [...unionType.getChildren()]; + const unionPrimitiveTypes = unionTypes.filter((type) => + type.isPrimitive(), + ); + if (unionTypes.length === unionPrimitiveTypes.length) { + return ["struct.", e]; + } + + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (nullable instanceof ClassType) { + return this.toDynamic(nullable, e, true); + } + + const nullableTypes = [...nullable.getChildren()]; + if (nullableTypes.length < 2) { + return this.toDynamic(nullable, e, true); + } + + return ["struct.", e, " && encode_", e, "(struct.", e, ")"]; + } + + return ["encode_", e, "(struct.", e, ")"]; + }, + ); + } + + protected emitBlock(source: Sourcelike, emit: () => void): void { + this.emitLine(source); + this.indent(emit); + this.emitLine("end"); + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + firstLineStart: '@moduledoc """\n', + lineStart: "", + afterComment: '"""', + }); + } + + protected emitModule(c: ClassType, moduleName: Name): void { + this.emitBlock( + ["defmodule ", this.nameWithNamespace(moduleName), " do"], + () => { + const structDescription = this.descriptionForType(c) ?? []; + const attributeDescriptions: Sourcelike[][] = []; + this.forEachClassProperty(c, "none", (name, jsonName, _p) => { + const attributeDescription = + this.descriptionForClassProperty(c, jsonName); + if (attributeDescription) { + attributeDescriptions.push([ + "- `:", + name, + "` - ", + attributeDescription, + ]); + } + }); + if (structDescription.length || attributeDescriptions.length) { + this.emitDescription([ + ...structDescription, + ...attributeDescriptions, + ]); + this.ensureBlankLine(); + } + + const requiredAttributes: Sourcelike[] = []; + this.forEachClassProperty(c, "none", (name, _jsonName, p) => { + if (!p.isOptional) { + if (requiredAttributes.length === 0) { + requiredAttributes.push([":", name]); + } else { + requiredAttributes.push([", :", name]); + } + } + }); + if (requiredAttributes.length) { + this.emitLine(["@enforce_keys [", requiredAttributes, "]"]); + } + + const attributeNames: Sourcelike[] = []; + this.forEachClassProperty(c, "none", (name, _jsonName, _p) => { + if (attributeNames.length === 0) { + attributeNames.push([":", name]); + } else { + attributeNames.push([", :", name]); + } + }); + + this.emitLine(["defstruct [", attributeNames, "]"]); + this.ensureBlankLine(); + + const typeDefinitionTable: Sourcelike[][] = [ + [["@type "], ["t :: %__MODULE__{"]], + ]; + let count = c.getProperties().size; + this.forEachClassProperty(c, "none", (name, _jsonName, p) => { + const last = --count === 0; + const attributeRow = [ + [], + [ + " ", + name, + ": ", + this.elixirType(p.type), + p.isOptional ? " | nil" : "", + last ? "" : ",", + ], + ]; + typeDefinitionTable.push(attributeRow); + }); + typeDefinitionTable.push([[], ["}"]]); + this.emitTable(typeDefinitionTable); + if (this._options.justTypes) { + return; + } + + this.forEachClassProperty(c, "none", (name, _jsonName, p) => { + if (p.type.kind === "union") { + const unionTypes = [...p.type.getChildren()]; + const unionPrimitiveTypes = unionTypes.filter((type) => + type.isPrimitive(), + ); + if (unionTypes.length === unionPrimitiveTypes.length) { + return; + } + + const unionTypesNonNull = unionTypes.filter( + (type) => type.kind !== "null", + ); + if (unionTypesNonNull.length === 1) { + let suffix = ""; + let itemTypes: Type[] = []; + if (unionTypesNonNull[0] instanceof ArrayType) { + suffix = "_element"; + itemTypes = [ + ...unionTypesNonNull[0].getChildren(), + ]; + } else if ( + unionTypesNonNull[0] instanceof MapType + ) { + suffix = "_value"; + itemTypes = [ + ...unionTypesNonNull[0].getChildren(), + ]; + } + + if ( + itemTypes.length === 1 && + itemTypes[0] instanceof UnionType + ) { + itemTypes = [...itemTypes[0].getChildren()]; + } + + this.emitPatternMatches( + itemTypes, + name, + this.nameForNamedTypeWithNamespace(c), + suffix, + p.isOptional, + ); + } else { + this.emitPatternMatches( + unionTypes, + name, + this.nameForNamedTypeWithNamespace(c), + "", + p.isOptional, + ); + } + } else if (p.type.kind === "array") { + const arrayType = p.type as ArrayType; + if (arrayType.items instanceof UnionType) { + const unionType = arrayType.items; + const typesInUnion = [...unionType.getChildren()]; + + this.emitPatternMatches( + typesInUnion, + name, + this.nameForNamedTypeWithNamespace(c), + "_element", + ); + } + } else if (p.type.kind === "map") { + const mapType = p.type as MapType; + if (mapType.values instanceof UnionType) { + const unionType = mapType.values; + const typesInUnion = [...unionType.getChildren()]; + + this.emitPatternMatches( + typesInUnion, + name, + this.nameForNamedTypeWithNamespace(c), + "_value", + ); + } + } + }); + let propCount = 0; + this.forEachClassProperty(c, "none", (_name, _jsonName, _p) => { + propCount++; + }); + const isEmpty = propCount ? false : true; + this.ensureBlankLine(); + this.emitBlock( + [`def from_map(${isEmpty ? "_" : ""}m) do`], + () => { + this.emitLine( + "%", + this.nameWithNamespace(moduleName), + "{", + ); + this.indent(() => { + this.forEachClassProperty( + c, + "none", + (name, jsonName, p) => { + jsonName = escapeDoubleQuotes(jsonName); + jsonName = escapeNewLines(jsonName); + const expression = this.fromDynamic( + p.type, + jsonName, + name, + p.isOptional, + ); + this.emitLine(name, ": ", expression, ","); + }, + ); + }); + this.emitLine("}"); + }, + ); + this.ensureBlankLine(); + this.emitBlock("def from_json(json) do", () => { + this.emitMultiline(`json + |> Jason.decode!() + |> from_map()`); + }); + this.ensureBlankLine(); + this.emitBlock( + [`def to_map(${isEmpty ? "_" : ""}struct) do`], + () => { + this.emitLine("%{"); + this.indent(() => { + this.forEachClassProperty( + c, + "none", + (name, jsonName, p) => { + const expression = this.toDynamic( + p.type, + name, + p.isOptional, + ); + this.emitLine([ + [`"${stringEscape(jsonName)}"`], + [" => ", expression, ","], + ]); + }, + ); + }); + this.emitLine("}"); + }, + ); + this.ensureBlankLine(); + this.emitBlock("def to_json(struct) do", () => { + this.emitMultiline(`struct + |> to_map() + |> Jason.encode!()`); + }); + }, + ); + } + + private isValidAtom(str: string): boolean { + function isLetter(char: string): boolean { + return /^[A-Za-z_]$/.test(char); + } + + function isLetterOrDigit(char: string): boolean { + return /^[A-Za-z0-9_]$/.test(char); + } + + if (str.length === 0) { + return false; + } + + const firstChar = str[0]; + if (!isLetter(firstChar)) { + return false; + } + + for (let i = 1; i < str.length; i++) { + const char = str[i]; + + if ( + !isLetterOrDigit(char) && + char !== "@" && + !(i === str.length - 1 && (char === "!" || char === "?")) + ) { + return false; + } + } + + return true; + } + + protected emitEnum(e: EnumType, enumName: Name): void { + this.emitBlock( + ["defmodule ", this.nameWithNamespace(enumName), " do"], + () => { + this.emitDescription(this.descriptionForType(e)); + this.emitLine("@valid_enum_members ["); + this.indent(() => { + this.forEachEnumCase(e, "none", (_name, json) => { + if (this.isValidAtom(json)) { + this.emitLine(":", json, ","); + } else { + this.emitLine(":", `"${json}"`, ","); + } + }); + }); + + this.emitLine("]"); + + this.ensureBlankLine(); + + this.emitMultiline(`def valid_atom?(value), do: value in @valid_enum_members + +def valid_atom_string?(value) do + try do + atom = String.to_existing_atom(value) + atom in @valid_enum_members + rescue + ArgumentError -> false + end +end + +def encode(value) do + if valid_atom?(value) do + Atom.to_string(value) + else + {:error, "Unexpected value when encoding atom: #{inspect(value)}"} + end +end + +def decode(value) do + if valid_atom_string?(value) do + String.to_existing_atom(value) + else + {:error, "Unexpected value when decoding atom: #{inspect(value)}"} + end +end + +def from_json(json) do + json + |> Jason.decode!() + |> decode() +end + +def to_json(data) do + data + |> encode() + |> Jason.encode!() +end`); + }, + ); + } + + protected emitUnion(_u: UnionType, _unionName: Name): void { + return; + } + + protected emitSourceStructure(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else if (!this._options.justTypes) { + this.emitMultiline(`# This file was autogenerated using quicktype https://github.com/quicktype/quicktype +# +# Add Jason to your mix.exs`); + this.forEachTopLevel("none", (_topLevel, name) => { + this.emitLine("#"); + this.emitLine( + "# Decode a JSON string: ", + this.nameWithNamespace(name), + ".from_json(data)", + ); + this.emitLine( + "# Encode into a JSON string: ", + this.nameWithNamespace(name), + ".to_json(struct)", + ); + }); + } + + this.ensureBlankLine(); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitModule(c, n), + (e, n) => this.emitEnum(e, n), + (u, n) => this.emitUnion(u, n), + ); + + if (!this._options.justTypes) { + this.forEachTopLevel( + "leading-and-interposing", + (topLevel, name) => { + const isTopLevelArray = "array" === topLevel.kind; + + this.emitBlock( + ["defmodule ", this.nameWithNamespace(name), " do"], + () => { + const description = + this.descriptionForType(topLevel) ?? []; + if (description.length) { + this.emitDescription([...description]); + this.ensureBlankLine(); + } + + if (isTopLevelArray) { + const arrayElement = (topLevel as ArrayType) + .items; + + let isUnion = false; + + if (arrayElement instanceof UnionType) { + this.emitPatternMatches( + [...arrayElement.getChildren()], + "element", + name, + ); + isUnion = true; + } + + this.emitBlock("def from_json(json) do", () => { + this.emitLine("json"); + this.emitLine("|> Jason.decode!()"); + this.emitLine( + "|> Enum.map(&", + isUnion + ? ["decode_element/1)"] + : [ + this.nameWithNamespace(name), + "Element.from_map/1)", + ], + ); + }); + + this.ensureBlankLine(); + + this.emitBlock("def to_json(list) do", () => { + this.emitLine( + "Enum.map(list, &", + isUnion + ? ["encode_element/1)"] + : [ + this.nameWithNamespace(name), + "Element.to_map/1)", + ], + ); + this.emitLine("|> Jason.encode!()"); + }); + } else { + this.emitBlock("def from_json(json) do", () => { + this.emitLine("Jason.decode!(json)"); + }); + + this.ensureBlankLine(); + + this.emitBlock("def to_json(data) do", () => { + this.emitLine("Jason.encode!(data)"); + }); + } + }, + ); + }, + (t) => this.namedTypeToNameForTopLevel(t) === undefined, + ); + } + } +} diff --git a/packages/quicktype-core/src/language/Elixir/constants.ts b/packages/quicktype-core/src/language/Elixir/constants.ts new file mode 100644 index 000000000..6216baa7b --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/constants.ts @@ -0,0 +1,101 @@ +export const forbiddenModuleNames = [ + "Access", + "Agent", + "Any", + "Application", + "ArgumentError", + "ArithmeticError", + "Atom", + "BadArityError", + "BadBooleanError", + "BadFunctionError", + "BadMapError", + "BadStructError", + "Base", + "Behaviour", + "Bitwise", + "Calendar", + "CaseClauseError", + "Code", + "Collectable", + "CondClauseError", + "Config", + "Date", + "DateTime", + "Dict", + "DynamicSupervisor", + "Enum", + "ErlangError", + "Exception", + "File", + "Float", + "Function", + "FunctionClauseError", + "GenEvent", + "GenServer", + "HashDict", + "HashSet", + "IO", + "Inspect", + "Integer", + "Kernel", + "KeyError", + "Keyword", + "List", + "Macro", + "Map", + "MapSet", + "MatchError", + "Module", + "Node", + "OptionParser", + "Path", + "Port", + "Process", + "Protocol", + "Range", + "Record", + "Regex", + "Registry", + "RuntimeError", + "Set", + "Stream", + "String", + "StringIO", + "Supervisor", + "SyntaxError", + "System", + "SystemLimitError", + "Task", + "Time", + "TokenMissingError", + "Tuple", + "URI", + "UndefinedFunctionError", + "UnicodeConversionError", + "Version", + "WithClauseError", +] as const; + +export const reservedWords = [ + "def", + "defmodule", + "use", + "import", + "alias", + "true", + "false", + "nil", + "when", + "and", + "or", + "not", + "in", + "fn", + "do", + "end", + "catch", + "rescue", + "after", + "else", +] as const; diff --git a/packages/quicktype-core/src/language/Elixir/index.ts b/packages/quicktype-core/src/language/Elixir/index.ts new file mode 100644 index 000000000..59a6f6eb3 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/index.ts @@ -0,0 +1,2 @@ +export { ElixirTargetLanguage, elixirOptions } from "./language"; +export { ElixirRenderer } from "./ElixirRenderer"; diff --git a/packages/quicktype-core/src/language/Elixir/language.ts b/packages/quicktype-core/src/language/Elixir/language.ts new file mode 100644 index 000000000..01783d1c2 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/language.ts @@ -0,0 +1,57 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { ElixirRenderer } from "./ElixirRenderer"; + +export const elixirOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + namespace: new StringOption( + "namespace", + "Specify a module namespace", + "NAME", + "", + ), +}; + +export const elixirLanguageConfig = { + displayName: "Elixir", + names: ["elixir"], + extension: "ex", +} as const; + +export class ElixirTargetLanguage extends TargetLanguage< + typeof elixirLanguageConfig +> { + public constructor() { + super(elixirLanguageConfig); + } + + public getOptions(): typeof elixirOptions { + return elixirOptions; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected get defaultIndentation(): string { + return " "; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ElixirRenderer { + return new ElixirRenderer( + this, + renderContext, + getOptionValues(elixirOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/Elixir/utils.ts b/packages/quicktype-core/src/language/Elixir/utils.ts new file mode 100644 index 000000000..2e2439e33 --- /dev/null +++ b/packages/quicktype-core/src/language/Elixir/utils.ts @@ -0,0 +1,79 @@ +import unicode from "unicode-properties"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isLetterOrUnderscore, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap, +} from "../../support/Strings"; + +function unicodeEscape(codePoint: number): string { + return `\\u{${intToHex(codePoint, 0)}}`; +} + +export function capitalizeFirstLetter(str: string): string { + return str.charAt(0).toUpperCase() + str.slice(1); +} + +export const stringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, unicodeEscape), +); + +export function escapeDoubleQuotes(str: string): string { + return str.replace(/"/g, '\\"'); +} + +export function escapeNewLines(str: string): string { + return str.replace(/\n/g, "\\n"); +} + +const isStartCharacter = isLetterOrUnderscore; + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + return ( + ["Nd", "Pc", "Mn", "Mc"].includes(category) || + isStartCharacter(utf16Unit) + ); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function simpleNameStyle(original: string, uppercase: boolean): string { + if (/^[0-9]+$/.test(original)) { + original = `${original}N`; + } + + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter, + ); +} + +export function memberNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + "_", + isStartCharacter, + ); +} diff --git a/packages/quicktype-core/src/language/Elm.ts b/packages/quicktype-core/src/language/Elm/ElmRenderer.ts similarity index 54% rename from packages/quicktype-core/src/language/Elm.ts rename to packages/quicktype-core/src/language/Elm/ElmRenderer.ts index 2c7fd49ae..b11daadfb 100644 --- a/packages/quicktype-core/src/language/Elm.ts +++ b/packages/quicktype-core/src/language/Elm/ElmRenderer.ts @@ -1,180 +1,94 @@ -import { mapContains, arrayIntercalate } from "collection-utils"; - -import { TargetLanguage } from "../TargetLanguage"; -import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; -import { matchType, nullableFromUnion } from "../TypeUtils"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Namer, Name, DependencyName, funPrefixNamer } from "../Naming"; -import { - legalizeCharacters, - isLetterOrUnderscoreOrDigit, - isLetterOrUnderscore, - decapitalize, - stringEscape, - isAscii, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle -} from "../support/Strings"; -import { defined } from "../support/Support"; -import { Sourcelike, annotated, MultiWord, singleWord, multiWord, parenIfNeeded } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { RenderContext } from "../Renderer"; - -export const elmOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - useList: new EnumOption("array-type", "Use Array or List", [ - ["array", false], - ["list", true] - ]), - // FIXME: Do this via a configurable named eventually. - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") -}; - -export class ElmTargetLanguage extends TargetLanguage { - constructor() { - super("Elm", ["elm"], "elm"); - } - - protected getOptions(): Option[] { - return [elmOptions.justTypes, elmOptions.moduleName, elmOptions.useList]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): ElmRenderer { - return new ElmRenderer(this, renderContext, getOptionValues(elmOptions, untypedOptionValues)); - } -} - -const forbiddenNames = [ - "if", - "then", - "else", - "case", - "of", - "let", - "in", - "infix", - "type", - "module", - "where", - "import", - "exposing", - "as", - "port", - "int", - "float", - "bool", - "string", - "Jenc", - "Jdec", - "Jpipe", - "always", - "identity", - "Array", - "List", - "Dict", - "Maybe", - "map", - "toList", - "makeArrayEncoder", - "makeDictEncoder", - "makeNullableEncoder", - "Int", - "True", - "False", - "String", - "Float" -]; - -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -function elmNameStyle(original: string, upper: boolean): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - upper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isLetterOrUnderscore - ); -} - -const upperNamingFunction = funPrefixNamer("upper", n => elmNameStyle(n, true)); -const lowerNamingFunction = funPrefixNamer("lower", n => elmNameStyle(n, false)); +import { arrayIntercalate, mapContains } from "collection-utils"; -type RequiredOrOptional = { - reqOrOpt: string; - fallback: string; -}; - -function requiredOrOptional(p: ClassProperty): RequiredOrOptional { - function optional(fallback: string): RequiredOrOptional { - return { reqOrOpt: "Jpipe.optional", fallback }; - } - const t = p.type; - if (p.isOptional || (t instanceof UnionType && nullableFromUnion(t) !== null)) { - return optional(" Nothing"); - } - if (t.kind === "null") { - return optional(" ()"); - } - return { reqOrOpt: "Jpipe.required", fallback: "" }; -} +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { + type MultiWord, + type Sourcelike, + annotated, + multiWord, + parenIfNeeded, + singleWord, +} from "../../Source"; +import { decapitalize, stringEscape } from "../../support/Strings"; +import { defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import type { + ClassProperty, + ClassType, + EnumType, + Type, + UnionType, +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../Type/TypeUtils"; + +import { forbiddenNames } from "./constants"; +import type { elmOptions } from "./language"; +import { + lowerNamingFunction, + requiredOrOptional, + upperNamingFunction, +} from "./utils"; -type TopLevelDependent = { - encoder: Name; +interface TopLevelDependent { decoder?: Name; -}; - -type NamedTypeDependent = { encoder: Name; +} + +interface NamedTypeDependent { decoder: Name; -}; + encoder: Name; +} export class ElmRenderer extends ConvenienceRenderer { private readonly _topLevelDependents = new Map(); + private readonly _namedTypeDependents = new Map(); - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return forbiddenNames; } - protected makeTopLevelDependencyNames(t: Type, topLevelName: Name): DependencyName[] { + protected makeTopLevelDependencyNames( + t: Type, + topLevelName: Name, + ): DependencyName[] { const encoder = new DependencyName( lowerNamingFunction, topLevelName.order, - lookup => `${lookup(topLevelName)}_to_string` + (lookup) => `${lookup(topLevelName)}_to_string`, ); let decoder: DependencyName | undefined = undefined; if (this.namedTypeToNameForTopLevel(t) === undefined) { - decoder = new DependencyName(lowerNamingFunction, topLevelName.order, lookup => lookup(topLevelName)); + decoder = new DependencyName( + lowerNamingFunction, + topLevelName.order, + (lookup) => lookup(topLevelName), + ); } + this._topLevelDependents.set(topLevelName, { encoder, decoder }); if (decoder !== undefined) { return [encoder, decoder]; } + return [encoder]; } @@ -182,9 +96,20 @@ export class ElmRenderer extends ConvenienceRenderer { return upperNamingFunction; } - protected makeNamedTypeDependencyNames(_: Type, typeName: Name): DependencyName[] { - const encoder = new DependencyName(lowerNamingFunction, typeName.order, lookup => `encode_${lookup(typeName)}`); - const decoder = new DependencyName(lowerNamingFunction, typeName.order, lookup => lookup(typeName)); + protected makeNamedTypeDependencyNames( + _: Type, + typeName: Name, + ): DependencyName[] { + const encoder = new DependencyName( + lowerNamingFunction, + typeName.order, + (lookup) => `encode_${lookup(typeName)}`, + ); + const decoder = new DependencyName( + lowerNamingFunction, + typeName.order, + (lookup) => lookup(typeName), + ); this._namedTypeDependents.set(typeName, { encoder, decoder }); return [encoder, decoder]; } @@ -193,7 +118,10 @@ export class ElmRenderer extends ConvenienceRenderer { return lowerNamingFunction; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -217,9 +145,14 @@ export class ElmRenderer extends ConvenienceRenderer { u: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { - const fieldName = super.proposeUnionMemberName(u, unionName, fieldType, lookup); + const fieldName = super.proposeUnionMemberName( + u, + unionName, + fieldType, + lookup, + ); return `${fieldName}_in_${lookup(unionName)}`; } @@ -229,9 +162,15 @@ export class ElmRenderer extends ConvenienceRenderer { protected emitDescriptionBlock(lines: Sourcelike[]): void { if (lines.length === 1) { - this.emitLine("{-| ", lines[0], " -}"); + this.emitComments([ + { customLines: lines, lineStart: "{-| ", lineEnd: " -}" }, + ]); } else { - this.emitCommentLines(lines, "", undefined, "-}", "{-| "); + this.emitCommentLines(lines, { + firstLineStart: "{-| ", + lineStart: "", + afterComment: "-}", + }); } } @@ -242,34 +181,50 @@ export class ElmRenderer extends ConvenienceRenderer { private elmType(t: Type, noOptional = false): MultiWord { return matchType( t, - _anyType => singleWord(annotated(anyTypeIssueAnnotation, "Jdec.Value")), - _nullType => singleWord(annotated(nullTypeIssueAnnotation, "()")), - _boolType => singleWord("Bool"), - _integerType => singleWord("Int"), - _doubleType => singleWord("Float"), - _stringType => singleWord("String"), - arrayType => multiWord(" ", this.arrayType, parenIfNeeded(this.elmType(arrayType.items))), - classType => singleWord(this.nameForNamedType(classType)), - mapType => multiWord(" ", "Dict String", parenIfNeeded(this.elmType(mapType.values))), - enumType => singleWord(this.nameForNamedType(enumType)), - unionType => { + (_anyType) => + singleWord(annotated(anyTypeIssueAnnotation, "Jdec.Value")), + (_nullType) => singleWord(annotated(nullTypeIssueAnnotation, "()")), + (_boolType) => singleWord("Bool"), + (_integerType) => singleWord("Int"), + (_doubleType) => singleWord("Float"), + (_stringType) => singleWord("String"), + (arrayType) => + multiWord( + " ", + this.arrayType, + parenIfNeeded(this.elmType(arrayType.items)), + ), + (classType) => singleWord(this.nameForNamedType(classType)), + (mapType) => + multiWord( + " ", + "Dict String", + parenIfNeeded(this.elmType(mapType.values)), + ), + (enumType) => singleWord(this.nameForNamedType(enumType)), + (unionType) => { const nullable = nullableFromUnion(unionType); if (nullable !== null) { const nullableType = this.elmType(nullable); if (noOptional) return nullableType; return multiWord(" ", "Maybe", parenIfNeeded(nullableType)); } + return singleWord(this.nameForNamedType(unionType)); - } + }, ); } private elmProperty(p: ClassProperty): Sourcelike { if (p.isOptional) { - return multiWord(" ", "Maybe", parenIfNeeded(this.elmType(p.type, true))).source; - } else { - return this.elmType(p.type).source; + return multiWord( + " ", + "Maybe", + parenIfNeeded(this.elmType(p.type, true)), + ).source; } + + return this.elmType(p.type).source; } private decoderNameForNamedType(t: Type): Name { @@ -280,39 +235,53 @@ export class ElmRenderer extends ConvenienceRenderer { private decoderNameForType(t: Type, noOptional = false): MultiWord { return matchType( t, - _anyType => singleWord("Jdec.value"), - _nullType => multiWord(" ", "Jdec.null", "()"), - _boolType => singleWord("Jdec.bool"), - _integerType => singleWord("Jdec.int"), - _doubleType => singleWord("Jdec.float"), - _stringType => singleWord("Jdec.string"), - arrayType => + (_anyType) => singleWord("Jdec.value"), + (_nullType) => multiWord(" ", "Jdec.null", "()"), + (_boolType) => singleWord("Jdec.bool"), + (_integerType) => singleWord("Jdec.int"), + (_doubleType) => singleWord("Jdec.float"), + (_stringType) => singleWord("Jdec.string"), + (arrayType) => multiWord( " ", ["Jdec.", decapitalize(this.arrayType)], - parenIfNeeded(this.decoderNameForType(arrayType.items)) + parenIfNeeded(this.decoderNameForType(arrayType.items)), + ), + (classType) => singleWord(this.decoderNameForNamedType(classType)), + (mapType) => + multiWord( + " ", + "Jdec.dict", + parenIfNeeded(this.decoderNameForType(mapType.values)), ), - classType => singleWord(this.decoderNameForNamedType(classType)), - mapType => multiWord(" ", "Jdec.dict", parenIfNeeded(this.decoderNameForType(mapType.values))), - enumType => singleWord(this.decoderNameForNamedType(enumType)), - unionType => { + (enumType) => singleWord(this.decoderNameForNamedType(enumType)), + (unionType) => { const nullable = nullableFromUnion(unionType); if (nullable !== null) { const nullableDecoder = this.decoderNameForType(nullable); if (noOptional) return nullableDecoder; - return multiWord(" ", "Jdec.nullable", parenIfNeeded(nullableDecoder)); + return multiWord( + " ", + "Jdec.nullable", + parenIfNeeded(nullableDecoder), + ); } + return singleWord(this.decoderNameForNamedType(unionType)); - } + }, ); } private decoderNameForProperty(p: ClassProperty): MultiWord { if (p.isOptional) { - return multiWord(" ", "Jdec.nullable", parenIfNeeded(this.decoderNameForType(p.type, true))); - } else { - return this.decoderNameForType(p.type); + return multiWord( + " ", + "Jdec.nullable", + parenIfNeeded(this.decoderNameForType(p.type, true)), + ); } + + return this.decoderNameForType(p.type); } private encoderNameForNamedType(t: Type): Name { @@ -323,49 +292,71 @@ export class ElmRenderer extends ConvenienceRenderer { private encoderNameForType(t: Type, noOptional = false): MultiWord { return matchType( t, - _anyType => singleWord("identity"), - _nullType => multiWord(" ", "always", "Jenc.null"), - _boolType => singleWord("Jenc.bool"), - _integerType => singleWord("Jenc.int"), - _doubleType => singleWord("Jenc.float"), - _stringType => singleWord("Jenc.string"), - arrayType => + (_anyType) => singleWord("identity"), + (_nullType) => multiWord(" ", "always", "Jenc.null"), + (_boolType) => singleWord("Jenc.bool"), + (_integerType) => singleWord("Jenc.int"), + (_doubleType) => singleWord("Jenc.float"), + (_stringType) => singleWord("Jenc.string"), + (arrayType) => multiWord( " ", ["make", this.arrayType, "Encoder"], - parenIfNeeded(this.encoderNameForType(arrayType.items)) + parenIfNeeded(this.encoderNameForType(arrayType.items)), ), - classType => singleWord(this.encoderNameForNamedType(classType)), - mapType => multiWord(" ", "makeDictEncoder", parenIfNeeded(this.encoderNameForType(mapType.values))), - enumType => singleWord(this.encoderNameForNamedType(enumType)), - unionType => { + (classType) => singleWord(this.encoderNameForNamedType(classType)), + (mapType) => + multiWord( + " ", + "makeDictEncoder", + parenIfNeeded(this.encoderNameForType(mapType.values)), + ), + (enumType) => singleWord(this.encoderNameForNamedType(enumType)), + (unionType) => { const nullable = nullableFromUnion(unionType); if (nullable !== null) { const nullableEncoder = this.encoderNameForType(nullable); if (noOptional) return nullableEncoder; - return multiWord(" ", "makeNullableEncoder", parenIfNeeded(nullableEncoder)); + return multiWord( + " ", + "makeNullableEncoder", + parenIfNeeded(nullableEncoder), + ); } + return singleWord(this.encoderNameForNamedType(unionType)); - } + }, ); } private encoderNameForProperty(p: ClassProperty): MultiWord { if (p.isOptional) { - return multiWord(" ", "makeNullableEncoder", parenIfNeeded(this.encoderNameForType(p.type, true))); - } else { - return this.encoderNameForType(p.type); + return multiWord( + " ", + "makeNullableEncoder", + parenIfNeeded(this.encoderNameForType(p.type, true)), + ); } + + return this.encoderNameForType(p.type); } private emitTopLevelDefinition(t: Type, topLevelName: Name): void { - this.emitLine("type alias ", topLevelName, " = ", this.elmType(t).source); + this.emitLine( + "type alias ", + topLevelName, + " = ", + this.elmType(t).source, + ); } private emitClassDefinition(c: ClassType, className: Name): void { let description = this.descriptionForType(c); this.forEachClassProperty(c, "none", (name, jsonName) => { - const propertyDescription = this.descriptionForClassProperty(c, jsonName); + const propertyDescription = this.descriptionForClassProperty( + c, + jsonName, + ); if (propertyDescription === undefined) return; if (description === undefined) { @@ -373,6 +364,7 @@ export class ElmRenderer extends ConvenienceRenderer { } else { description.push(""); } + description.push(`${this.sourcelikeToString(name)}:`); description.push(...propertyDescription); }); @@ -382,12 +374,19 @@ export class ElmRenderer extends ConvenienceRenderer { this.indent(() => { let onFirst = true; this.forEachClassProperty(c, "none", (name, _jsonName, p) => { - this.emitLine(onFirst ? "{" : ",", " ", name, " : ", this.elmProperty(p)); + this.emitLine( + onFirst ? "{" : ",", + " ", + name, + " : ", + this.elmProperty(p), + ); onFirst = false; }); if (onFirst) { this.emitLine("{"); } + this.emitLine("}"); }); } @@ -397,7 +396,7 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("type ", enumName); this.indent(() => { let onFirst = true; - this.forEachEnumCase(e, "none", name => { + this.forEachEnumCase(e, "none", (name) => { const equalsOrPipe = onFirst ? "=" : "|"; this.emitLine(equalsOrPipe, " ", name); onFirst = false; @@ -410,27 +409,46 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("type ", unionName); this.indent(() => { let onFirst = true; - this.forEachUnionMember(u, null, "none", null, (constructor, t) => { + this.forEachUnionMember(u, null, "none", null, (name, t) => { const equalsOrPipe = onFirst ? "=" : "|"; if (t.kind === "null") { - this.emitLine(equalsOrPipe, " ", constructor); + this.emitLine(equalsOrPipe, " ", name); } else { - this.emitLine(equalsOrPipe, " ", constructor, " ", parenIfNeeded(this.elmType(t))); + this.emitLine( + equalsOrPipe, + " ", + name, + " ", + parenIfNeeded(this.elmType(t)), + ); } + onFirst = false; }); }); } private emitTopLevelFunctions(t: Type, topLevelName: Name): void { - const { encoder, decoder } = defined(this._topLevelDependents.get(topLevelName)); + const { encoder, decoder } = defined( + this._topLevelDependents.get(topLevelName), + ); if (this.namedTypeToNameForTopLevel(t) === undefined) { this.emitLine(defined(decoder), " : Jdec.Decoder ", topLevelName); - this.emitLine(defined(decoder), " = ", this.decoderNameForType(t).source); + this.emitLine( + defined(decoder), + " = ", + this.decoderNameForType(t).source, + ); this.ensureBlankLine(); } + this.emitLine(encoder, " : ", topLevelName, " -> String"); - this.emitLine(encoder, " r = Jenc.encode 0 (", this.encoderNameForType(t).source, " r)"); + this.emitLine( + encoder, + " r = Jenc.encode 0 (", + this.encoderNameForType(t).source, + " r)", + ); } private emitClassFunctions(c: ClassType, className: Name): void { @@ -441,9 +459,19 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("Jpipe.decode ", className); this.indent(() => { this.forEachClassProperty(c, "none", (_, jsonName, p) => { - const propDecoder = parenIfNeeded(this.decoderNameForProperty(p)); + const propDecoder = parenIfNeeded( + this.decoderNameForProperty(p), + ); const { reqOrOpt, fallback } = requiredOrOptional(p); - this.emitLine("|> ", reqOrOpt, ' "', stringEscape(jsonName), '" ', propDecoder, fallback); + this.emitLine( + "|> ", + reqOrOpt, + ' "', + stringEscape(jsonName), + '" ', + propDecoder, + fallback, + ); }); }); }); @@ -459,12 +487,22 @@ export class ElmRenderer extends ConvenienceRenderer { this.forEachClassProperty(c, "none", (name, jsonName, p) => { const bracketOrComma = onFirst ? "[" : ","; const propEncoder = this.encoderNameForProperty(p).source; - this.emitLine(bracketOrComma, ' ("', stringEscape(jsonName), '", ', propEncoder, " x.", name, ")"); + this.emitLine( + bracketOrComma, + ' ("', + stringEscape(jsonName), + '", ', + propEncoder, + " x.", + name, + ")", + ); onFirst = false; }); if (onFirst) { this.emitLine("["); } + this.emitLine("]"); }); }); @@ -482,9 +520,18 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("case str of"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine('"', stringEscape(jsonName), '" -> Jdec.succeed ', name); + this.emitLine( + '"', + stringEscape(jsonName), + '" -> Jdec.succeed ', + name, + ); }); - this.emitLine('somethingElse -> Jdec.fail <| "Invalid ', enumName, ': " ++ somethingElse'); + this.emitLine( + 'somethingElse -> Jdec.fail <| "Invalid ', + enumName, + ': " ++ somethingElse', + ); }); }); this.emitLine(")"); @@ -497,7 +544,12 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine(encoderName, " x = case x of"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine(name, ' -> Jenc.string "', stringEscape(jsonName), '"'); + this.emitLine( + name, + ' -> Jenc.string "', + stringEscape(jsonName), + '"', + ); }); }); } @@ -507,11 +559,14 @@ export class ElmRenderer extends ConvenienceRenderer { function sortOrder(_: Name, t: Type): string { if (t.kind === "array") { return " array"; - } else if (t.kind === "double") { + } + if (t.kind === "double") { return " xdouble"; - } else if (t.isPrimitive()) { + } + if (t.isPrimitive()) { return " " + t.kind; } + return t.kind; } @@ -522,16 +577,31 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine("Jdec.oneOf"); this.indent(() => { let onFirst = true; - this.forEachUnionMember(u, null, "none", sortOrder, (constructor, t) => { - const bracketOrComma = onFirst ? "[" : ","; - if (t.kind === "null") { - this.emitLine(bracketOrComma, " Jdec.null ", constructor); - } else { - const decoder = parenIfNeeded(this.decoderNameForType(t)); - this.emitLine(bracketOrComma, " Jdec.map ", constructor, " ", decoder); - } - onFirst = false; - }); + this.forEachUnionMember( + u, + null, + "none", + sortOrder, + (name, t) => { + const bracketOrComma = onFirst ? "[" : ","; + if (t.kind === "null") { + this.emitLine(bracketOrComma, " Jdec.null ", name); + } else { + const decoder = parenIfNeeded( + this.decoderNameForType(t), + ); + this.emitLine( + bracketOrComma, + " Jdec.map ", + name, + " ", + decoder, + ); + } + + onFirst = false; + }, + ); this.emitLine("]"); }); }); @@ -541,12 +611,12 @@ export class ElmRenderer extends ConvenienceRenderer { this.emitLine(encoderName, " : ", unionName, " -> Jenc.Value"); this.emitLine(encoderName, " x = case x of"); this.indent(() => { - this.forEachUnionMember(u, null, "none", sortOrder, (constructor, t) => { + this.forEachUnionMember(u, null, "none", sortOrder, (name, t) => { if (t.kind === "null") { - this.emitLine(constructor, " -> Jenc.null"); + this.emitLine(name, " -> Jenc.null"); } else { const encoder = this.encoderNameForType(t).source; - this.emitLine(constructor, " y -> ", encoder, " y"); + this.emitLine(name, " y -> ", encoder, " y"); } }); }); @@ -556,10 +626,13 @@ export class ElmRenderer extends ConvenienceRenderer { const exports: Sourcelike[] = []; const topLevelDecoders: Sourcelike[] = []; this.forEachTopLevel("none", (_, name) => { - let { encoder, decoder } = defined(this._topLevelDependents.get(name)); + let { encoder, decoder } = defined( + this._topLevelDependents.get(name), + ); if (decoder === undefined) { decoder = defined(this._namedTypeDependents.get(name)).decoder; } + topLevelDecoders.push(decoder); exports.push(name, encoder, decoder); }); @@ -574,7 +647,7 @@ export class ElmRenderer extends ConvenienceRenderer { }); if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); + this.emitComments(this.leadingComments); } else if (!this._options.justTypes) { this.emitCommentLines([ "To decode the JSON data, add this file to your project, run", @@ -583,14 +656,14 @@ export class ElmRenderer extends ConvenienceRenderer { "", "add these imports", "", - " import Json.Decode exposing (decodeString)`);" + " import Json.Decode exposing (decodeString)`);", ]); this.emitLine( "-- import ", this._options.moduleName, " exposing (", arrayIntercalate(", ", topLevelDecoders), - ")" + ")", ); this.emitMultiline(`-- -- and you're off to the races with @@ -598,8 +671,11 @@ export class ElmRenderer extends ConvenienceRenderer { this.forEachTopLevel("none", (_, name) => { let { decoder } = defined(this._topLevelDependents.get(name)); if (decoder === undefined) { - decoder = defined(this._namedTypeDependents.get(name)).decoder; + decoder = defined( + this._namedTypeDependents.get(name), + ).decoder; } + this.emitLine("-- decodeString ", decoder, " myJsonString"); }); } @@ -611,6 +687,7 @@ export class ElmRenderer extends ConvenienceRenderer { for (let i = 0; i < exports.length; i++) { this.emitLine(i === 0 ? "(" : ",", " ", exports[i]); } + this.emitLine(")"); }); this.ensureBlankLine(); @@ -628,47 +705,68 @@ import Dict exposing (Dict, map, toList)`); this.forEachTopLevel( "leading-and-interposing", - (t: Type, topLevelName: Name) => this.emitTopLevelDefinition(t, topLevelName), - t => this.namedTypeToNameForTopLevel(t) === undefined + (t: Type, topLevelName: Name) => + this.emitTopLevelDefinition(t, topLevelName), + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachNamedType( "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassDefinition(c, className), - (e: EnumType, enumName: Name) => this.emitEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName) + (c: ClassType, className: Name) => + this.emitClassDefinition(c, className), + (e: EnumType, enumName: Name) => + this.emitEnumDefinition(e, enumName), + (u: UnionType, unionName: Name) => + this.emitUnionDefinition(u, unionName), ); if (this._options.justTypes) return; this.ensureBlankLine(); this.emitLine("-- decoders and encoders"); - this.forEachTopLevel("leading-and-interposing", (t: Type, topLevelName: Name) => - this.emitTopLevelFunctions(t, topLevelName) + this.forEachTopLevel( + "leading-and-interposing", + (t: Type, topLevelName: Name) => + this.emitTopLevelFunctions(t, topLevelName), ); this.forEachNamedType( "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassFunctions(c, className), - (e: EnumType, enumName: Name) => this.emitEnumFunctions(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName) + (c: ClassType, className: Name) => + this.emitClassFunctions(c, className), + (e: EnumType, enumName: Name) => + this.emitEnumFunctions(e, enumName), + (u: UnionType, unionName: Name) => + this.emitUnionFunctions(u, unionName), ); this.ensureBlankLine(); this.emitLine("--- encoder helpers"); this.ensureBlankLine(); - this.emitLine("make", this.arrayType, "Encoder : (a -> Jenc.Value) -> ", this.arrayType, " a -> Jenc.Value"); + this.emitLine( + "make", + this.arrayType, + "Encoder : (a -> Jenc.Value) -> ", + this.arrayType, + " a -> Jenc.Value", + ); this.emitLine("make", this.arrayType, "Encoder f arr ="); this.indent(() => { - this.emitLine("Jenc.", decapitalize(this.arrayType), " (", this.arrayType, ".map f arr)"); + this.emitLine( + "Jenc.", + decapitalize(this.arrayType), + " (", + this.arrayType, + ".map f arr)", + ); }); this.ensureBlankLine(); this.emitMultiline(`makeDictEncoder : (a -> Jenc.Value) -> Dict String a -> Jenc.Value makeDictEncoder f dict = - Jenc.object (toList (Dict.map (\\k -> f) dict)) + Jenc.object (toList (Dict.map (\\k -> f) dict)) makeNullableEncoder : (a -> Jenc.Value) -> Maybe a -> Jenc.Value makeNullableEncoder f m = - case m of - Just x -> f x - Nothing -> Jenc.null`); + case m of + Just x -> f x + Nothing -> Jenc.null`); } } diff --git a/packages/quicktype-core/src/language/Elm/constants.ts b/packages/quicktype-core/src/language/Elm/constants.ts new file mode 100644 index 000000000..5b3d11973 --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/constants.ts @@ -0,0 +1,40 @@ +export const forbiddenNames = [ + "if", + "then", + "else", + "case", + "of", + "let", + "in", + "infix", + "type", + "module", + "where", + "import", + "exposing", + "as", + "port", + "int", + "float", + "bool", + "string", + "Jenc", + "Jdec", + "Jpipe", + "always", + "identity", + "Array", + "List", + "Dict", + "Maybe", + "map", + "toList", + "makeArrayEncoder", + "makeDictEncoder", + "makeNullableEncoder", + "Int", + "True", + "False", + "String", + "Float", +] as const; diff --git a/packages/quicktype-core/src/language/Elm/index.ts b/packages/quicktype-core/src/language/Elm/index.ts new file mode 100644 index 000000000..9dcf263d0 --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/index.ts @@ -0,0 +1,2 @@ +export { ElmTargetLanguage, elmOptions } from "./language"; +export { ElmRenderer } from "./ElmRenderer"; diff --git a/packages/quicktype-core/src/language/Elm/language.ts b/packages/quicktype-core/src/language/Elm/language.ts new file mode 100644 index 000000000..7fc113618 --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/language.ts @@ -0,0 +1,68 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { ElmRenderer } from "./ElmRenderer"; + +export const elmOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + useList: new EnumOption( + "array-type", + "Use Array or List", + { + array: false, + list: true, + } as const, + "array", + ), + // FIXME: Do this via a configurable named eventually. + moduleName: new StringOption( + "module", + "Generated module name", + "NAME", + "QuickType", + ), +}; + +export const elmLanguageConfig = { + displayName: "Elm", + names: ["elm"], + extension: "elm", +} as const; + +export class ElmTargetLanguage extends TargetLanguage< + typeof elmLanguageConfig +> { + public constructor() { + super(elmLanguageConfig); + } + + public getOptions(): typeof elmOptions { + return elmOptions; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ElmRenderer { + return new ElmRenderer( + this, + renderContext, + getOptionValues(elmOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/Elm/utils.ts b/packages/quicktype-core/src/language/Elm/utils.ts new file mode 100644 index 000000000..31cb0b622 --- /dev/null +++ b/packages/quicktype-core/src/language/Elm/utils.ts @@ -0,0 +1,64 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords, +} from "../../support/Strings"; +import { type ClassProperty, UnionType } from "../../Type"; +import { nullableFromUnion } from "../../Type/TypeUtils"; + +const legalizeName = legalizeCharacters( + (cp) => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp), +); + +function elmNameStyle(original: string, upper: boolean): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + upper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isLetterOrUnderscore, + ); +} + +export const upperNamingFunction = funPrefixNamer("upper", (n) => + elmNameStyle(n, true), +); +export const lowerNamingFunction = funPrefixNamer("lower", (n) => + elmNameStyle(n, false), +); + +interface RequiredOrOptional { + fallback: string; + reqOrOpt: string; +} + +export function requiredOrOptional(p: ClassProperty): RequiredOrOptional { + function optional(fallback: string): RequiredOrOptional { + return { reqOrOpt: "Jpipe.optional", fallback }; + } + + const t = p.type; + if ( + p.isOptional || + (t instanceof UnionType && nullableFromUnion(t) !== null) + ) { + return optional(" Nothing"); + } + + if (t.kind === "null") { + return optional(" ()"); + } + + return { reqOrOpt: "Jpipe.required", fallback: "" }; +} diff --git a/packages/quicktype-core/src/language/Golang.ts b/packages/quicktype-core/src/language/Golang.ts deleted file mode 100644 index 42cfacddd..000000000 --- a/packages/quicktype-core/src/language/Golang.ts +++ /dev/null @@ -1,588 +0,0 @@ -import { TypeKind, Type, ClassType, EnumType, UnionType, ClassProperty } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Name, DependencyName, Namer, funPrefixNamer } from "../Naming"; -import { - legalizeCharacters, - isLetterOrUnderscore, - isLetterOrUnderscoreOrDigit, - stringEscape, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, - camelCase -} from "../support/Strings"; -import { assert, defined } from "../support/Support"; -import { StringOption, BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { TargetLanguage } from "../TargetLanguage"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { RenderContext } from "../Renderer"; - -export const goOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - justTypesAndPackage: new BooleanOption("just-types-and-package", "Plain types with package only", false), - packageName: new StringOption("package", "Generated package name", "NAME", "main"), - multiFileOutput: new BooleanOption("multi-file-output", "Renders each top-level object in its own Go file", false), - fieldTags: new StringOption("field-tags", "list of tags which should be generated for fields", "TAGS", "json") -}; - -export class GoTargetLanguage extends TargetLanguage { - constructor() { - super("Go", ["go", "golang"], "go"); - } - - protected getOptions(): Option[] { - return [ - goOptions.justTypes, - goOptions.packageName, - goOptions.multiFileOutput, - goOptions.justTypesAndPackage, - goOptions.fieldTags - ]; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): GoRenderer { - return new GoRenderer(this, renderContext, getOptionValues(goOptions, untypedOptionValues)); - } - - protected get defaultIndentation(): string { - return "\t"; - } -} - -const namingFunction = funPrefixNamer("namer", goNameStyle); - -const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); - -function goNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isLetterOrUnderscore - ); -} - -const primitiveValueTypeKinds: TypeKind[] = ["integer", "double", "bool", "string"]; -const compoundTypeKinds: TypeKind[] = ["array", "class", "map", "enum"]; - -function isValueType(t: Type): boolean { - const kind = t.kind; - return primitiveValueTypeKinds.indexOf(kind) >= 0 || kind === "class" || kind === "enum"; -} - -function canOmitEmpty(cp: ClassProperty): boolean { - if (!cp.isOptional) return false; - const t = cp.type; - return ["union", "null", "any"].indexOf(t.kind) < 0; -} - -export class GoRenderer extends ConvenienceRenderer { - private readonly _topLevelUnmarshalNames = new Map(); - private _currentFilename: string | undefined; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected makeNamedTypeNamer(): Namer { - return namingFunction; - } - - protected namerForObjectProperty(): Namer { - return namingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return namingFunction; - } - - protected makeEnumCaseNamer(): Namer { - return namingFunction; - } - - protected get enumCasesInGlobalNamespace(): boolean { - return true; - } - - protected makeTopLevelDependencyNames(_: Type, topLevelName: Name): DependencyName[] { - const unmarshalName = new DependencyName( - namingFunction, - topLevelName.order, - lookup => `unmarshal_${lookup(topLevelName)}` - ); - this._topLevelUnmarshalNames.set(topLevelName, unmarshalName); - return [unmarshalName]; - } - - /// startFile takes a file name, lowercases it, appends ".go" to it, and sets it as the current filename. - protected startFile(basename: Sourcelike): void { - if (this._options.multiFileOutput === false) { - return; - } - - assert(this._currentFilename === undefined, "Previous file wasn't finished: " + this._currentFilename); - this._currentFilename = `${this.sourcelikeToString(basename)}.go`; - this.initializeEmitContextForFilename(this._currentFilename); - } - - /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. - protected endFile(): void { - if (this._options.multiFileOutput === false) { - return; - } - - this.finishFile(defined(this._currentFilename)); - this._currentFilename = undefined; - } - - private emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line, " {"); - this.indent(f); - this.emitLine("}"); - } - - private emitFunc(decl: Sourcelike, f: () => void): void { - this.emitBlock(["func ", decl], f); - } - - private emitStruct(name: Name, table: Sourcelike[][]): void { - this.emitBlock(["type ", name, " struct"], () => this.emitTable(table)); - } - - private nullableGoType(t: Type, withIssues: boolean): Sourcelike { - const goType = this.goType(t, withIssues); - if (isValueType(t)) { - return ["*", goType]; - } else { - return goType; - } - } - - private propertyGoType(cp: ClassProperty): Sourcelike { - const t = cp.type; - if (t instanceof UnionType && nullableFromUnion(t) === null) { - return ["*", this.goType(t, true)]; - } - if (cp.isOptional) { - return this.nullableGoType(t, true); - } - return this.goType(t, true); - } - - private goType(t: Type, withIssues = false): Sourcelike { - return matchType( - t, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "interface{}"), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "interface{}"), - _boolType => "bool", - _integerType => "int64", - _doubleType => "float64", - _stringType => "string", - arrayType => ["[]", this.goType(arrayType.items, withIssues)], - classType => this.nameForNamedType(classType), - mapType => { - let valueSource: Sourcelike; - const v = mapType.values; - if (v instanceof UnionType && nullableFromUnion(v) === null) { - valueSource = ["*", this.nameForNamedType(v)]; - } else { - valueSource = this.goType(v, withIssues); - } - return ["map[string]", valueSource]; - }, - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return this.nullableGoType(nullable, withIssues); - return this.nameForNamedType(unionType); - } - ); - } - - private emitTopLevel(t: Type, name: Name): void { - this.startFile(name); - - if ( - this._options.multiFileOutput && - this._options.justTypes === false && - this._options.justTypesAndPackage === false && - this.leadingComments === undefined - ) { - this.emitLineOnce( - "// This file was generated from JSON Schema using quicktype, do not modify it directly." - ); - this.emitLineOnce("// To parse and unparse this JSON data, add this code to your project and do:"); - this.emitLineOnce("//"); - const ref = modifySource(camelCase, name); - this.emitLineOnce("// ", ref, ", err := ", defined(this._topLevelUnmarshalNames.get(name)), "(bytes)"); - this.emitLineOnce("// bytes, err = ", ref, ".Marshal()"); - } - - this.emitPackageDefinitons(true); - - const unmarshalName = defined(this._topLevelUnmarshalNames.get(name)); - if (this.namedTypeToNameForTopLevel(t) === undefined) { - this.emitLine("type ", name, " ", this.goType(t)); - } - - if (this._options.justTypes || this._options.justTypesAndPackage) return; - - this.ensureBlankLine(); - this.emitFunc([unmarshalName, "(data []byte) (", name, ", error)"], () => { - this.emitLine("var r ", name); - this.emitLine("err := json.Unmarshal(data, &r)"); - this.emitLine("return r, err"); - }); - this.ensureBlankLine(); - this.emitFunc(["(r *", name, ") Marshal() ([]byte, error)"], () => { - this.emitLine("return json.Marshal(r)"); - }); - this.endFile(); - } - - private emitClass(c: ClassType, className: Name): void { - this.startFile(className); - this.emitPackageDefinitons(false); - let columns: Sourcelike[][] = []; - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const description = this.descriptionForClassProperty(c, jsonName); - const docStrings = - description !== undefined && description.length > 0 ? description.map(d => "// " + d) : []; - const goType = this.propertyGoType(p); - const omitEmpty = canOmitEmpty(p) ? ",omitempty" : []; - - docStrings.forEach(doc => columns.push([doc])); - const tags = this._options.fieldTags - .split(",") - .map(tag => tag + ':"' + stringEscape(jsonName) + omitEmpty + '"') - .join(" "); - columns.push([ - [name, " "], - [goType, " "], - ["`", tags, "`"] - ]); - }); - this.emitDescription(this.descriptionForType(c)); - this.emitStruct(className, columns); - this.endFile(); - } - - private emitEnum(e: EnumType, enumName: Name): void { - this.startFile(enumName); - this.emitPackageDefinitons(false); - this.emitDescription(this.descriptionForType(e)); - this.emitLine("type ", enumName, " string"); - this.ensureBlankLine(); - this.emitLine("const ("); - let columns: Sourcelike[][] = []; - this.forEachEnumCase(e, "none", (name, jsonName) => { - columns.push([ - [name, " "], - [enumName, ' = "', stringEscape(jsonName), '"'] - ]); - }); - this.indent(() => this.emitTable(columns)); - this.emitLine(")"); - this.endFile(); - } - - private emitUnion(u: UnionType, unionName: Name): void { - this.startFile(unionName); - this.emitPackageDefinitons(false); - const [hasNull, nonNulls] = removeNullFromUnion(u); - const isNullableArg = hasNull !== null ? "true" : "false"; - - const ifMember: ( - kind: TypeKind, - ifNotMember: U, - f: (t: Type, fieldName: Name, goType: Sourcelike) => T - ) => T | U = (kind, ifNotMember, f) => { - const maybeType = u.findMember(kind); - if (maybeType === undefined) return ifNotMember; - return f(maybeType, this.nameForUnionMember(u, maybeType), this.goType(maybeType)); - }; - - const maybeAssignNil = (kind: TypeKind): void => { - ifMember(kind, undefined, (_1, fieldName, _2) => { - this.emitLine("x.", fieldName, " = nil"); - }); - }; - const makeArgs = ( - primitiveArg: (fieldName: Sourcelike) => Sourcelike, - compoundArg: (isClass: boolean, fieldName: Sourcelike) => Sourcelike - ): Sourcelike => { - const args: Sourcelike = []; - for (const kind of primitiveValueTypeKinds) { - args.push( - ifMember(kind, "nil", (_1, fieldName, _2) => primitiveArg(fieldName)), - ", " - ); - } - for (const kind of compoundTypeKinds) { - args.push( - ifMember(kind, "false, nil", (t, fieldName, _) => compoundArg(t.kind === "class", fieldName)), - ", " - ); - } - args.push(isNullableArg); - return args; - }; - - let columns: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { - const goType = this.nullableGoType(t, true); - columns.push([[fieldName, " "], goType]); - }); - this.emitDescription(this.descriptionForType(u)); - this.emitStruct(unionName, columns); - - if (this._options.justTypes || this._options.justTypesAndPackage) return; - - this.ensureBlankLine(); - this.emitFunc(["(x *", unionName, ") UnmarshalJSON(data []byte) error"], () => { - for (const kind of compoundTypeKinds) { - maybeAssignNil(kind); - } - ifMember("class", undefined, (_1, _2, goType) => { - this.emitLine("var c ", goType); - }); - const args = makeArgs( - fn => ["&x.", fn], - (isClass, fn) => { - if (isClass) { - return "true, &c"; - } else { - return ["true, &x.", fn]; - } - } - ); - this.emitLine("object, err := unmarshalUnion(data, ", args, ")"); - this.emitBlock("if err != nil", () => { - this.emitLine("return err"); - }); - this.emitBlock("if object", () => { - ifMember("class", undefined, (_1, fieldName, _2) => { - this.emitLine("x.", fieldName, " = &c"); - }); - }); - this.emitLine("return nil"); - }); - this.ensureBlankLine(); - this.emitFunc(["(x *", unionName, ") MarshalJSON() ([]byte, error)"], () => { - const args = makeArgs( - fn => ["x.", fn], - (_, fn) => ["x.", fn, " != nil, x.", fn] - ); - this.emitLine("return marshalUnion(", args, ")"); - }); - this.endFile(); - } - - private emitSingleFileHeaderComments(): void { - this.emitLineOnce("// This file was generated from JSON Schema using quicktype, do not modify it directly."); - this.emitLineOnce("// To parse and unparse this JSON data, add this code to your project and do:"); - this.forEachTopLevel("none", (_: Type, name: Name) => { - this.emitLine("//"); - const ref = modifySource(camelCase, name); - this.emitLine("// ", ref, ", err := ", defined(this._topLevelUnmarshalNames.get(name)), "(bytes)"); - this.emitLine("// bytes, err = ", ref, ".Marshal()"); - }); - } - - private emitPackageDefinitons(includeJSONEncodingImport: boolean): void { - if (!this._options.justTypes || this._options.justTypesAndPackage) { - this.ensureBlankLine(); - const packageDeclaration = "package " + this._options.packageName; - this.emitLineOnce(packageDeclaration); - this.ensureBlankLine(); - } - - if (!this._options.justTypes && !this._options.justTypesAndPackage) { - this.ensureBlankLine(); - if (this.haveNamedUnions && this._options.multiFileOutput === false) { - this.emitLineOnce('import "bytes"'); - this.emitLineOnce('import "errors"'); - } - - if (includeJSONEncodingImport) { - this.emitLineOnce('import "encoding/json"'); - } - this.ensureBlankLine(); - } - } - - private emitHelperFunctions(): void { - if (this.haveNamedUnions) { - this.startFile("JSONSchemaSupport"); - this.emitPackageDefinitons(true); - if (this._options.multiFileOutput) { - this.emitLineOnce('import "bytes"'); - this.emitLineOnce('import "errors"'); - } - this.ensureBlankLine(); - this - .emitMultiline(`func unmarshalUnion(data []byte, pi **int64, pf **float64, pb **bool, ps **string, haveArray bool, pa interface{}, haveObject bool, pc interface{}, haveMap bool, pm interface{}, haveEnum bool, pe interface{}, nullable bool) (bool, error) { - if pi != nil { - *pi = nil - } - if pf != nil { - *pf = nil - } - if pb != nil { - *pb = nil - } - if ps != nil { - *ps = nil - } - - dec := json.NewDecoder(bytes.NewReader(data)) - dec.UseNumber() - tok, err := dec.Token() - if err != nil { - return false, err - } - - switch v := tok.(type) { - case json.Number: - if pi != nil { - i, err := v.Int64() - if err == nil { - *pi = &i - return false, nil - } - } - if pf != nil { - f, err := v.Float64() - if err == nil { - *pf = &f - return false, nil - } - return false, errors.New("Unparsable number") - } - return false, errors.New("Union does not contain number") - case float64: - return false, errors.New("Decoder should not return float64") - case bool: - if pb != nil { - *pb = &v - return false, nil - } - return false, errors.New("Union does not contain bool") - case string: - if haveEnum { - return false, json.Unmarshal(data, pe) - } - if ps != nil { - *ps = &v - return false, nil - } - return false, errors.New("Union does not contain string") - case nil: - if nullable { - return false, nil - } - return false, errors.New("Union does not contain null") - case json.Delim: - if v == '{' { - if haveObject { - return true, json.Unmarshal(data, pc) - } - if haveMap { - return false, json.Unmarshal(data, pm) - } - return false, errors.New("Union does not contain object") - } - if v == '[' { - if haveArray { - return false, json.Unmarshal(data, pa) - } - return false, errors.New("Union does not contain array") - } - return false, errors.New("Cannot handle delimiter") - } - return false, errors.New("Cannot unmarshal union") - -} - -func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, pa interface{}, haveObject bool, pc interface{}, haveMap bool, pm interface{}, haveEnum bool, pe interface{}, nullable bool) ([]byte, error) { - if pi != nil { - return json.Marshal(*pi) - } - if pf != nil { - return json.Marshal(*pf) - } - if pb != nil { - return json.Marshal(*pb) - } - if ps != nil { - return json.Marshal(*ps) - } - if haveArray { - return json.Marshal(pa) - } - if haveObject { - return json.Marshal(pc) - } - if haveMap { - return json.Marshal(pm) - } - if haveEnum { - return json.Marshal(pe) - } - if nullable { - return json.Marshal(nil) - } - return nil, errors.New("Union must not be null") -}`); - this.endFile(); - } - } - - protected emitSourceStructure(): void { - if ( - this._options.multiFileOutput === false && - this._options.justTypes === false && - this._options.justTypesAndPackage === false && - this.leadingComments === undefined - ) { - this.emitSingleFileHeaderComments(); - } - - this.forEachTopLevel( - "leading-and-interposing", - (t, name) => this.emitTopLevel(t, name), - t => - !(this._options.justTypes || this._options.justTypesAndPackage) || - this.namedTypeToNameForTopLevel(t) === undefined - ); - this.forEachObject("leading-and-interposing", (c: ClassType, className: Name) => this.emitClass(c, className)); - this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => this.emitEnum(u, enumName)); - this.forEachUnion("leading-and-interposing", (u: UnionType, unionName: Name) => this.emitUnion(u, unionName)); - - if (this._options.justTypes || this._options.justTypesAndPackage) { - return; - } - - this.emitHelperFunctions(); - } -} diff --git a/packages/quicktype-core/src/language/Golang/GolangRenderer.ts b/packages/quicktype-core/src/language/Golang/GolangRenderer.ts new file mode 100644 index 000000000..7dccdb039 --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/GolangRenderer.ts @@ -0,0 +1,712 @@ +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, type Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../../Source"; +import { camelCase, stringEscape } from "../../support/Strings"; +import { assert, defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + type ClassProperty, + type ClassType, + type EnumType, + type Type, + type TypeKind, + UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import type { goOptions } from "./language"; +import { + canOmitEmpty, + compoundTypeKinds, + isValueType, + namingFunction, + primitiveValueTypeKinds, +} from "./utils"; + +export class GoRenderer extends ConvenienceRenderer { + private readonly _topLevelUnmarshalNames = new Map(); + + private _currentFilename: string | undefined; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected makeNamedTypeNamer(): Namer { + return namingFunction; + } + + protected namerForObjectProperty(): Namer { + return namingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return namingFunction; + } + + protected makeEnumCaseNamer(): Namer { + return namingFunction; + } + + protected get enumCasesInGlobalNamespace(): boolean { + return true; + } + + protected makeTopLevelDependencyNames( + _: Type, + topLevelName: Name, + ): DependencyName[] { + const unmarshalName = new DependencyName( + namingFunction, + topLevelName.order, + (lookup) => `unmarshal_${lookup(topLevelName)}`, + ); + this._topLevelUnmarshalNames.set(topLevelName, unmarshalName); + return [unmarshalName]; + } + + /// startFile takes a file name, lowercases it, appends ".go" to it, and sets it as the current filename. + protected startFile(basename: Sourcelike): void { + if (this._options.multiFileOutput === false) { + return; + } + + assert( + this._currentFilename === undefined, + `Previous file wasn't finished: ${this._currentFilename}`, + ); + this._currentFilename = `${this.sourcelikeToString(basename)}.go`; + this.initializeEmitContextForFilename(this._currentFilename); + } + + /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. + protected endFile(): void { + if (this._options.multiFileOutput === false) { + return; + } + + this.finishFile(defined(this._currentFilename)); + this._currentFilename = undefined; + } + + private emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + private emitFunc(decl: Sourcelike, f: () => void): void { + this.emitBlock(["func ", decl], f); + } + + private emitStruct(name: Name, table: Sourcelike[][]): void { + this.emitBlock(["type ", name, " struct"], () => this.emitTable(table)); + } + + private nullableGoType(t: Type, withIssues: boolean): Sourcelike { + const goType = this.goType(t, withIssues); + if (isValueType(t)) { + return ["*", goType]; + } + + return goType; + } + + private propertyGoType(cp: ClassProperty): Sourcelike { + const t = cp.type; + if (t instanceof UnionType && nullableFromUnion(t) === null) { + return ["*", this.goType(t, true)]; + } + + if (cp.isOptional) { + return this.nullableGoType(t, true); + } + + return this.goType(t, true); + } + + private goType(t: Type, withIssues = false): Sourcelike { + return matchType( + t, + (_anyType) => + maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + "interface{}", + ), + (_nullType) => + maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + "interface{}", + ), + (_boolType) => "bool", + (_integerType) => "int64", + (_doubleType) => "float64", + (_stringType) => "string", + (arrayType) => ["[]", this.goType(arrayType.items, withIssues)], + (classType) => this.nameForNamedType(classType), + (mapType) => { + let valueSource: Sourcelike; + const v = mapType.values; + if (v instanceof UnionType && nullableFromUnion(v) === null) { + valueSource = ["*", this.nameForNamedType(v)]; + } else { + valueSource = this.goType(v, withIssues); + } + + return ["map[string]", valueSource]; + }, + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) + return this.nullableGoType(nullable, withIssues); + return this.nameForNamedType(unionType); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return "time.Time"; + } + + return "string"; + }, + ); + } + + private emitTopLevel(t: Type, name: Name): void { + this.startFile(name); + + if ( + this._options.multiFileOutput && + this._options.justTypes === false && + this._options.justTypesAndPackage === false && + this.leadingComments === undefined + ) { + this.emitLineOnce( + "// Code generated from JSON Schema using quicktype. DO NOT EDIT.", + ); + this.emitLineOnce( + "// To parse and unparse this JSON data, add this code to your project and do:", + ); + this.emitLineOnce("//"); + const ref = modifySource(camelCase, name); + this.emitLineOnce( + "// ", + ref, + ", err := ", + defined(this._topLevelUnmarshalNames.get(name)), + "(bytes)", + ); + this.emitLineOnce("// bytes, err = ", ref, ".Marshal()"); + } + + this.emitPackageDefinitons(true); + + const unmarshalName = defined(this._topLevelUnmarshalNames.get(name)); + if (this.namedTypeToNameForTopLevel(t) === undefined) { + this.emitLine("type ", name, " ", this.goType(t)); + } + + if (this._options.justTypes || this._options.justTypesAndPackage) + return; + + this.ensureBlankLine(); + this.emitFunc( + [unmarshalName, "(data []byte) (", name, ", error)"], + () => { + this.emitLine("var r ", name); + this.emitLine("err := json.Unmarshal(data, &r)"); + this.emitLine("return r, err"); + }, + ); + this.ensureBlankLine(); + this.emitFunc(["(r *", name, ") Marshal() ([]byte, error)"], () => { + this.emitLine("return json.Marshal(r)"); + }); + this.endFile(); + } + + private emitClass(c: ClassType, className: Name): void { + this.startFile(className); + const columns: Sourcelike[][] = []; + const usedTypes = new Set(); + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + const description = this.descriptionForClassProperty(c, jsonName); + const docStrings = + description !== undefined && description.length > 0 + ? description.map((d) => "// " + d) + : []; + const goType = this.propertyGoType(p); + const omitEmpty = canOmitEmpty(p, this._options.omitEmpty) + ? ",omitempty" + : []; + + docStrings.forEach((doc) => columns.push([doc])); + const tags = this._options.fieldTags + .split(",") + .map((tag) => `${tag}:"${stringEscape(jsonName)}${omitEmpty}"`) + .join(" "); + columns.push([ + [name, " "], + [goType, " "], + ["`", tags, "`"], + ]); + usedTypes.add(goType.toString()); + }); + + this.emitPackageDefinitons( + false, + usedTypes.has("time.Time") || + usedTypes.has("*,time.Time") || + usedTypes.has("[],time.Time") + ? new Set(["time"]) + : undefined, + ); + this.emitDescription(this.descriptionForType(c)); + this.emitStruct(className, columns); + this.endFile(); + } + + private emitEnum(e: EnumType, enumName: Name): void { + this.startFile(enumName); + this.emitPackageDefinitons(false); + this.emitDescription(this.descriptionForType(e)); + this.emitLine("type ", enumName, " string"); + this.ensureBlankLine(); + this.emitLine("const ("); + const columns: Sourcelike[][] = []; + this.forEachEnumCase(e, "none", (name, jsonName) => { + columns.push([ + [name, " "], + [enumName, ' = "', stringEscape(jsonName), '"'], + ]); + }); + this.indent(() => this.emitTable(columns)); + this.emitLine(")"); + this.endFile(); + } + + private emitUnion(u: UnionType, unionName: Name): void { + this.startFile(unionName); + this.emitPackageDefinitons(false); + const [hasNull, nonNulls] = removeNullFromUnion(u); + const isNullableArg = hasNull !== null ? "true" : "false"; + + const ifMember: ( + kind: TypeKind, + ifNotMember: U, + f: (t: Type, fieldName: Name, goType: Sourcelike) => T, + ) => T | U = (kind, ifNotMember, f) => { + const maybeType = u.findMember(kind); + if (maybeType === undefined) return ifNotMember; + return f( + maybeType, + this.nameForUnionMember(u, maybeType), + this.goType(maybeType), + ); + }; + + const maybeAssignNil = (kind: TypeKind): void => { + ifMember(kind, undefined, (_1, fieldName, _2) => { + this.emitLine("x.", fieldName, " = nil"); + }); + }; + + const makeArgs = ( + primitiveArg: (fieldName: Sourcelike) => Sourcelike, + compoundArg: ( + isClass: boolean, + fieldName: Sourcelike, + ) => Sourcelike, + ): Sourcelike => { + const args: Sourcelike = []; + for (const kind of primitiveValueTypeKinds) { + args.push( + ifMember(kind, "nil", (_1, fieldName, _2) => + primitiveArg(fieldName), + ), + ", ", + ); + } + + for (const kind of compoundTypeKinds) { + args.push( + ifMember(kind, "false, nil", (t, fieldName, _) => + compoundArg(t.kind === "class", fieldName), + ), + ", ", + ); + } + + args.push(isNullableArg); + return args; + }; + + const columns: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (fieldName, t) => { + const goType = this.nullableGoType(t, true); + columns.push([[fieldName, " "], goType]); + }); + this.emitDescription(this.descriptionForType(u)); + this.emitStruct(unionName, columns); + + if (this._options.justTypes || this._options.justTypesAndPackage) + return; + + this.ensureBlankLine(); + this.emitFunc( + ["(x *", unionName, ") UnmarshalJSON(data []byte) error"], + () => { + for (const kind of compoundTypeKinds) { + maybeAssignNil(kind); + } + + ifMember("class", undefined, (_1, _2, goType) => { + this.emitLine("var c ", goType); + }); + const args = makeArgs( + (fn) => ["&x.", fn], + (isClass, fn) => (isClass ? "true, &c" : ["true, &x.", fn]), + ); + this.emitLine( + "object, err := unmarshalUnion(data, ", + args, + ")", + ); + this.emitBlock("if err != nil", () => { + this.emitLine("return err"); + }); + this.emitBlock("if object", () => { + ifMember("class", undefined, (_1, fieldName, _2) => { + this.emitLine("x.", fieldName, " = &c"); + }); + }); + this.emitLine("return nil"); + }, + ); + this.ensureBlankLine(); + this.emitFunc( + ["(x *", unionName, ") MarshalJSON() ([]byte, error)"], + () => { + const args = makeArgs( + (fn) => ["x.", fn], + (_, fn) => ["x.", fn, " != nil, x.", fn], + ); + this.emitLine("return marshalUnion(", args, ")"); + }, + ); + this.endFile(); + } + + private emitSingleFileHeaderComments(): void { + this.emitLineOnce( + "// Code generated from JSON Schema using quicktype. DO NOT EDIT.", + ); + this.emitLineOnce( + "// To parse and unparse this JSON data, add this code to your project and do:", + ); + this.forEachTopLevel("none", (_: Type, name: Name) => { + this.emitLine("//"); + const ref = modifySource(camelCase, name); + this.emitLine( + "// ", + ref, + ", err := ", + defined(this._topLevelUnmarshalNames.get(name)), + "(bytes)", + ); + this.emitLine("// bytes, err = ", ref, ".Marshal()"); + }); + } + + private emitPackageDefinitons( + includeJSONEncodingImport: boolean, + imports: Set = new Set(), + ): void { + if (!this._options.justTypes || this._options.justTypesAndPackage) { + this.ensureBlankLine(); + const packageDeclaration = `package ${this._options.packageName}`; + this.emitLineOnce(packageDeclaration); + this.ensureBlankLine(); + } + + if (!this._options.justTypes && !this._options.justTypesAndPackage) { + if ( + this.haveNamedUnions && + this._options.multiFileOutput === false + ) { + imports.add("bytes"); + imports.add("errors"); + } + + if (includeJSONEncodingImport) { + imports.add("encoding/json"); + } + } + + this.emitImports(imports); + } + + private emitImports(imports: Set): void { + const sortedImports = Array.from(imports).sort((a, b) => + a.localeCompare(b), + ); + + if (sortedImports.length === 0) { + return; + } + + sortedImports.forEach((packageName) => { + this.emitLineOnce(`import "${packageName}"`); + }); + this.ensureBlankLine(); + } + + private emitHelperFunctions(): void { + if (this.haveNamedUnions) { + this.startFile("JSONSchemaSupport"); + const imports = new Set(); + if (this._options.multiFileOutput) { + imports.add("bytes"); + imports.add("errors"); + } + + this.emitPackageDefinitons(true, imports); + this.ensureBlankLine(); + this.emitMultiline(`func unmarshalUnion(data []byte, pi **int64, pf **float64, pb **bool, ps **string, haveArray bool, pa interface{}, haveObject bool, pc interface{}, haveMap bool, pm interface{}, haveEnum bool, pe interface{}, nullable bool) (bool, error) { + if pi != nil { + *pi = nil + } + if pf != nil { + *pf = nil + } + if pb != nil { + *pb = nil + } + if ps != nil { + *ps = nil + } + + dec := json.NewDecoder(bytes.NewReader(data)) + dec.UseNumber() + tok, err := dec.Token() + if err != nil { + return false, err + } + + switch v := tok.(type) { + case json.Number: + if pi != nil { + i, err := v.Int64() + if err == nil { + *pi = &i + return false, nil + } + } + if pf != nil { + f, err := v.Float64() + if err == nil { + *pf = &f + return false, nil + } + return false, errors.New("Unparsable number") + } + return false, errors.New("Union does not contain number") + case float64: + return false, errors.New("Decoder should not return float64") + case bool: + if pb != nil { + *pb = &v + return false, nil + } + return false, errors.New("Union does not contain bool") + case string: + if haveEnum { + return false, json.Unmarshal(data, pe) + } + if ps != nil { + *ps = &v + return false, nil + } + return false, errors.New("Union does not contain string") + case nil: + if nullable { + return false, nil + } + return false, errors.New("Union does not contain null") + case json.Delim: + if v == '{' { + if haveObject { + return true, json.Unmarshal(data, pc) + } + if haveMap { + return false, json.Unmarshal(data, pm) + } + return false, errors.New("Union does not contain object") + } + if v == '[' { + if haveArray { + return false, json.Unmarshal(data, pa) + } + return false, errors.New("Union does not contain array") + } + return false, errors.New("Cannot handle delimiter") + } + return false, errors.New("Cannot unmarshal union") +} + +func marshalUnion(pi *int64, pf *float64, pb *bool, ps *string, haveArray bool, pa interface{}, haveObject bool, pc interface{}, haveMap bool, pm interface{}, haveEnum bool, pe interface{}, nullable bool) ([]byte, error) { + if pi != nil { + return json.Marshal(*pi) + } + if pf != nil { + return json.Marshal(*pf) + } + if pb != nil { + return json.Marshal(*pb) + } + if ps != nil { + return json.Marshal(*ps) + } + if haveArray { + return json.Marshal(pa) + } + if haveObject { + return json.Marshal(pc) + } + if haveMap { + return json.Marshal(pm) + } + if haveEnum { + return json.Marshal(pe) + } + if nullable { + return json.Marshal(nil) + } + return nil, errors.New("Union must not be null") +}`); + this.endFile(); + } + } + + protected emitSourceStructure(): void { + if ( + this._options.multiFileOutput === false && + this._options.justTypes === false && + this._options.justTypesAndPackage === false && + this.leadingComments === undefined + ) { + this.emitSingleFileHeaderComments(); + this.emitPackageDefinitons(false, this.collectAllImports()); + } + + this.forEachTopLevel( + "leading-and-interposing", + (t, name) => this.emitTopLevel(t, name), + (t) => + !( + this._options.justTypes || this._options.justTypesAndPackage + ) || this.namedTypeToNameForTopLevel(t) === undefined, + ); + this.forEachObject( + "leading-and-interposing", + (c: ClassType, className: Name) => this.emitClass(c, className), + ); + this.forEachEnum( + "leading-and-interposing", + (u: EnumType, enumName: Name) => this.emitEnum(u, enumName), + ); + this.forEachUnion( + "leading-and-interposing", + (u: UnionType, unionName: Name) => this.emitUnion(u, unionName), + ); + + if (this._options.justTypes || this._options.justTypesAndPackage) { + return; + } + + this.emitHelperFunctions(); + } + + private collectAllImports(): Set { + let imports = new Set(); + this.forEachObject( + "leading-and-interposing", + (c: ClassType, _className: Name) => { + const classImports = this.collectClassImports(c); + imports = new Set([...imports, ...classImports]); + }, + ); + + this.forEachUnion( + "leading-and-interposing", + (u: UnionType, _unionName: Name) => { + const unionImports = this.collectUnionImports(u); + imports = new Set([...imports, ...unionImports]); + }, + ); + return imports; + } + + private collectClassImports(c: ClassType): Set { + const usedTypes = new Set(); + const mapping: Map = new Map(); + mapping.set("time.Time", "time"); + mapping.set("*,time.Time", "time"); + mapping.set("[],time.Time", "time"); + + this.forEachClassProperty(c, "none", (_name, _jsonName, p) => { + const goType = this.propertyGoType(p); + usedTypes.add(goType.toString()); + }); + + const imports = new Set(); + usedTypes.forEach((k) => { + const typeImport = mapping.get(k); + if (typeImport) { + imports.add(typeImport); + } + }); + + return imports; + } + + private collectUnionImports(u: UnionType): Set { + const usedTypes = new Set(); + const mapping: Map = new Map(); + mapping.set("time.Time", "time"); + mapping.set("*,time.Time", "time"); + + this.forEachUnionMember(u, null, "none", null, (_fieldName, t) => { + const goType = this.nullableGoType(t, true); + usedTypes.add(goType.toString()); + }); + + const imports = new Set(); + for (const k of usedTypes) { + const typeImport = mapping.get(k); + if (!typeImport) { + continue; + } + + imports.add(typeImport); + } + + return imports; + } +} diff --git a/packages/quicktype-core/src/language/Golang/index.ts b/packages/quicktype-core/src/language/Golang/index.ts new file mode 100644 index 000000000..04d294d43 --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/index.ts @@ -0,0 +1,2 @@ +export { GoTargetLanguage, goOptions } from "./language"; +export { GoRenderer } from "./GolangRenderer"; diff --git a/packages/quicktype-core/src/language/Golang/language.ts b/packages/quicktype-core/src/language/Golang/language.ts new file mode 100644 index 000000000..8c3a07409 --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/language.ts @@ -0,0 +1,94 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { GoRenderer } from "./GolangRenderer"; + +export const goOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + justTypesAndPackage: new BooleanOption( + "just-types-and-package", + "Plain types with package only", + false, + ), + packageName: new StringOption( + "package", + "Generated package name", + "NAME", + "main", + ), + multiFileOutput: new BooleanOption( + "multi-file-output", + "Renders each top-level object in its own Go file", + false, + ), + fieldTags: new StringOption( + "field-tags", + "list of tags which should be generated for fields", + "TAGS", + "json", + ), + omitEmpty: new BooleanOption( + "omit-empty", + 'If set, all non-required objects will be tagged with ",omitempty"', + false, + ), +}; + +const golangLanguageConfig = { + displayName: "Go", + names: ["go", "golang"], + extension: "go", +} as const; + +export class GoTargetLanguage extends TargetLanguage< + typeof golangLanguageConfig +> { + public constructor() { + super(golangLanguageConfig); + } + + public getOptions(): typeof goOptions { + return goOptions; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + mapping.set("date-time", "date-time"); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): GoRenderer { + return new GoRenderer( + this, + renderContext, + getOptionValues(goOptions, untypedOptionValues), + ); + } + + protected get defaultIndentation(): string { + return "\t"; + } +} diff --git a/packages/quicktype-core/src/language/Golang/utils.ts b/packages/quicktype-core/src/language/Golang/utils.ts new file mode 100644 index 000000000..b53ecd011 --- /dev/null +++ b/packages/quicktype-core/src/language/Golang/utils.ts @@ -0,0 +1,57 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords, +} from "../../support/Strings"; +import type { ClassProperty, Type, TypeKind } from "../../Type"; + +export const namingFunction = funPrefixNamer("namer", goNameStyle); + +const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); + +function goNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isLetterOrUnderscore, + ); +} + +export const primitiveValueTypeKinds: TypeKind[] = [ + "integer", + "double", + "bool", + "string", +]; +export const compoundTypeKinds: TypeKind[] = ["array", "class", "map", "enum"]; + +export function isValueType(t: Type): boolean { + const kind = t.kind; + return ( + primitiveValueTypeKinds.includes(kind) || + kind === "class" || + kind === "enum" || + kind === "date-time" + ); +} + +export function canOmitEmpty( + cp: ClassProperty, + omitEmptyOption: boolean, +): boolean { + if (!cp.isOptional) return false; + if (omitEmptyOption) return true; + const t = cp.type; + return !["union", "null", "any"].includes(t.kind); +} diff --git a/packages/quicktype-core/src/language/Haskell.ts b/packages/quicktype-core/src/language/Haskell/HaskellRenderer.ts similarity index 59% rename from packages/quicktype-core/src/language/Haskell.ts rename to packages/quicktype-core/src/language/Haskell/HaskellRenderer.ts index e597e685d..7ad2e7586 100644 --- a/packages/quicktype-core/src/language/Haskell.ts +++ b/packages/quicktype-core/src/language/Haskell/HaskellRenderer.ts @@ -1,143 +1,44 @@ import { mapContains } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { EnumOption, StringOption, BooleanOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { Type, ClassType, UnionType, EnumType, ClassProperty } from "../Type"; -import { matchType, nullableFromUnion } from "../TypeUtils"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Namer, Name, funPrefixNamer } from "../Naming"; -import { - legalizeCharacters, - isLetterOrUnderscoreOrDigit, - isLetterOrUnderscore, - stringEscape, - isAscii, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle -} from "../support/Strings"; -import { Sourcelike, MultiWord, singleWord, multiWord, parenIfNeeded } from "../Source"; -import { RenderContext } from "../Renderer"; - -export const haskellOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - useList: new EnumOption("array-type", "Use Array or List", [ - ["array", false], - ["list", true] - ]), - moduleName: new StringOption("module", "Generated module name", "NAME", "QuickType") -}; - -export class HaskellTargetLanguage extends TargetLanguage { - constructor() { - super("Haskell", ["haskell"], "haskell"); - } - - protected getOptions(): Option[] { - return [haskellOptions.justTypes, haskellOptions.moduleName, haskellOptions.useList]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): HaskellRenderer { - return new HaskellRenderer(this, renderContext, getOptionValues(haskellOptions, untypedOptionValues)); - } -} - -const forbiddenNames = [ - // reserved keywords - "as", - "case", - "class", - "data", - "default", - "deriving", - "do", - "else", - "family", - "forall", - "foreign", - "hiding", - "if", - "import", - "in", - "infix", - "infixl", - "infixr", - "instance", - "let", - "of", - "mdo", - "module", - "newtype", - "proc", - "qualified", - "rec", - "then", - "type", - "where", - // in Prelude keywords ... - "id", - "Array", - "HashMap", - "Map", - "Maybe", - "Bool", - "Int", - "True", - "False", - "Enum", - // Aeson types - "encode", - "decode", - "text", - "Text", - "Value", - "Object", - "Result", - "Series", - "Error" -]; - -const legalizeName = legalizeCharacters(cp => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp)); - -function haskellNameStyle(original: string, upper: boolean): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - upper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isLetterOrUnderscore - ); -} -const upperNamingFunction = funPrefixNamer("upper", n => haskellNameStyle(n, true)); -const lowerNamingFunction = funPrefixNamer("lower", n => haskellNameStyle(n, false)); +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import type { Name, Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { + type MultiWord, + type Sourcelike, + multiWord, + parenIfNeeded, + singleWord, +} from "../../Source"; +import { stringEscape } from "../../support/Strings"; +import type { TargetLanguage } from "../../TargetLanguage"; +import type { + ClassProperty, + ClassType, + EnumType, + Type, + UnionType, +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../Type/TypeUtils"; + +import { forbiddenNames } from "./constants"; +import type { haskellOptions } from "./language"; +import { lowerNamingFunction, upperNamingFunction } from "./utils"; export class HaskellRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _options: OptionValues + private readonly _options: OptionValues, ) { super(targetLanguage, renderContext); } - protected forbiddenNamesForGlobalNamespace(): string[] { + protected forbiddenNamesForGlobalNamespace(): readonly string[] { return forbiddenNames; } @@ -149,7 +50,10 @@ export class HaskellRenderer extends ConvenienceRenderer { return lowerNamingFunction; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } @@ -173,9 +77,14 @@ export class HaskellRenderer extends ConvenienceRenderer { u: UnionType, unionName: Name, fieldType: Type, - lookup: (n: Name) => string + lookup: (n: Name) => string, ): string { - const fieldName = super.proposeUnionMemberName(u, unionName, fieldType, lookup); + const fieldName = super.proposeUnionMemberName( + u, + unionName, + fieldType, + lookup, + ); return `${fieldName}_in_${lookup(unionName)}`; } @@ -185,64 +94,90 @@ export class HaskellRenderer extends ConvenienceRenderer { protected emitDescriptionBlock(lines: Sourcelike[]): void { if (lines.length === 1) { - this.emitLine("{-| ", lines[0], " -}"); + this.emitComments([ + { customLines: lines, lineStart: "{-| ", lineEnd: " -}" }, + ]); } else { - this.emitCommentLines(lines, "", undefined, "-}", "{-| "); + this.emitCommentLines(lines, { + firstLineStart: "{-| ", + lineStart: "", + afterComment: "-}", + }); } } private haskellType(t: Type, noOptional = false): MultiWord { return matchType( t, - _anyType => multiWord(" ", "Maybe", "Text"), - _nullType => multiWord(" ", "Maybe", "Text"), - _boolType => singleWord("Bool"), - _integerType => singleWord("Int"), - _doubleType => singleWord("Float"), - _stringType => singleWord("Text"), - arrayType => { + (_anyType) => multiWord(" ", "Maybe", "Text"), + (_nullType) => multiWord(" ", "Maybe", "Text"), + (_boolType) => singleWord("Bool"), + (_integerType) => singleWord("Int"), + (_doubleType) => singleWord("Float"), + (_stringType) => singleWord("Text"), + (arrayType) => { if (this._options.useList) { - return multiWord("", "[", parenIfNeeded(this.haskellType(arrayType.items)), "]"); + return multiWord( + "", + "[", + parenIfNeeded(this.haskellType(arrayType.items)), + "]", + ); } - return multiWord(" ", "Vector", parenIfNeeded(this.haskellType(arrayType.items))); + + return multiWord( + " ", + "Vector", + parenIfNeeded(this.haskellType(arrayType.items)), + ); }, - classType => singleWord(this.nameForNamedType(classType)), - mapType => multiWord(" ", "HashMap Text", parenIfNeeded(this.haskellType(mapType.values))), - enumType => singleWord(this.nameForNamedType(enumType)), - unionType => { + (classType) => singleWord(this.nameForNamedType(classType)), + (mapType) => + multiWord( + " ", + "HashMap Text", + parenIfNeeded(this.haskellType(mapType.values)), + ), + (enumType) => singleWord(this.nameForNamedType(enumType)), + (unionType) => { const nullable = nullableFromUnion(unionType); if (nullable !== null) { const nullableType = this.haskellType(nullable); if (noOptional) return nullableType; return multiWord(" ", "Maybe", parenIfNeeded(nullableType)); } + return singleWord(this.nameForNamedType(unionType)); - } + }, ); } private haskellProperty(p: ClassProperty): Sourcelike { if (p.isOptional) { - return multiWord(" ", "Maybe", parenIfNeeded(this.haskellType(p.type, true))).source; - } else { - return this.haskellType(p.type).source; + return multiWord( + " ", + "Maybe", + parenIfNeeded(this.haskellType(p.type, true)), + ).source; } + + return this.haskellType(p.type).source; } private encoderNameForType(t: Type): MultiWord { return matchType( t, - _anyType => singleWord("String"), - _nullType => singleWord("Null"), - _boolType => singleWord("Bool"), - _integerType => singleWord("Number"), - _doubleType => singleWord("Number"), - _stringType => singleWord("String"), - _arrayType => singleWord("Array"), - _classType => singleWord("Object"), - _mapType => singleWord("Object"), - _enumType => singleWord("Object"), - _unionType => singleWord("Object") + (_anyType) => singleWord("String"), + (_nullType) => singleWord("Null"), + (_boolType) => singleWord("Bool"), + (_integerType) => singleWord("Number"), + (_doubleType) => singleWord("Number"), + (_stringType) => singleWord("String"), + (_arrayType) => singleWord("Array"), + (_classType) => singleWord("Object"), + (_mapType) => singleWord("Object"), + (_enumType) => singleWord("Object"), + (_unionType) => singleWord("Object"), ); } @@ -253,7 +188,10 @@ export class HaskellRenderer extends ConvenienceRenderer { private emitClassDefinition(c: ClassType, className: Name): void { let description = this.descriptionForType(c); this.forEachClassProperty(c, "none", (name, jsonName) => { - const propertyDescription = this.descriptionForClassProperty(c, jsonName); + const propertyDescription = this.descriptionForClassProperty( + c, + jsonName, + ); if (propertyDescription === undefined) return; if (description === undefined) { @@ -261,6 +199,7 @@ export class HaskellRenderer extends ConvenienceRenderer { } else { description.push(""); } + description.push(`${this.sourcelikeToString(name)}:`); description.push(...propertyDescription); }); @@ -270,12 +209,19 @@ export class HaskellRenderer extends ConvenienceRenderer { this.indent(() => { let onFirst = true; this.forEachClassProperty(c, "none", (name, _jsonName, p) => { - this.emitLine(onFirst ? "{ " : ", ", name, className, " :: ", this.haskellProperty(p)); + this.emitLine( + onFirst ? "{ " : ", ", + name, + className, + " :: ", + this.haskellProperty(p), + ); onFirst = false; }); if (onFirst) { this.emitLine("{"); } + this.emitLine("} deriving (Show)"); }); } @@ -285,7 +231,7 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("data ", enumName); this.indent(() => { let onFirst = true; - this.forEachEnumCase(e, "none", name => { + this.forEachEnumCase(e, "none", (name) => { const equalsOrPipe = onFirst ? "=" : "|"; this.emitLine(equalsOrPipe, " ", name, enumName); onFirst = false; @@ -299,13 +245,20 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("data ", unionName); this.indent(() => { let onFirst = true; - this.forEachUnionMember(u, null, "none", null, (constructor, t) => { + this.forEachUnionMember(u, null, "none", null, (name, t) => { const equalsOrPipe = onFirst ? "=" : "|"; if (t.kind === "null") { - this.emitLine(equalsOrPipe, " ", constructor); + this.emitLine(equalsOrPipe, " ", name); } else { - this.emitLine(equalsOrPipe, " ", constructor, " ", parenIfNeeded(this.haskellType(t))); + this.emitLine( + equalsOrPipe, + " ", + name, + " ", + parenIfNeeded(this.haskellType(t)), + ); } + onFirst = false; }); this.emitLine("deriving (Show)"); @@ -326,8 +279,8 @@ export class HaskellRenderer extends ConvenienceRenderer { } private emitClassEncoderInstance(c: ClassType, className: Name): void { - let classProperties: Array = []; - this.forEachClassProperty(c, "none", name => { + const classProperties: Array = []; + this.forEachClassProperty(c, "none", (name) => { classProperties.push(" "); classProperties.push(name); classProperties.push(className); @@ -343,12 +296,20 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("object"); let onFirst = true; this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(onFirst ? "[ " : ", ", '"', stringEscape(jsonName), '" .= ', name, className); + this.emitLine( + onFirst ? "[ " : ", ", + '"', + stringEscape(jsonName), + '" .= ', + name, + className, + ); onFirst = false; }); if (onFirst) { this.emitLine("["); } + this.emitLine("]"); }); } @@ -367,7 +328,14 @@ export class HaskellRenderer extends ConvenienceRenderer { let onFirst = true; this.forEachClassProperty(c, "none", (_, jsonName, p) => { const operator = p.isOptional ? ".:?" : ".:"; - this.emitLine(onFirst ? "<$> " : "<*> ", "v ", operator, ' "', stringEscape(jsonName), '"'); + this.emitLine( + onFirst ? "<$> " : "<*> ", + "v ", + operator, + ' "', + stringEscape(jsonName), + '"', + ); onFirst = false; }); }); @@ -385,7 +353,14 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("instance ToJSON ", enumName, " where"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("toJSON ", name, enumName, ' = "', stringEscape(jsonName), '"'); + this.emitLine( + "toJSON ", + name, + enumName, + ' = "', + stringEscape(jsonName), + '"', + ); }); }); } @@ -398,7 +373,13 @@ export class HaskellRenderer extends ConvenienceRenderer { this.emitLine("where"); this.indent(() => { this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine('parseText "', stringEscape(jsonName), '" = return ', name, enumName); + this.emitLine( + 'parseText "', + stringEscape(jsonName), + '" = return ', + name, + enumName, + ); }); }); }); @@ -414,11 +395,11 @@ export class HaskellRenderer extends ConvenienceRenderer { private emitUnionEncoderInstance(u: UnionType, unionName: Name): void { this.emitLine("instance ToJSON ", unionName, " where"); this.indent(() => { - this.forEachUnionMember(u, null, "none", null, (constructor, t) => { + this.forEachUnionMember(u, null, "none", null, (name, t) => { if (t.kind === "null") { - this.emitLine("toJSON ", constructor, " = Null"); + this.emitLine("toJSON ", name, " = Null"); } else { - this.emitLine("toJSON (", constructor, " x) = toJSON x"); + this.emitLine("toJSON (", name, " x) = toJSON x"); } }); }); @@ -427,16 +408,16 @@ export class HaskellRenderer extends ConvenienceRenderer { private emitUnionDecoderInstance(u: UnionType, unionName: Name): void { this.emitLine("instance FromJSON ", unionName, " where"); this.indent(() => { - this.forEachUnionMember(u, null, "none", null, (constructor, t) => { + this.forEachUnionMember(u, null, "none", null, (name, t) => { if (t.kind === "null") { - this.emitLine("parseJSON Null = return ", constructor); + this.emitLine("parseJSON Null = return ", name); } else { this.emitLine( "parseJSON xs@(", this.encoderNameForType(t).source, " _) = (fmap ", - constructor, - " . parseJSON) xs" + name, + " . parseJSON) xs", ); } }); @@ -478,6 +459,7 @@ export class HaskellRenderer extends ConvenienceRenderer { for (let i = 0; i < exports.length; i++) { this.emitLine(i === 0 ? "(" : ",", " ", exports[i]); } + this.emitLine(", decodeTopLevel"); this.emitLine(") where"); }); @@ -496,26 +478,35 @@ import Data.Text (Text)`); this.forEachTopLevel( "leading-and-interposing", - (t: Type, topLevelName: Name) => this.emitTopLevelDefinition(t, topLevelName), - t => this.namedTypeToNameForTopLevel(t) === undefined + (t: Type, topLevelName: Name) => + this.emitTopLevelDefinition(t, topLevelName), + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); this.forEachNamedType( "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassDefinition(c, className), - (e: EnumType, enumName: Name) => this.emitEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionDefinition(u, unionName) + (c: ClassType, className: Name) => + this.emitClassDefinition(c, className), + (e: EnumType, enumName: Name) => + this.emitEnumDefinition(e, enumName), + (u: UnionType, unionName: Name) => + this.emitUnionDefinition(u, unionName), ); - this.forEachTopLevel("leading-and-interposing", (_: Type, topLevelName: Name) => - this.emitTopLevelFunctions(topLevelName) + this.forEachTopLevel( + "leading-and-interposing", + (_: Type, topLevelName: Name) => + this.emitTopLevelFunctions(topLevelName), ); this.forEachNamedType( "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassFunctions(c, className), - (e: EnumType, enumName: Name) => this.emitEnumFunctions(e, enumName), - (u: UnionType, unionName: Name) => this.emitUnionFunctions(u, unionName) + (c: ClassType, className: Name) => + this.emitClassFunctions(c, className), + (e: EnumType, enumName: Name) => + this.emitEnumFunctions(e, enumName), + (u: UnionType, unionName: Name) => + this.emitUnionFunctions(u, unionName), ); if (this._options.justTypes) return; diff --git a/packages/quicktype-core/src/language/Haskell/constants.ts b/packages/quicktype-core/src/language/Haskell/constants.ts new file mode 100644 index 000000000..e4eee6e53 --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/constants.ts @@ -0,0 +1,54 @@ +export const forbiddenNames = [ + // reserved keywords + "as", + "case", + "class", + "data", + "default", + "deriving", + "do", + "else", + "family", + "forall", + "foreign", + "hiding", + "if", + "import", + "in", + "infix", + "infixl", + "infixr", + "instance", + "let", + "of", + "mdo", + "module", + "newtype", + "proc", + "qualified", + "rec", + "then", + "type", + "where", + // in Prelude keywords ... + "id", + "Array", + "HashMap", + "Map", + "Maybe", + "Bool", + "Int", + "True", + "False", + "Enum", + // Aeson types + "encode", + "decode", + "text", + "Text", + "Value", + "Object", + "Result", + "Series", + "Error", +] as const; diff --git a/packages/quicktype-core/src/language/Haskell/index.ts b/packages/quicktype-core/src/language/Haskell/index.ts new file mode 100644 index 000000000..9658076f0 --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/index.ts @@ -0,0 +1,2 @@ +export { HaskellTargetLanguage, haskellOptions } from "./language"; +export { HaskellRenderer } from "./HaskellRenderer"; diff --git a/packages/quicktype-core/src/language/Haskell/language.ts b/packages/quicktype-core/src/language/Haskell/language.ts new file mode 100644 index 000000000..58638b03b --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/language.ts @@ -0,0 +1,67 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { HaskellRenderer } from "./HaskellRenderer"; + +export const haskellOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + useList: new EnumOption( + "array-type", + "Use Array or List", + { + array: false, + list: true, + } as const, + "array", + ), + moduleName: new StringOption( + "module", + "Generated module name", + "NAME", + "QuickType", + ), +}; + +export const haskellLanguageConfig = { + displayName: "Haskell", + names: ["haskell"], + extension: "haskell", +} as const; + +export class HaskellTargetLanguage extends TargetLanguage< + typeof haskellLanguageConfig +> { + public constructor() { + super(haskellLanguageConfig); + } + + public getOptions(): typeof haskellOptions { + return haskellOptions; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): HaskellRenderer { + return new HaskellRenderer( + this, + renderContext, + getOptionValues(haskellOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/Haskell/utils.ts b/packages/quicktype-core/src/language/Haskell/utils.ts new file mode 100644 index 000000000..d71067574 --- /dev/null +++ b/packages/quicktype-core/src/language/Haskell/utils.ts @@ -0,0 +1,37 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + splitIntoWords, +} from "../../support/Strings"; + +const legalizeName = legalizeCharacters( + (cp) => isAscii(cp) && isLetterOrUnderscoreOrDigit(cp), +); + +function haskellNameStyle(original: string, upper: boolean): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + upper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isLetterOrUnderscore, + ); +} + +export const upperNamingFunction = funPrefixNamer("upper", (n) => + haskellNameStyle(n, true), +); +export const lowerNamingFunction = funPrefixNamer("lower", (n) => + haskellNameStyle(n, false), +); diff --git a/packages/quicktype-core/src/language/JSONSchema.ts b/packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts similarity index 53% rename from packages/quicktype-core/src/language/JSONSchema.ts rename to packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts index 2b8a447ba..2f2aca5d0 100644 --- a/packages/quicktype-core/src/language/JSONSchema.ts +++ b/packages/quicktype-core/src/language/JSONSchema/JSONSchemaRenderer.ts @@ -1,72 +1,25 @@ -import { mapFirst, iterableFirst } from "collection-utils"; +import { iterableFirst, mapFirst } from "collection-utils"; -import { TargetLanguage } from "../TargetLanguage"; -import { Type, UnionType, EnumType, ObjectType, transformedStringTypeTargetTypeKindsMap } from "../Type"; -import { matchTypeExhaustive } from "../TypeUtils"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { Namer, funPrefixNamer, Name } from "../Naming"; +import { addDescriptionToSchema } from "../../attributes/Description"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import type { Name, Namer } from "../../Naming"; +import { defined, panic } from "../../support/Support"; import { - legalizeCharacters, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle -} from "../support/Strings"; -import { defined, panic } from "../support/Support"; -import { StringTypeMapping, getNoStringTypeMapping } from "../TypeBuilder"; -import { addDescriptionToSchema } from "../attributes/Description"; -import { Option } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; - -export class JSONSchemaTargetLanguage extends TargetLanguage { - constructor() { - super("JSON Schema", ["schema", "json-schema"], "schema"); - } - - protected getOptions(): Option[] { - return []; - } - - get stringTypeMapping(): StringTypeMapping { - return getNoStringTypeMapping(); - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsFullObjectType(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - _untypedOptionValues: { [name: string]: any } - ): JSONSchemaRenderer { - return new JSONSchemaRenderer(this, renderContext); - } + type EnumType, + type ObjectType, + type Type, + type UnionType, + transformedStringTypeTargetTypeKindsMap, +} from "../../Type"; +import { matchTypeExhaustive } from "../../Type/TypeUtils"; + +import { namingFunction } from "./utils"; + +interface Schema { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [name: string]: any; } -const namingFunction = funPrefixNamer("namer", jsonNameStyle); - -const legalizeName = legalizeCharacters(cp => cp >= 32 && cp < 128 && cp !== 0x2f /* slash */); - -function jsonNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - _ => true - ); -} - -type Schema = { [name: string]: any }; - export class JSONSchemaRenderer extends ConvenienceRenderer { protected makeNamedTypeNamer(): Namer { return namingFunction; @@ -93,10 +46,14 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { if (first === undefined) { return panic("Must have at least one type for oneOf"); } + if (types.size === 1) { return this.schemaForType(first); } - return { anyOf: Array.from(types).map((t: Type) => this.schemaForType(t)) }; + + return { + anyOf: Array.from(types).map((t: Type) => this.schemaForType(t)), + }; } private makeRef(t: Type): Schema { @@ -111,44 +68,56 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { } private schemaForType(t: Type): Schema { - const schema = matchTypeExhaustive<{ [name: string]: any }>( + const schema = matchTypeExhaustive( t, - _noneType => { + (_noneType) => { return panic("none type should have been replaced"); }, - _anyType => ({}), - _nullType => ({ type: "null" }), - _boolType => ({ type: "boolean" }), - _integerType => ({ type: "integer" }), - _doubleType => ({ type: "number" }), - _stringType => ({ type: "string" }), - arrayType => ({ type: "array", items: this.schemaForType(arrayType.items) }), - classType => this.makeRef(classType), - mapType => this.definitionForObject(mapType, undefined), - objectType => this.makeRef(objectType), - enumType => this.makeRef(enumType), - unionType => { + (_anyType) => ({}), + (_nullType) => ({ type: "null" }), + (_boolType) => ({ type: "boolean" }), + (_integerType) => ({ type: "integer" }), + (_doubleType) => ({ type: "number" }), + (_stringType) => ({ type: "string" }), + (arrayType) => ({ + type: "array", + items: this.schemaForType(arrayType.items), + }), + (classType) => this.makeRef(classType), + (mapType) => this.definitionForObject(mapType, undefined), + (objectType) => this.makeRef(objectType), + (enumType) => this.makeRef(enumType), + (unionType) => { if (this.unionNeedsName(unionType)) { return this.makeRef(unionType); - } else { - return this.definitionForUnion(unionType); } + + return this.definitionForUnion(unionType); }, - transformedStringType => { - const target = transformedStringTypeTargetTypeKindsMap.get(transformedStringType.kind); + (transformedStringType) => { + const target = transformedStringTypeTargetTypeKindsMap.get( + transformedStringType.kind, + ); if (target === undefined) { - return panic(`Unknown transformed string type ${transformedStringType.kind}`); + return panic( + `Unknown transformed string type ${transformedStringType.kind}`, + ); } + return { type: "string", format: target.jsonSchema }; - } + }, ); if (schema.$ref === undefined) { this.addAttributesToSchema(t, schema); } + return schema; } - private definitionForObject(o: ObjectType, title: string | undefined): Schema { + private definitionForObject( + o: ObjectType, + title: string | undefined, + ): Schema { let properties: Schema | undefined; let required: string[] | undefined; if (o.getProperties().size === 0) { @@ -160,24 +129,31 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { for (const [name, p] of o.getProperties()) { const prop = this.schemaForType(p.type); if (prop.description === undefined) { - addDescriptionToSchema(prop, this.descriptionForClassProperty(o, name)); + addDescriptionToSchema( + prop, + this.descriptionForClassProperty(o, name), + ); } + props[name] = prop; if (!p.isOptional) { req.push(name); } } + properties = props; required = req.sort(); } + const additional = o.getAdditionalProperties(); - const additionalProperties = additional !== undefined ? this.schemaForType(additional) : false; + const additionalProperties = + additional !== undefined ? this.schemaForType(additional) : false; const schema = { type: "object", additionalProperties, properties, required, - title + title, }; this.addAttributesToSchema(o, schema); return schema; @@ -188,6 +164,7 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { if (title !== undefined) { oneOf.title = title; } + this.addAttributesToSchema(u, oneOf); return oneOf; } @@ -200,8 +177,14 @@ export class JSONSchemaRenderer extends ConvenienceRenderer { protected emitSourceStructure(): void { // FIXME: Find a good way to do multiple top-levels. Maybe multiple files? - const topLevelType = this.topLevels.size === 1 ? this.schemaForType(defined(mapFirst(this.topLevels))) : {}; - const schema = Object.assign({ $schema: "http://json-schema.org/draft-06/schema#" }, topLevelType); + const topLevelType = + this.topLevels.size === 1 + ? this.schemaForType(defined(mapFirst(this.topLevels))) + : {}; + const schema = Object.assign( + { $schema: "http://json-schema.org/draft-06/schema#" }, + topLevelType, + ); const definitions: { [name: string]: Schema } = {}; this.forEachObject("none", (o: ObjectType, name: Name) => { const title = defined(this.names.get(name)); diff --git a/packages/quicktype-core/src/language/JSONSchema/index.ts b/packages/quicktype-core/src/language/JSONSchema/index.ts new file mode 100644 index 000000000..6cb0b7958 --- /dev/null +++ b/packages/quicktype-core/src/language/JSONSchema/index.ts @@ -0,0 +1,2 @@ +export { JSONSchemaTargetLanguage } from "./language"; +export { JSONSchemaRenderer } from "./JSONSchemaRenderer"; diff --git a/packages/quicktype-core/src/language/JSONSchema/language.ts b/packages/quicktype-core/src/language/JSONSchema/language.ts new file mode 100644 index 000000000..6a371de56 --- /dev/null +++ b/packages/quicktype-core/src/language/JSONSchema/language.ts @@ -0,0 +1,46 @@ +import type { RenderContext } from "../../Renderer"; +import { TargetLanguage } from "../../TargetLanguage"; +import { + type StringTypeMapping, + getNoStringTypeMapping, +} from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { JSONSchemaRenderer } from "./JSONSchemaRenderer"; + +export const JSONSchemaLanguageConfig = { + displayName: "JSON Schema", + names: ["schema", "json-schema"], + extension: "schema", +} as const; + +export class JSONSchemaTargetLanguage extends TargetLanguage< + typeof JSONSchemaLanguageConfig +> { + public constructor() { + super(JSONSchemaLanguageConfig); + } + + public getOptions(): {} { + return {}; + } + + public get stringTypeMapping(): StringTypeMapping { + return getNoStringTypeMapping(); + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsFullObjectType(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + _untypedOptionValues: RendererOptions, + ): JSONSchemaRenderer { + return new JSONSchemaRenderer(this, renderContext); + } +} diff --git a/packages/quicktype-core/src/language/JSONSchema/utils.ts b/packages/quicktype-core/src/language/JSONSchema/utils.ts new file mode 100644 index 000000000..32f65b51d --- /dev/null +++ b/packages/quicktype-core/src/language/JSONSchema/utils.ts @@ -0,0 +1,28 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + legalizeCharacters, + splitIntoWords, +} from "../../support/Strings"; + +export const namingFunction = funPrefixNamer("namer", jsonNameStyle); + +const legalizeName = legalizeCharacters( + (cp) => cp >= 32 && cp < 128 && cp !== 0x2f /* slash */, +); + +function jsonNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + (_) => true, + ); +} diff --git a/packages/quicktype-core/src/language/Java.ts b/packages/quicktype-core/src/language/Java.ts deleted file mode 100644 index 5289794fd..000000000 --- a/packages/quicktype-core/src/language/Java.ts +++ /dev/null @@ -1,1445 +0,0 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, EnumOption, getOptionValues, Option, OptionValues, StringOption } from "../RendererOptions"; -import { maybeAnnotated, Sourcelike } from "../Source"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { - allLowerWordStyle, - allUpperWordStyle, - capitalize, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - isAscii, - isDigit, - isLetter, - splitIntoWords, - standardUnicodeHexEscape, - utf16ConcatMap, - utf16LegalizeCharacters -} from "../support/Strings"; -import { assert, assertNever, defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { ArrayType, ClassProperty, ClassType, EnumType, MapType, Type, TypeKind, UnionType } from "../Type"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; - -export const javaOptions = { - useList: new EnumOption( - "array-type", - "Use T[] or List", - [ - ["array", false], - ["list", true] - ], - "array" - ), - justTypes: new BooleanOption("just-types", "Plain types only", false), - dateTimeProvider: new EnumOption( - "datetime-provider", - "Date time provider type", - [ - ["java8", "java8"], - ["legacy", "legacy"] - ], - "java8" - ), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - // FIXME: Do this via a configurable named eventually. - packageName: new StringOption("package", "Generated package name", "NAME", "io.quicktype"), - lombok: new BooleanOption("lombok", "Use lombok", false, "primary"), - lombokCopyAnnotations: new BooleanOption("lombok-copy-annotations", "Copy accessor annotations", true, "secondary") -}; - -export class JavaTargetLanguage extends TargetLanguage { - constructor() { - super("Java", ["java"], "java"); - } - - protected getOptions(): Option[] { - return [ - javaOptions.useList, - javaOptions.justTypes, - javaOptions.dateTimeProvider, - javaOptions.acronymStyle, - javaOptions.packageName, - javaOptions.lombok, - javaOptions.lombokCopyAnnotations - ]; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): JavaRenderer { - const options = getOptionValues(javaOptions, untypedOptionValues); - if (options.justTypes) { - return new JavaRenderer(this, renderContext, options); - } - return new JacksonRenderer(this, renderContext, options); - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date"); - mapping.set("time", "time"); - mapping.set("date-time", "date-time"); - mapping.set("uuid", "uuid"); - return mapping; - } -} - -const javaKeywords = [ - "_", // as of release 9, '_' is a keyword, and may not be used as an identifier - "Object", - "Class", - "System", - "Long", - "Double", - "Boolean", - "String", - "List", - "Map", - "UUID", - "Exception", - "IOException", - "Override", - "abstract", - "continue", - "for", - "new", - "switch", - "assert", - "default", - "goto", - "package", - "synchronized", - "boolean", - "do", - "if", - "private", - "this", - "break", - "double", - "implements", - "protected", - "throw", - "byte", - "else", - "import", - "public", - "throws", - "case", - "enum", - "instanceof", - "return", - "transient", - "catch", - "extends", - "int", - "short", - "try", - "char", - "final", - "interface", - "static", - "void", - "class", - "finally", - "long", - "strictfp", - "volatile", - "const", - "float", - "native", - "super", - "while", - "null", - "false", - "true" -]; - -export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); - -function isStartCharacter(codePoint: number): boolean { - if (codePoint === 0x5f) return true; // underscore - return isAscii(codePoint) && isLetter(codePoint); -} - -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -export function javaNameStyle( - startWithUpper: boolean, - upperUnderscore: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upperUnderscore ? allUpperWordStyle : startWithUpper ? firstUpperWordStyle : allLowerWordStyle, - upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, - upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - upperUnderscore ? "_" : "", - isStartCharacter - ); -} - -abstract class JavaDateTimeProvider { - constructor(protected readonly _renderer: JavaRenderer, protected readonly _className: string) {} - abstract keywords: string[]; - - abstract dateTimeImports: string[]; - abstract dateImports: string[]; - abstract timeImports: string[]; - abstract converterImports: string[]; - - abstract dateTimeType: string; - abstract dateType: string; - abstract timeType: string; - - abstract dateTimeJacksonAnnotations: string[]; - abstract dateJacksonAnnotations: string[]; - abstract timeJacksonAnnotations: string[]; - - abstract emitDateTimeConverters(): void; - - public shouldEmitDateTimeConverter = true; - public shouldEmitTimeConverter = true; - public shouldEmitDateConverter = true; - - abstract convertStringToDateTime(variable: Sourcelike): Sourcelike; - abstract convertStringToTime(variable: Sourcelike): Sourcelike; - abstract convertStringToDate(variable: Sourcelike): Sourcelike; - - abstract convertDateTimeToString(variable: Sourcelike): Sourcelike; - abstract convertTimeToString(variable: Sourcelike): Sourcelike; - abstract convertDateToString(variable: Sourcelike): Sourcelike; -} - -class Java8DateTimeProvider extends JavaDateTimeProvider { - keywords = [ - "LocalDate", - "OffsetDateTime", - "OffsetTime", - "ZoneOffset", - "ZonedDateTime", - "DateTimeFormatter", - "DateTimeFormatterBuilder", - "ChronoField" - ]; - - dateTimeImports: string[] = ["java.time.OffsetDateTime"]; - dateImports: string[] = ["java.time.LocalDate"]; - timeImports: string[] = ["java.time.OffsetTime"]; - converterImports: string[] = [ - "java.time.LocalDate", - "java.time.OffsetDateTime", - "java.time.OffsetTime", - "java.time.ZoneOffset", - "java.time.ZonedDateTime", - "java.time.format.DateTimeFormatter", - "java.time.format.DateTimeFormatterBuilder", - "java.time.temporal.ChronoField" - ]; - - dateTimeType = "OffsetDateTime"; - dateType = "LocalDate"; - timeType = "OffsetTime"; - - dateTimeJacksonAnnotations: string[] = []; - dateJacksonAnnotations: string[] = []; - timeJacksonAnnotations: string[] = []; - - emitDateTimeConverters(): void { - this._renderer.ensureBlankLine(); - this._renderer.emitLine( - "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()" - ); - this._renderer.indent(() => - this._renderer.indent(() => { - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_DATE_TIME)"); - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)"); - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_INSTANT)"); - this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))'); - this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))'); - this._renderer.emitLine('.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))'); - this._renderer.emitLine(".toFormatter()"); - this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); - }) - ); - this._renderer.ensureBlankLine(); - this._renderer.emitBlock("public static OffsetDateTime parseDateTimeString(String str)", () => { - this._renderer.emitLine( - "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();" - ); - }); - - this._renderer.ensureBlankLine(); - this._renderer.emitLine( - "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()" - ); - this._renderer.indent(() => - this._renderer.indent(() => { - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_TIME)"); - this._renderer.emitLine(".appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)"); - this._renderer.emitLine(".parseDefaulting(ChronoField.YEAR, 2020)"); - this._renderer.emitLine(".parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)"); - this._renderer.emitLine(".parseDefaulting(ChronoField.DAY_OF_MONTH, 1)"); - this._renderer.emitLine(".toFormatter()"); - this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); - }) - ); - this._renderer.ensureBlankLine(); - this._renderer.emitBlock("public static OffsetTime parseTimeString(String str)", () => { - this._renderer.emitLine( - "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();" - ); - }); - } - - convertStringToDateTime(variable: Sourcelike): Sourcelike { - return [this._className, ".parseDateTimeString(", variable, ")"]; - } - - convertStringToTime(variable: Sourcelike): Sourcelike { - return [this._className, ".parseTimeString(", variable, ")"]; - } - - convertStringToDate(variable: Sourcelike): Sourcelike { - return ["LocalDate.parse(", variable, ")"]; - } - - convertDateTimeToString(variable: Sourcelike): Sourcelike { - return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)"]; - } - - convertTimeToString(variable: Sourcelike): Sourcelike { - return [variable, ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_TIME)"]; - } - - convertDateToString(variable: Sourcelike): Sourcelike { - return [variable, ".format(java.time.format.DateTimeFormatter.ISO_DATE)"]; - } -} - -class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { - keywords = ["SimpleDateFormat", "Date"]; - - dateTimeImports: string[] = ["java.util.Date"]; - dateImports: string[] = ["java.util.Date"]; - timeImports: string[] = ["java.util.Date"]; - converterImports: string[] = ["java.util.Date", "java.text.SimpleDateFormat"]; - - dateTimeType = "Date"; - dateType = "Date"; - timeType = "Date"; - - dateTimeJacksonAnnotations: string[] = ['@JsonFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ssX", timezone = "UTC")']; - dateJacksonAnnotations: string[] = ['@JsonFormat(pattern = "yyyy-MM-dd")']; - timeJacksonAnnotations: string[] = ['@JsonFormat(pattern = "HH:mm:ssX", timezone = "UTC")']; - - emitDateTimeConverters(): void { - this._renderer.ensureBlankLine(); - this._renderer.emitLine("private static final String[] DATE_TIME_FORMATS = {"); - this._renderer.indent(() => - this._renderer.indent(() => { - this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.SX\","); - this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.S\","); - this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ssX\","); - this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss\","); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.SX",'); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.S",'); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ssX",'); - this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss",'); - this._renderer.emitLine('"HH:mm:ss.SZ",'); - this._renderer.emitLine('"HH:mm:ss.S",'); - this._renderer.emitLine('"HH:mm:ssZ",'); - this._renderer.emitLine('"HH:mm:ss",'); - this._renderer.emitLine('"yyyy-MM-dd",'); - }) - ); - this._renderer.emitLine("};"); - this._renderer.ensureBlankLine(); - this._renderer.emitBlock("public static Date parseAllDateTimeString(String str)", () => { - this._renderer.emitBlock("for (String format : DATE_TIME_FORMATS)", () => { - this._renderer.emitIgnoredTryCatchBlock(() => { - this._renderer.emitLine("return new SimpleDateFormat(format).parse(str);"); - }); - }); - this._renderer.emitLine("return null;"); - }); - - this._renderer.ensureBlankLine(); - this._renderer.emitBlock("public static String serializeDateTime(Date datetime)", () => { - this._renderer.emitLine("return new SimpleDateFormat(\"yyyy-MM-dd'T'hh:mm:ssZ\").format(datetime);"); - }); - - this._renderer.ensureBlankLine(); - this._renderer.emitBlock("public static String serializeDate(Date datetime)", () => { - this._renderer.emitLine('return new SimpleDateFormat("yyyy-MM-dd").format(datetime);'); - }); - - this._renderer.ensureBlankLine(); - this._renderer.emitBlock("public static String serializeTime(Date datetime)", () => { - this._renderer.emitLine('return new SimpleDateFormat("hh:mm:ssZ").format(datetime);'); - }); - } - - shouldEmitTimeConverter = false; - shouldEmitDateConverter = false; - - convertStringToDateTime(variable: Sourcelike): Sourcelike { - return [this._className, ".parseAllDateTimeString(", variable, ")"]; - } - - convertStringToTime(variable: Sourcelike): Sourcelike { - return [this._className, ".parseAllDateTimeString(", variable, ")"]; - } - - convertStringToDate(variable: Sourcelike): Sourcelike { - return [this._className, ".parseAllDateTimeString(", variable, ")"]; - } - - convertDateTimeToString(variable: Sourcelike): Sourcelike { - return [this._className, ".serializeDateTime(", variable, ")"]; - } - - convertTimeToString(variable: Sourcelike): Sourcelike { - return [this._className, ".serializeTime(", variable, ")"]; - } - - convertDateToString(variable: Sourcelike): Sourcelike { - return [this._className, ".serializeDate(", variable, ")"]; - } -} - -export class JavaRenderer extends ConvenienceRenderer { - private _currentFilename: string | undefined; - private readonly _gettersAndSettersForPropertyName = new Map(); - private _haveEmittedLeadingComments = false; - protected readonly _dateTimeProvider: JavaDateTimeProvider; - protected readonly _converterClassname: string = "Converter"; - protected readonly _converterKeywords: string[] = []; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - - switch (_options.dateTimeProvider) { - default: - case "java8": - this._dateTimeProvider = new Java8DateTimeProvider(this, this._converterClassname); - break; - case "legacy": - this._dateTimeProvider = new JavaLegacyDateTimeProvider(this, this._converterClassname); - break; - } - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - const keywords = [ - ...javaKeywords, - ...this._converterKeywords, - this._converterClassname, - ...this._dateTimeProvider.keywords - ]; - return keywords; - } - - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return this.getNameStyling("typeNamingFunction"); - } - - protected namerForObjectProperty(): Namer { - return this.getNameStyling("propertyNamingFunction"); - } - - protected makeUnionMemberNamer(): Namer { - return this.getNameStyling("propertyNamingFunction"); - } - - protected makeEnumCaseNamer(): Namer { - return this.getNameStyling("enumCaseNamingFunction"); - } - - protected unionNeedsName(u: UnionType): boolean { - return nullableFromUnion(u) === null; - } - - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { - // If the top-level type doesn't contain any classes or unions - // we have to define a class just for the `FromJson` method, in - // emitFromJsonForTopLevel. - return directlyReachableSingleNamedType(type); - } - - protected makeNamesForPropertyGetterAndSetter( - _c: ClassType, - _className: Name, - _p: ClassProperty, - _jsonName: string, - name: Name - ): [Name, Name] { - const getterName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `get_${lookup(name)}` - ); - const setterName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `set_${lookup(name)}` - ); - return [getterName, setterName]; - } - - protected makePropertyDependencyNames( - c: ClassType, - className: Name, - p: ClassProperty, - jsonName: string, - name: Name - ): Name[] { - const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); - this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); - return getterAndSetterNames; - } - - private getNameStyling(convention: string): Namer { - const styling: { [key: string]: Namer } = { - typeNamingFunction: funPrefixNamer("types", n => - javaNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) - ), - propertyNamingFunction: funPrefixNamer("properties", n => - javaNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) - ), - enumCaseNamingFunction: funPrefixNamer("enum-cases", n => - javaNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) - ) - }; - return styling[convention]; - } - - protected fieldOrMethodName(methodName: string, topLevelName: Name): Sourcelike { - if (this.topLevels.size === 1) { - return methodName; - } - return [topLevelName, capitalize(methodName)]; - } - - protected methodName(prefix: string, suffix: string, topLevelName: Name): Sourcelike { - if (this.topLevels.size === 1) { - return [prefix, suffix]; - } - return [prefix, topLevelName, suffix]; - } - - protected decoderName(topLevelName: Name): Sourcelike { - return this.fieldOrMethodName("fromJsonString", topLevelName); - } - - protected encoderName(topLevelName: Name): Sourcelike { - return this.fieldOrMethodName("toJsonString", topLevelName); - } - - protected readerGetterName(topLevelName: Name): Sourcelike { - return this.methodName("get", "ObjectReader", topLevelName); - } - - protected writerGetterName(topLevelName: Name): Sourcelike { - return this.methodName("get", "ObjectWriter", topLevelName); - } - - protected startFile(basename: Sourcelike): void { - assert(this._currentFilename === undefined, "Previous file wasn't finished"); - // FIXME: The filenames should actually be Sourcelikes, too - this._currentFilename = `${this.sourcelikeToString(basename)}.java`; - // FIXME: Why is this necessary? - this.ensureBlankLine(); - if (!this._haveEmittedLeadingComments && this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - this.ensureBlankLine(); - this._haveEmittedLeadingComments = true; - } - } - - protected finishFile(): void { - super.finishFile(defined(this._currentFilename)); - this._currentFilename = undefined; - } - - protected emitPackageAndImports(imports: string[]): void { - this.emitLine("package ", this._options.packageName, ";"); - this.ensureBlankLine(); - for (const pkg of imports) { - this.emitLine("import ", pkg, ";"); - } - } - - protected emitFileHeader(fileName: Sourcelike, imports: string[]): void { - this.startFile(fileName); - this.emitPackageAndImports(imports); - this.ensureBlankLine(); - } - - public emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); - } - - public emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line, " {"); - this.indent(f); - this.emitLine("}"); - } - - public emitTryCatch(main: () => void, handler: () => void, exception = "Exception") { - this.emitLine("try {"); - this.indent(main); - this.emitLine("} catch (", exception, " ex) {"); - this.indent(handler); - this.emitLine("}"); - } - - public emitIgnoredTryCatchBlock(f: () => void) { - this.emitTryCatch(f, () => this.emitLine("// Ignored")); - } - - protected javaType(reference: boolean, t: Type, withIssues = false): Sourcelike { - return matchType( - t, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Object"), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Object"), - _boolType => (reference ? "Boolean" : "boolean"), - _integerType => (reference ? "Long" : "long"), - _doubleType => (reference ? "Double" : "double"), - _stringType => "String", - arrayType => { - if (this._options.useList) { - return ["List<", this.javaType(true, arrayType.items, withIssues), ">"]; - } else { - return [this.javaType(false, arrayType.items, withIssues), "[]"]; - } - }, - classType => this.nameForNamedType(classType), - mapType => ["Map"], - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return this.javaType(true, nullable, withIssues); - return this.nameForNamedType(unionType); - }, - transformedStringType => { - if (transformedStringType.kind === "time") { - return this._dateTimeProvider.timeType; - } - if (transformedStringType.kind === "date") { - return this._dateTimeProvider.dateType; - } - if (transformedStringType.kind === "date-time") { - return this._dateTimeProvider.dateTimeType; - } - if (transformedStringType.kind === "uuid") { - return "UUID"; - } - return "String"; - } - ); - } - - protected javaImport(t: Type): string[] { - return matchType( - t, - _anyType => [], - _nullType => [], - _boolType => [], - _integerType => [], - _doubleType => [], - _stringType => [], - arrayType => { - if (this._options.useList) { - return [...this.javaImport(arrayType.items), "java.util.List"]; - } else { - return [...this.javaImport(arrayType.items)]; - } - }, - _classType => [], - mapType => [...this.javaImport(mapType.values), "java.util.Map"], - _enumType => [], - unionType => { - const imports: string[] = []; - unionType.members.forEach(type => this.javaImport(type).forEach(imp => imports.push(imp))); - return imports; - }, - transformedStringType => { - if (transformedStringType.kind === "time") { - return this._dateTimeProvider.timeImports; - } - if (transformedStringType.kind === "date") { - return this._dateTimeProvider.dateImports; - } - if (transformedStringType.kind === "date-time") { - return this._dateTimeProvider.dateTimeImports; - } - if (transformedStringType.kind === "uuid") { - return ["java.util.UUID"]; - } - return []; - } - ); - } - - protected javaTypeWithoutGenerics(reference: boolean, t: Type): Sourcelike { - if (t instanceof ArrayType) { - if (this._options.useList) { - return ["List"]; - } else { - return [this.javaTypeWithoutGenerics(false, t.items), "[]"]; - } - } else if (t instanceof MapType) { - return "Map"; - } else if (t instanceof UnionType) { - const nullable = nullableFromUnion(t); - if (nullable !== null) return this.javaTypeWithoutGenerics(true, nullable); - return this.nameForNamedType(t); - } else { - return this.javaType(reference, t); - } - } - - protected emitClassAttributes(_c: ClassType, _className: Name): void { - if (this._options.lombok) { - this.emitLine("@lombok.Data"); - } - } - - protected annotationsForAccessor( - _c: ClassType, - _className: Name, - _propertyName: Name, - _jsonName: string, - _p: ClassProperty, - _isSetter: boolean - ): string[] { - return []; - } - - protected importsForType(t: ClassType | UnionType | EnumType): string[] { - if (t instanceof ClassType) { - return []; - } - if (t instanceof UnionType) { - return ["java.io.IOException"]; - } - if (t instanceof EnumType) { - return ["java.io.IOException"]; - } - return assertNever(t); - } - - protected importsForClass(c: ClassType): string[] { - const imports: string[] = []; - this.forEachClassProperty(c, "none", (_name, _jsonName, p) => { - this.javaImport(p.type).forEach(imp => imports.push(imp)); - }); - imports.sort(); - return [...new Set(imports)]; - } - - protected importsForUnionMembers(u: UnionType): string[] { - const imports: string[] = []; - const [, nonNulls] = removeNullFromUnion(u); - this.forEachUnionMember(u, nonNulls, "none", null, (_fieldName, t) => { - this.javaImport(t).forEach(imp => imports.push(imp)); - }); - imports.sort(); - return [...new Set(imports)]; - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - let imports = [...this.importsForType(c), ...this.importsForClass(c)]; - - this.emitFileHeader(className, imports); - this.emitDescription(this.descriptionForType(c)); - this.emitClassAttributes(c, className); - this.emitBlock(["public class ", className], () => { - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - if (this._options.lombok && this._options.lombokCopyAnnotations) { - const getter = this.annotationsForAccessor(c, className, name, jsonName, p, false); - const setter = this.annotationsForAccessor(c, className, name, jsonName, p, true); - if (getter.length !== 0) { - this.emitLine("@lombok.Getter(onMethod_ = {" + getter.join(", ") + "})"); - } - if (setter.length !== 0) { - this.emitLine("@lombok.Setter(onMethod_ = {" + setter.join(", ") + "})"); - } - } - this.emitLine("private ", this.javaType(false, p.type, true), " ", name, ";"); - }); - if (!this._options.lombok) { - this.forEachClassProperty(c, "leading-and-interposing", (name, jsonName, p) => { - this.emitDescription(this.descriptionForClassProperty(c, jsonName)); - const [getterName, setterName] = defined(this._gettersAndSettersForPropertyName.get(name)); - const rendered = this.javaType(false, p.type); - this.annotationsForAccessor(c, className, name, jsonName, p, false).forEach(annotation => - this.emitLine(annotation) - ); - this.emitLine("public ", rendered, " ", getterName, "() { return ", name, "; }"); - this.annotationsForAccessor(c, className, name, jsonName, p, true).forEach(annotation => - this.emitLine(annotation) - ); - this.emitLine("public void ", setterName, "(", rendered, " value) { this.", name, " = value; }"); - }); - } - }); - this.finishFile(); - } - - protected unionField(u: UnionType, t: Type, withIssues = false): { fieldType: Sourcelike; fieldName: Sourcelike } { - const fieldType = this.javaType(true, t, withIssues); - // FIXME: "Value" should be part of the name. - const fieldName = [this.nameForUnionMember(u, t), "Value"]; - return { fieldType, fieldName }; - } - - protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { - // empty - } - - protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { - // empty - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - const imports = [...this.importsForType(u), ...this.importsForUnionMembers(u)]; - - this.emitFileHeader(unionName, imports); - this.emitDescription(this.descriptionForType(u)); - const [, nonNulls] = removeNullFromUnion(u); - - this.emitUnionAttributes(u, unionName); - this.emitBlock(["public class ", unionName], () => { - for (const t of nonNulls) { - const { fieldType, fieldName } = this.unionField(u, t, true); - this.emitLine("public ", fieldType, " ", fieldName, ";"); - } - this.emitUnionSerializer(u, unionName); - }); - this.finishFile(); - } - - protected emitEnumSerializationAttributes(_e: EnumType) { - // Empty - } - - protected emitEnumDeserializationAttributes(_e: EnumType) { - // Empty - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitFileHeader(enumName, this.importsForType(e)); - this.emitDescription(this.descriptionForType(e)); - const caseNames: Sourcelike[] = []; - this.forEachEnumCase(e, "none", name => { - if (caseNames.length > 0) caseNames.push(", "); - caseNames.push(name); - }); - caseNames.push(";"); - this.emitBlock(["public enum ", enumName], () => { - this.emitLine(caseNames); - this.ensureBlankLine(); - - this.emitEnumSerializationAttributes(e); - this.emitBlock("public String toValue()", () => { - this.emitLine("switch (this) {"); - this.indent(() => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("case ", name, ': return "', stringEscape(jsonName), '";'); - }); - }); - this.emitLine("}"); - this.emitLine("return null;"); - }); - this.ensureBlankLine(); - - this.emitEnumDeserializationAttributes(e); - this.emitBlock(["public static ", enumName, " forValue(String value) throws IOException"], () => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine('if (value.equals("', stringEscape(jsonName), '")) return ', name, ";"); - }); - this.emitLine('throw new IOException("Cannot deserialize ', enumName, '");'); - }); - }); - this.finishFile(); - } - - protected emitSourceStructure(): void { - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - } -} - -export class JacksonRenderer extends JavaRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - options: OptionValues - ) { - super(targetLanguage, renderContext, options); - } - - protected readonly _converterKeywords: string[] = [ - "JsonProperty", - "JsonDeserialize", - "JsonDeserializer", - "JsonSerialize", - "JsonSerializer", - "JsonParser", - "JsonProcessingException", - "DeserializationContext", - "SerializerProvider" - ]; - - protected emitClassAttributes(c: ClassType, _className: Name): void { - if (c.getProperties().size === 0) - this.emitLine("@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE)"); - - super.emitClassAttributes(c, _className); - } - - protected annotationsForAccessor( - _c: ClassType, - _className: Name, - _propertyName: Name, - jsonName: string, - p: ClassProperty, - _isSetter: boolean - ): string[] { - const superAnnotations = super.annotationsForAccessor(_c, _className, _propertyName, jsonName, p, _isSetter); - - const annotations: string[] = ['@JsonProperty("' + stringEscape(jsonName) + '")']; - - switch (p.type.kind) { - case "date-time": - this._dateTimeProvider.dateTimeJacksonAnnotations.forEach(annotation => annotations.push(annotation)); - break; - case "date": - this._dateTimeProvider.dateJacksonAnnotations.forEach(annotation => annotations.push(annotation)); - break; - case "time": - this._dateTimeProvider.timeJacksonAnnotations.forEach(annotation => annotations.push(annotation)); - break; - default: - break; - } - - return [...superAnnotations, ...annotations]; - } - - protected importsForType(t: ClassType | UnionType | EnumType): string[] { - if (t instanceof ClassType) { - const imports = super.importsForType(t); - imports.push("com.fasterxml.jackson.annotation.*"); - return imports; - } - if (t instanceof UnionType) { - const imports = super.importsForType(t); - imports.push( - "java.io.IOException", - "com.fasterxml.jackson.core.*", - "com.fasterxml.jackson.databind.*", - "com.fasterxml.jackson.databind.annotation.*" - ); - if (this._options.useList) { - imports.push("com.fasterxml.jackson.core.type.*"); - } - return imports; - } - if (t instanceof EnumType) { - const imports = super.importsForType(t); - imports.push("com.fasterxml.jackson.annotation.*"); - return imports; - } - return assertNever(t); - } - - protected emitUnionAttributes(_u: UnionType, unionName: Name): void { - this.emitLine("@JsonDeserialize(using = ", unionName, ".Deserializer.class)"); - this.emitLine("@JsonSerialize(using = ", unionName, ".Serializer.class)"); - } - - protected emitUnionSerializer(u: UnionType, unionName: Name): void { - const stringBasedObjects: TypeKind[] = ["uuid", "time", "date", "date-time"]; - - const tokenCase = (tokenType: string): void => { - this.emitLine("case ", tokenType, ":"); - }; - - const emitNullDeserializer = (): void => { - this.indent(() => { - tokenCase("VALUE_NULL"); - this.indent(() => this.emitLine("break;")); - }); - }; - - const emitDeserializerCodeForStringObjects = ( - fieldName: Sourcelike, - kind: TypeKind, - parseFrom: string - ): void => { - switch (kind) { - case "date": - this.emitLine( - "value.", - fieldName, - " = ", - this._dateTimeProvider.convertStringToDate(parseFrom), - ";" - ); - - break; - case "time": - this.emitLine( - "value.", - fieldName, - " = ", - this._dateTimeProvider.convertStringToTime(parseFrom), - ";" - ); - - break; - case "date-time": - this.emitLine( - "value.", - fieldName, - " = ", - this._dateTimeProvider.convertStringToDateTime(parseFrom), - ";" - ); - break; - case "uuid": - this.emitLine("value.", fieldName, " = UUID.fromString(", parseFrom, ");"); - - break; - default: - return panic("Requested type isnt an object!"); - } - }; - - const emitDeserializeType = (t: Type, variableFieldName = ""): void => { - const { fieldName } = this.unionField(u, t); - const rendered = this.javaTypeWithoutGenerics(true, t); - if (this._options.useList && t instanceof ArrayType) { - this.emitLine( - "value.", - fieldName, - " = jsonParser.readValueAs(new TypeReference<", - rendered, - ">() {});" - ); - } else if (stringBasedObjects.some(stringBasedTypeKind => t.kind === stringBasedTypeKind)) { - emitDeserializerCodeForStringObjects(fieldName, t.kind, variableFieldName); - } else if (t.kind === "string") { - this.emitLine("value.", fieldName, " = ", variableFieldName, ";"); - } else if (t.kind === "enum") { - const { fieldType } = this.unionField(u, t, true); - this.emitLine("value.", fieldName, " = ", fieldType, ".forValue(", variableFieldName, ");"); - } else { - this.emitLine("value.", fieldName, " = jsonParser.readValueAs(", rendered, ".class);"); - } - }; - - const emitDeserializer = (tokenTypes: string[], kind: TypeKind): void => { - const t = u.findMember(kind); - if (t === undefined) return; - - this.indent(() => { - for (const tokenType of tokenTypes) { - tokenCase(tokenType); - } - this.indent(() => { - emitDeserializeType(t); - this.emitLine("break;"); - }); - }); - }; - - const emitStringDeserializer = () => { - const enumType = u.findMember("enum"); - const stringType = u.findMember("string"); - - if ( - stringBasedObjects.every(kind => u.findMember(kind) === undefined) && - stringType === undefined && - enumType === undefined - ) - return; - - this.indent(() => { - tokenCase("VALUE_STRING"); - - this.indent(() => { - const fromVariable = "string"; - this.emitLine("String " + fromVariable + " = jsonParser.readValueAs(String.class);"); - - stringBasedObjects.forEach(kind => { - const type = u.findMember(kind); - if (type !== undefined) { - this.emitIgnoredTryCatchBlock(() => { - emitDeserializeType(type, fromVariable); - }); - } - }); - - if (enumType !== undefined) { - this.emitIgnoredTryCatchBlock(() => { - emitDeserializeType(enumType, fromVariable); - }); - } - - // String should be the last one if exists, because it cannot fail, unlike the parsers. - if (stringType !== undefined) { - emitDeserializeType(stringType, fromVariable); - } - this.emitLine("break;"); - }); - }); - }; - - const emitNumberDeserializer = (): void => { - const integerType = u.findMember("integer"); - const doubleType = u.findMember("double"); - if (doubleType === undefined && integerType === undefined) return; - - this.indent(() => { - tokenCase("VALUE_NUMBER_INT"); - if (integerType !== undefined) { - this.indent(() => { - emitDeserializeType(integerType); - this.emitLine("break;"); - }); - } - if (doubleType !== undefined) { - tokenCase("VALUE_NUMBER_FLOAT"); - this.indent(() => { - emitDeserializeType(doubleType); - this.emitLine("break;"); - }); - } - }); - }; - - const customObjectSerializer: TypeKind[] = ["time", "date", "date-time"]; - - const serializerCodeForType = (type: Type, fieldName: Sourcelike): Sourcelike => { - switch (type.kind) { - case "date": - return this._dateTimeProvider.convertDateToString(fieldName); - case "time": - return this._dateTimeProvider.convertTimeToString(fieldName); - case "date-time": - return this._dateTimeProvider.convertDateTimeToString(fieldName); - default: - return panic("Requested type doesn't have custom serializer code!"); - } - }; - - const emitSerializeType = (t: Type): void => { - let { fieldName } = this.unionField(u, t, true); - - this.emitBlock(["if (obj.", fieldName, " != null)"], () => { - if (customObjectSerializer.some(customSerializerType => t.kind === customSerializerType)) { - this.emitLine("jsonGenerator.writeObject(", serializerCodeForType(t, ["obj.", fieldName]), ");"); - } else { - this.emitLine("jsonGenerator.writeObject(obj.", fieldName, ");"); - } - this.emitLine("return;"); - }); - }; - - const [maybeNull, nonNulls] = removeNullFromUnion(u); - - this.ensureBlankLine(); - this.emitBlock(["static class Deserializer extends JsonDeserializer<", unionName, ">"], () => { - this.emitLine("@Override"); - this.emitBlock( - [ - "public ", - unionName, - " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException" - ], - () => { - this.emitLine(unionName, " value = new ", unionName, "();"); - this.emitLine("switch (jsonParser.currentToken()) {"); - if (maybeNull !== null) emitNullDeserializer(); - emitNumberDeserializer(); - emitDeserializer(["VALUE_TRUE", "VALUE_FALSE"], "bool"); - emitStringDeserializer(); - emitDeserializer(["START_ARRAY"], "array"); - emitDeserializer(["START_OBJECT"], "class"); - emitDeserializer(["START_OBJECT"], "map"); - this.indent(() => - this.emitLine('default: throw new IOException("Cannot deserialize ', unionName, '");') - ); - this.emitLine("}"); - this.emitLine("return value;"); - } - ); - }); - this.ensureBlankLine(); - this.emitBlock(["static class Serializer extends JsonSerializer<", unionName, ">"], () => { - this.emitLine("@Override"); - this.emitBlock( - [ - "public void serialize(", - unionName, - " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException" - ], - () => { - for (const t of nonNulls) { - emitSerializeType(t); - } - if (maybeNull !== null) { - this.emitLine("jsonGenerator.writeNull();"); - } else { - this.emitLine('throw new IOException("', unionName, ' must not be null");'); - } - } - ); - }); - } - - protected emitEnumSerializationAttributes(_e: EnumType) { - this.emitLine("@JsonValue"); - } - - protected emitEnumDeserializationAttributes(_e: EnumType) { - this.emitLine("@JsonCreator"); - } - - protected emitOffsetDateTimeConverterModule(): void { - this.emitLine("SimpleModule module = new SimpleModule();"); - - if (this._dateTimeProvider.shouldEmitDateTimeConverter) { - this.emitLine( - "module.addDeserializer(", - this._dateTimeProvider.dateTimeType, - ".class, new JsonDeserializer<", - this._dateTimeProvider.dateTimeType, - ">() {" - ); - this.indent(() => { - this.emitLine("@Override"); - this.emitBlock( - [ - "public ", - this._dateTimeProvider.dateTimeType, - " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException" - ], - () => { - this.emitLine("String value = jsonParser.getText();"); - this.emitLine("return ", this._dateTimeProvider.convertStringToDateTime("value"), ";"); - } - ); - }); - this.emitLine("});"); - } - - if (!this._dateTimeProvider.shouldEmitTimeConverter) { - this.emitLine( - "module.addDeserializer(", - this._dateTimeProvider.timeType, - ".class, new JsonDeserializer<", - this._dateTimeProvider.timeType, - ">() {" - ); - this.indent(() => { - this.emitLine("@Override"); - this.emitBlock( - [ - "public ", - this._dateTimeProvider.timeType, - " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException" - ], - () => { - this.emitLine("String value = jsonParser.getText();"); - this.emitLine("return ", this._dateTimeProvider.convertStringToTime("value"), ";"); - } - ); - }); - this.emitLine("});"); - } - - if (!this._dateTimeProvider.shouldEmitDateConverter) { - this.emitLine( - "module.addDeserializer(", - this._dateTimeProvider.dateType, - ".class, new JsonDeserializer<", - this._dateTimeProvider.dateType, - ">() {" - ); - this.indent(() => { - this.emitLine("@Override"); - this.emitBlock( - [ - "public ", - this._dateTimeProvider.dateType, - " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", - "throws IOException, JsonProcessingException" - ], - () => { - this.emitLine("String value = jsonParser.getText();"); - this.emitLine("return ", this._dateTimeProvider.convertStringToDate("value"), ";"); - } - ); - }); - this.emitLine("});"); - } - - this.emitLine("mapper.registerModule(module);"); - } - - protected emitConverterClass(): void { - this.startFile(this._converterClassname); - this.emitCommentLines([ - "To use this code, add the following Maven dependency to your project:", - "", - this._options.lombok ? " org.projectlombok : lombok : 1.18.2" : "", - " com.fasterxml.jackson.core : jackson-databind : 2.9.0", - this._options.dateTimeProvider === "java8" - ? " com.fasterxml.jackson.datatype : jackson-datatype-jsr310 : 2.9.0" - : "", - "", - "Import this package:", - "" - ]); - this.emitLine("// import ", this._options.packageName, ".Converter;"); - this.emitMultiline(`// -// Then you can deserialize a JSON string with -//`); - this.forEachTopLevel("none", (t, name) => { - this.emitLine( - "// ", - this.javaType(false, t), - " data = Converter.", - this.decoderName(name), - "(jsonString);" - ); - }); - this.ensureBlankLine(); - const imports = [ - "java.io.IOException", - "com.fasterxml.jackson.databind.*", - "com.fasterxml.jackson.databind.module.SimpleModule", - "com.fasterxml.jackson.core.JsonParser", - "com.fasterxml.jackson.core.JsonProcessingException", - "java.util.*" - ].concat(this._dateTimeProvider.converterImports); - this.emitPackageAndImports(imports); - this.ensureBlankLine(); - this.emitBlock(["public class Converter"], () => { - this.emitLine("// Date-time helpers"); - this._dateTimeProvider.emitDateTimeConverters(); - - this.emitLine("// Serialize/deserialize helpers"); - this.forEachTopLevel("leading-and-interposing", (topLevelType, topLevelName) => { - const topLevelTypeRendered = this.javaType(false, topLevelType); - this.emitBlock( - [ - "public static ", - topLevelTypeRendered, - " ", - this.decoderName(topLevelName), - "(String json) throws IOException" - ], - () => { - this.emitLine("return ", this.readerGetterName(topLevelName), "().readValue(json);"); - } - ); - this.ensureBlankLine(); - this.emitBlock( - [ - "public static String ", - this.encoderName(topLevelName), - "(", - topLevelTypeRendered, - " obj) throws JsonProcessingException" - ], - () => { - this.emitLine("return ", this.writerGetterName(topLevelName), "().writeValueAsString(obj);"); - } - ); - }); - this.forEachTopLevel("leading-and-interposing", (topLevelType, topLevelName) => { - const readerName = this.fieldOrMethodName("reader", topLevelName); - const writerName = this.fieldOrMethodName("writer", topLevelName); - this.emitLine("private static ObjectReader ", readerName, ";"); - this.emitLine("private static ObjectWriter ", writerName, ";"); - this.ensureBlankLine(); - this.emitBlock( - ["private static void ", this.methodName("instantiate", "Mapper", topLevelName), "()"], - () => { - const renderedForClass = this.javaTypeWithoutGenerics(false, topLevelType); - this.emitLine("ObjectMapper mapper = new ObjectMapper();"); - this.emitLine("mapper.findAndRegisterModules();"); - this.emitLine("mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);"); - this.emitLine("mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);"); - this.emitOffsetDateTimeConverterModule(); - this.emitLine(readerName, " = mapper.readerFor(", renderedForClass, ".class);"); - this.emitLine(writerName, " = mapper.writerFor(", renderedForClass, ".class);"); - } - ); - this.ensureBlankLine(); - this.emitBlock(["private static ObjectReader ", this.readerGetterName(topLevelName), "()"], () => { - this.emitLine( - "if (", - readerName, - " == null) ", - this.methodName("instantiate", "Mapper", topLevelName), - "();" - ); - this.emitLine("return ", readerName, ";"); - }); - this.ensureBlankLine(); - this.emitBlock(["private static ObjectWriter ", this.writerGetterName(topLevelName), "()"], () => { - this.emitLine( - "if (", - writerName, - " == null) ", - this.methodName("instantiate", "Mapper", topLevelName), - "();" - ); - this.emitLine("return ", writerName, ";"); - }); - }); - }); - this.finishFile(); - } - - protected emitSourceStructure(): void { - this.emitConverterClass(); - super.emitSourceStructure(); - } -} diff --git a/packages/quicktype-core/src/language/Java/DateTimeProvider.ts b/packages/quicktype-core/src/language/Java/DateTimeProvider.ts new file mode 100644 index 000000000..e1e4d3c73 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/DateTimeProvider.ts @@ -0,0 +1,330 @@ +import type { Sourcelike } from "../../Source"; + +import type { JavaRenderer } from "./JavaRenderer"; + +export abstract class JavaDateTimeProvider { + public constructor( + protected readonly _renderer: JavaRenderer, + protected readonly _className: string, + ) {} + + public abstract keywords: string[]; + + public abstract dateTimeImports: string[]; + + public abstract dateImports: string[]; + + public abstract timeImports: string[]; + + public abstract converterImports: string[]; + + public abstract dateTimeType: string; + + public abstract dateType: string; + + public abstract timeType: string; + + public abstract dateTimeJacksonAnnotations: string[]; + + public abstract dateJacksonAnnotations: string[]; + + public abstract timeJacksonAnnotations: string[]; + + public abstract emitDateTimeConverters(): void; + + public shouldEmitDateTimeConverter = true; + + public shouldEmitTimeConverter = true; + + public shouldEmitDateConverter = true; + + public abstract convertStringToDateTime(variable: Sourcelike): Sourcelike; + public abstract convertStringToTime(variable: Sourcelike): Sourcelike; + public abstract convertStringToDate(variable: Sourcelike): Sourcelike; + + public abstract convertDateTimeToString(variable: Sourcelike): Sourcelike; + public abstract convertTimeToString(variable: Sourcelike): Sourcelike; + public abstract convertDateToString(variable: Sourcelike): Sourcelike; +} + +export class Java8DateTimeProvider extends JavaDateTimeProvider { + public keywords = [ + "LocalDate", + "OffsetDateTime", + "OffsetTime", + "ZoneOffset", + "ZonedDateTime", + "DateTimeFormatter", + "DateTimeFormatterBuilder", + "ChronoField", + ]; + + public dateTimeImports: string[] = ["java.time.OffsetDateTime"]; + + public dateImports: string[] = ["java.time.LocalDate"]; + + public timeImports: string[] = ["java.time.OffsetTime"]; + + public converterImports: string[] = [ + "java.time.LocalDate", + "java.time.OffsetDateTime", + "java.time.OffsetTime", + "java.time.ZoneOffset", + "java.time.ZonedDateTime", + "java.time.format.DateTimeFormatter", + "java.time.format.DateTimeFormatterBuilder", + "java.time.temporal.ChronoField", + ]; + + public dateTimeType = "OffsetDateTime"; + + public dateType = "LocalDate"; + + public timeType = "OffsetTime"; + + public dateTimeJacksonAnnotations: string[] = []; + + public dateJacksonAnnotations: string[] = []; + + public timeJacksonAnnotations: string[] = []; + + public emitDateTimeConverters(): void { + this._renderer.ensureBlankLine(); + this._renderer.emitLine( + "private static final DateTimeFormatter DATE_TIME_FORMATTER = new DateTimeFormatterBuilder()", + ); + this._renderer.indent(() => + this._renderer.indent(() => { + this._renderer.emitLine( + ".appendOptional(DateTimeFormatter.ISO_DATE_TIME)", + ); + this._renderer.emitLine( + ".appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME)", + ); + this._renderer.emitLine( + ".appendOptional(DateTimeFormatter.ISO_INSTANT)", + ); + this._renderer.emitLine( + '.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SX"))', + ); + this._renderer.emitLine( + '.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ssX"))', + ); + this._renderer.emitLine( + '.appendOptional(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))', + ); + this._renderer.emitLine(".toFormatter()"); + this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); + }), + ); + this._renderer.ensureBlankLine(); + this._renderer.emitBlock( + "public static OffsetDateTime parseDateTimeString(String str)", + () => { + this._renderer.emitLine( + "return ZonedDateTime.from(Converter.DATE_TIME_FORMATTER.parse(str)).toOffsetDateTime();", + ); + }, + ); + + this._renderer.ensureBlankLine(); + this._renderer.emitLine( + "private static final DateTimeFormatter TIME_FORMATTER = new DateTimeFormatterBuilder()", + ); + this._renderer.indent(() => + this._renderer.indent(() => { + this._renderer.emitLine( + ".appendOptional(DateTimeFormatter.ISO_TIME)", + ); + this._renderer.emitLine( + ".appendOptional(DateTimeFormatter.ISO_OFFSET_TIME)", + ); + this._renderer.emitLine( + ".parseDefaulting(ChronoField.YEAR, 2020)", + ); + this._renderer.emitLine( + ".parseDefaulting(ChronoField.MONTH_OF_YEAR, 1)", + ); + this._renderer.emitLine( + ".parseDefaulting(ChronoField.DAY_OF_MONTH, 1)", + ); + this._renderer.emitLine(".toFormatter()"); + this._renderer.emitLine(".withZone(ZoneOffset.UTC);"); + }), + ); + this._renderer.ensureBlankLine(); + this._renderer.emitBlock( + "public static OffsetTime parseTimeString(String str)", + () => { + this._renderer.emitLine( + "return ZonedDateTime.from(Converter.TIME_FORMATTER.parse(str)).toOffsetDateTime().toOffsetTime();", + ); + }, + ); + } + + public convertStringToDateTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseDateTimeString(", variable, ")"]; + } + + public convertStringToTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseTimeString(", variable, ")"]; + } + + public convertStringToDate(variable: Sourcelike): Sourcelike { + return ["LocalDate.parse(", variable, ")"]; + } + + public convertDateTimeToString(variable: Sourcelike): Sourcelike { + return [ + variable, + ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME)", + ]; + } + + public convertTimeToString(variable: Sourcelike): Sourcelike { + return [ + variable, + ".format(java.time.format.DateTimeFormatter.ISO_OFFSET_TIME)", + ]; + } + + public convertDateToString(variable: Sourcelike): Sourcelike { + return [ + variable, + ".format(java.time.format.DateTimeFormatter.ISO_DATE)", + ]; + } +} +export class JavaLegacyDateTimeProvider extends JavaDateTimeProvider { + public keywords = ["SimpleDateFormat", "Date"]; + + public dateTimeImports: string[] = ["java.util.Date"]; + + public dateImports: string[] = ["java.util.Date"]; + + public timeImports: string[] = ["java.util.Date"]; + + public converterImports: string[] = [ + "java.util.Date", + "java.text.SimpleDateFormat", + ]; + + public dateTimeType = "Date"; + + public dateType = "Date"; + + public timeType = "Date"; + + public dateTimeJacksonAnnotations: string[] = [ + '@JsonFormat(pattern = "yyyy-MM-dd\'T\'HH:mm:ssX", timezone = "UTC")', + ]; + + public dateJacksonAnnotations: string[] = [ + '@JsonFormat(pattern = "yyyy-MM-dd")', + ]; + + public timeJacksonAnnotations: string[] = [ + '@JsonFormat(pattern = "HH:mm:ssX", timezone = "UTC")', + ]; + + public shouldEmitTimeConverter = false; + + public shouldEmitDateConverter = false; + + public emitDateTimeConverters(): void { + this._renderer.ensureBlankLine(); + this._renderer.emitLine( + "private static final String[] DATE_TIME_FORMATS = {", + ); + this._renderer.indent(() => + this._renderer.indent(() => { + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.SX\","); + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss.S\","); + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ssX\","); + this._renderer.emitLine("\"yyyy-MM-dd'T'HH:mm:ss\","); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.SX",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss.S",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ssX",'); + this._renderer.emitLine('"yyyy-MM-dd HH:mm:ss",'); + this._renderer.emitLine('"HH:mm:ss.SZ",'); + this._renderer.emitLine('"HH:mm:ss.S",'); + this._renderer.emitLine('"HH:mm:ssZ",'); + this._renderer.emitLine('"HH:mm:ss",'); + this._renderer.emitLine('"yyyy-MM-dd",'); + }), + ); + this._renderer.emitLine("};"); + this._renderer.ensureBlankLine(); + this._renderer.emitBlock( + "public static Date parseAllDateTimeString(String str)", + () => { + this._renderer.emitBlock( + "for (String format : DATE_TIME_FORMATS)", + () => { + this._renderer.emitIgnoredTryCatchBlock(() => { + this._renderer.emitLine( + "return new SimpleDateFormat(format).parse(str);", + ); + }); + }, + ); + this._renderer.emitLine("return null;"); + }, + ); + + this._renderer.ensureBlankLine(); + this._renderer.emitBlock( + "public static String serializeDateTime(Date datetime)", + () => { + this._renderer.emitLine( + "return new SimpleDateFormat(\"yyyy-MM-dd'T'hh:mm:ssZ\").format(datetime);", + ); + }, + ); + + this._renderer.ensureBlankLine(); + this._renderer.emitBlock( + "public static String serializeDate(Date datetime)", + () => { + this._renderer.emitLine( + 'return new SimpleDateFormat("yyyy-MM-dd").format(datetime);', + ); + }, + ); + + this._renderer.ensureBlankLine(); + this._renderer.emitBlock( + "public static String serializeTime(Date datetime)", + () => { + this._renderer.emitLine( + 'return new SimpleDateFormat("hh:mm:ssZ").format(datetime);', + ); + }, + ); + } + + public convertStringToDateTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseAllDateTimeString(", variable, ")"]; + } + + public convertStringToTime(variable: Sourcelike): Sourcelike { + return [this._className, ".parseAllDateTimeString(", variable, ")"]; + } + + public convertStringToDate(variable: Sourcelike): Sourcelike { + return [this._className, ".parseAllDateTimeString(", variable, ")"]; + } + + public convertDateTimeToString(variable: Sourcelike): Sourcelike { + return [this._className, ".serializeDateTime(", variable, ")"]; + } + + public convertTimeToString(variable: Sourcelike): Sourcelike { + return [this._className, ".serializeTime(", variable, ")"]; + } + + public convertDateToString(variable: Sourcelike): Sourcelike { + return [this._className, ".serializeDate(", variable, ")"]; + } +} diff --git a/packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts b/packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts new file mode 100644 index 000000000..721bada43 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/JavaJacksonRenderer.ts @@ -0,0 +1,799 @@ +import type { Name } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import type { Sourcelike } from "../../Source"; +import { assertNever, panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + type Type, + type TypeKind, + UnionType, +} from "../../Type"; +import { removeNullFromUnion } from "../../Type/TypeUtils"; + +import { JavaRenderer } from "./JavaRenderer"; +import type { javaOptions } from "./language"; +import { stringEscape } from "./utils"; + +export class JacksonRenderer extends JavaRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + options: OptionValues, + ) { + super(targetLanguage, renderContext, options); + } + + protected readonly _converterKeywords: string[] = [ + "JsonProperty", + "JsonDeserialize", + "JsonDeserializer", + "JsonSerialize", + "JsonSerializer", + "JsonParser", + "JsonProcessingException", + "DeserializationContext", + "SerializerProvider", + ]; + + protected emitClassAttributes(c: ClassType, _className: Name): void { + if (c.getProperties().size === 0) + this.emitLine( + "@JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.NONE)", + ); + + super.emitClassAttributes(c, _className); + } + + protected annotationsForAccessor( + _c: ClassType, + _className: Name, + _propertyName: Name, + jsonName: string, + p: ClassProperty, + _isSetter: boolean, + ): string[] { + const superAnnotations = super.annotationsForAccessor( + _c, + _className, + _propertyName, + jsonName, + p, + _isSetter, + ); + + const annotations: string[] = [ + `@JsonProperty("${stringEscape(jsonName)}")`, + ]; + + switch (p.type.kind) { + case "date-time": + this._dateTimeProvider.dateTimeJacksonAnnotations.forEach( + (annotation) => annotations.push(annotation), + ); + break; + case "date": + this._dateTimeProvider.dateJacksonAnnotations.forEach( + (annotation) => annotations.push(annotation), + ); + break; + case "time": + this._dateTimeProvider.timeJacksonAnnotations.forEach( + (annotation) => annotations.push(annotation), + ); + break; + default: + break; + } + + return [...superAnnotations, ...annotations]; + } + + protected importsForType(t: ClassType | UnionType | EnumType): string[] { + if (t instanceof ClassType) { + const imports = super.importsForType(t); + imports.push("com.fasterxml.jackson.annotation.*"); + return imports; + } + + if (t instanceof UnionType) { + const imports = super.importsForType(t); + imports.push( + "java.io.IOException", + "com.fasterxml.jackson.core.*", + "com.fasterxml.jackson.databind.*", + "com.fasterxml.jackson.databind.annotation.*", + ); + if (this._options.useList) { + imports.push("com.fasterxml.jackson.core.type.*"); + } + + return imports; + } + + if (t instanceof EnumType) { + const imports = super.importsForType(t); + imports.push("com.fasterxml.jackson.annotation.*"); + return imports; + } + + return assertNever(t); + } + + protected emitUnionAttributes(_u: UnionType, unionName: Name): void { + this.emitLine( + "@JsonDeserialize(using = ", + unionName, + ".Deserializer.class)", + ); + this.emitLine( + "@JsonSerialize(using = ", + unionName, + ".Serializer.class)", + ); + } + + protected emitUnionSerializer(u: UnionType, unionName: Name): void { + const stringBasedObjects: TypeKind[] = [ + "uuid", + "time", + "date", + "date-time", + ]; + + const tokenCase = (tokenType: string): void => { + this.emitLine("case ", tokenType, ":"); + }; + + const emitNullDeserializer = (): void => { + this.indent(() => { + tokenCase("VALUE_NULL"); + this.indent(() => this.emitLine("break;")); + }); + }; + + const emitDeserializerCodeForStringObjects = ( + fieldName: Sourcelike, + kind: TypeKind, + parseFrom: string, + ): void => { + switch (kind) { + case "date": + this.emitLine( + "value.", + fieldName, + " = ", + this._dateTimeProvider.convertStringToDate(parseFrom), + ";", + ); + + break; + case "time": + this.emitLine( + "value.", + fieldName, + " = ", + this._dateTimeProvider.convertStringToTime(parseFrom), + ";", + ); + + break; + case "date-time": + this.emitLine( + "value.", + fieldName, + " = ", + this._dateTimeProvider.convertStringToDateTime( + parseFrom, + ), + ";", + ); + break; + case "uuid": + this.emitLine( + "value.", + fieldName, + " = UUID.fromString(", + parseFrom, + ");", + ); + + break; + default: + panic("Requested type isnt an object!"); + } + }; + + const emitDeserializeType = (t: Type, variableFieldName = ""): void => { + const { fieldName } = this.unionField(u, t); + const rendered = this.javaTypeWithoutGenerics(true, t); + if (this._options.useList && t instanceof ArrayType) { + this.emitLine( + "value.", + fieldName, + " = jsonParser.readValueAs(new TypeReference<", + rendered, + ">() {});", + ); + } else if ( + stringBasedObjects.some( + (stringBasedTypeKind) => t.kind === stringBasedTypeKind, + ) + ) { + emitDeserializerCodeForStringObjects( + fieldName, + t.kind, + variableFieldName, + ); + } else if (t.kind === "string") { + this.emitLine( + "value.", + fieldName, + " = ", + variableFieldName, + ";", + ); + } else if (t.kind === "enum") { + const { fieldType } = this.unionField(u, t, true); + this.emitLine( + "value.", + fieldName, + " = ", + fieldType, + ".forValue(", + variableFieldName, + ");", + ); + } else { + this.emitLine( + "value.", + fieldName, + " = jsonParser.readValueAs(", + rendered, + ".class);", + ); + } + }; + + const emitDeserializer = ( + tokenTypes: string[], + kind: TypeKind, + ): void => { + const t = u.findMember(kind); + if (t === undefined) return; + + this.indent(() => { + for (const tokenType of tokenTypes) { + tokenCase(tokenType); + } + + this.indent(() => { + emitDeserializeType(t); + this.emitLine("break;"); + }); + }); + }; + + const emitStringDeserializer = (): void => { + const enumType = u.findMember("enum"); + const stringType = u.findMember("string"); + + if ( + stringBasedObjects.every( + (kind) => u.findMember(kind) === undefined, + ) && + stringType === undefined && + enumType === undefined + ) + return; + + this.indent(() => { + tokenCase("VALUE_STRING"); + + this.indent(() => { + const fromVariable = "string"; + this.emitLine( + `String ${fromVariable} = jsonParser.readValueAs(String.class);`, + ); + + stringBasedObjects.forEach((kind) => { + const type = u.findMember(kind); + if (type !== undefined) { + this.emitIgnoredTryCatchBlock(() => { + emitDeserializeType(type, fromVariable); + }); + } + }); + + if (enumType !== undefined) { + this.emitIgnoredTryCatchBlock(() => { + emitDeserializeType(enumType, fromVariable); + }); + } + + // String should be the last one if exists, because it cannot fail, unlike the parsers. + if (stringType !== undefined) { + emitDeserializeType(stringType, fromVariable); + } + + this.emitLine("break;"); + }); + }); + }; + + const emitNumberDeserializer = (): void => { + const integerType = u.findMember("integer"); + const doubleType = u.findMember("double"); + if (doubleType === undefined && integerType === undefined) return; + + this.indent(() => { + tokenCase("VALUE_NUMBER_INT"); + if (integerType !== undefined) { + this.indent(() => { + emitDeserializeType(integerType); + this.emitLine("break;"); + }); + } + + if (doubleType !== undefined) { + tokenCase("VALUE_NUMBER_FLOAT"); + this.indent(() => { + emitDeserializeType(doubleType); + this.emitLine("break;"); + }); + } + }); + }; + + const customObjectSerializer: TypeKind[] = [ + "time", + "date", + "date-time", + ]; + + const serializerCodeForType = ( + type: Type, + fieldName: Sourcelike, + ): Sourcelike => { + switch (type.kind) { + case "date": + return this._dateTimeProvider.convertDateToString( + fieldName, + ); + case "time": + return this._dateTimeProvider.convertTimeToString( + fieldName, + ); + case "date-time": + return this._dateTimeProvider.convertDateTimeToString( + fieldName, + ); + default: + return panic( + "Requested type doesn't have custom serializer code!", + ); + } + }; + + const emitSerializeType = (t: Type): void => { + const { fieldName } = this.unionField(u, t, true); + + this.emitBlock(["if (obj.", fieldName, " != null)"], () => { + if ( + customObjectSerializer.some( + (customSerializerType) => + t.kind === customSerializerType, + ) + ) { + this.emitLine( + "jsonGenerator.writeObject(", + serializerCodeForType(t, ["obj.", fieldName]), + ");", + ); + } else { + this.emitLine( + "jsonGenerator.writeObject(obj.", + fieldName, + ");", + ); + } + + this.emitLine("return;"); + }); + }; + + const [maybeNull, nonNulls] = removeNullFromUnion(u); + + this.ensureBlankLine(); + this.emitBlock( + [ + "static class Deserializer extends JsonDeserializer<", + unionName, + ">", + ], + () => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + unionName, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException", + ], + () => { + this.emitLine( + unionName, + " value = new ", + unionName, + "();", + ); + this.emitLine("switch (jsonParser.currentToken()) {"); + if (maybeNull !== null) emitNullDeserializer(); + emitNumberDeserializer(); + emitDeserializer(["VALUE_TRUE", "VALUE_FALSE"], "bool"); + emitStringDeserializer(); + emitDeserializer(["START_ARRAY"], "array"); + emitDeserializer(["START_OBJECT"], "class"); + emitDeserializer(["START_OBJECT"], "map"); + this.indent(() => + this.emitLine( + 'default: throw new IOException("Cannot deserialize ', + unionName, + '");', + ), + ); + this.emitLine("}"); + this.emitLine("return value;"); + }, + ); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + ["static class Serializer extends JsonSerializer<", unionName, ">"], + () => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public void serialize(", + unionName, + " obj, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException", + ], + () => { + for (const t of nonNulls) { + emitSerializeType(t); + } + + if (maybeNull !== null) { + this.emitLine("jsonGenerator.writeNull();"); + } else { + this.emitLine( + 'throw new IOException("', + unionName, + ' must not be null");', + ); + } + }, + ); + }, + ); + } + + protected emitEnumSerializationAttributes(_e: EnumType): void { + this.emitLine("@JsonValue"); + } + + protected emitEnumDeserializationAttributes(_e: EnumType): void { + this.emitLine("@JsonCreator"); + } + + protected emitOffsetDateTimeConverterModule(): void { + this.emitLine("SimpleModule module = new SimpleModule();"); + + if (this._dateTimeProvider.shouldEmitDateTimeConverter) { + this.emitLine( + "module.addDeserializer(", + this._dateTimeProvider.dateTimeType, + ".class, new JsonDeserializer<", + this._dateTimeProvider.dateTimeType, + ">() {", + ); + this.indent(() => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + this._dateTimeProvider.dateTimeType, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", + "throws IOException, JsonProcessingException", + ], + () => { + this.emitLine("String value = jsonParser.getText();"); + this.emitLine( + "return ", + this._dateTimeProvider.convertStringToDateTime( + "value", + ), + ";", + ); + }, + ); + }); + this.emitLine("});"); + } + + if (!this._dateTimeProvider.shouldEmitTimeConverter) { + this.emitLine( + "module.addDeserializer(", + this._dateTimeProvider.timeType, + ".class, new JsonDeserializer<", + this._dateTimeProvider.timeType, + ">() {", + ); + this.indent(() => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + this._dateTimeProvider.timeType, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", + "throws IOException, JsonProcessingException", + ], + () => { + this.emitLine("String value = jsonParser.getText();"); + this.emitLine( + "return ", + this._dateTimeProvider.convertStringToTime("value"), + ";", + ); + }, + ); + }); + this.emitLine("});"); + } + + if (!this._dateTimeProvider.shouldEmitDateConverter) { + this.emitLine( + "module.addDeserializer(", + this._dateTimeProvider.dateType, + ".class, new JsonDeserializer<", + this._dateTimeProvider.dateType, + ">() {", + ); + this.indent(() => { + this.emitLine("@Override"); + this.emitBlock( + [ + "public ", + this._dateTimeProvider.dateType, + " deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) ", + "throws IOException, JsonProcessingException", + ], + () => { + this.emitLine("String value = jsonParser.getText();"); + this.emitLine( + "return ", + this._dateTimeProvider.convertStringToDate("value"), + ";", + ); + }, + ); + }); + this.emitLine("});"); + } + + this.emitLine("mapper.registerModule(module);"); + } + + protected emitConverterClass(): void { + this.startFile(this._converterClassname); + this.emitCommentLines([ + "To use this code, add the following Maven dependency to your project:", + "", + this._options.lombok + ? " org.projectlombok : lombok : 1.18.2" + : "", + " com.fasterxml.jackson.core : jackson-databind : 2.9.0", + this._options.dateTimeProvider === "java8" + ? " com.fasterxml.jackson.datatype : jackson-datatype-jsr310 : 2.9.0" + : "", + "", + "Import this package:", + "", + ]); + this.emitLine( + "// import ", + this._options.packageName, + ".Converter;", + ); + this.emitMultiline(`// +// Then you can deserialize a JSON string with +//`); + this.forEachTopLevel("none", (t, name) => { + this.emitLine( + "// ", + this.javaType(false, t), + " data = Converter.", + this.decoderName(name), + "(jsonString);", + ); + }); + this.ensureBlankLine(); + const imports = [ + "java.io.IOException", + "com.fasterxml.jackson.databind.*", + "com.fasterxml.jackson.databind.module.SimpleModule", + "com.fasterxml.jackson.core.JsonParser", + "com.fasterxml.jackson.core.JsonProcessingException", + "java.util.*", + ].concat(this._dateTimeProvider.converterImports); + this.emitPackageAndImports(imports); + this.ensureBlankLine(); + this.emitBlock(["public class Converter"], () => { + this.emitLine("// Date-time helpers"); + this._dateTimeProvider.emitDateTimeConverters(); + + this.emitLine("// Serialize/deserialize helpers"); + this.forEachTopLevel( + "leading-and-interposing", + (topLevelType, topLevelName) => { + const topLevelTypeRendered = this.javaType( + false, + topLevelType, + ); + this.emitBlock( + [ + "public static ", + topLevelTypeRendered, + " ", + this.decoderName(topLevelName), + "(String json) throws IOException", + ], + () => { + this.emitLine( + "return ", + this.readerGetterName(topLevelName), + "().readValue(json);", + ); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "public static String ", + this.encoderName(topLevelName), + "(", + topLevelTypeRendered, + " obj) throws JsonProcessingException", + ], + () => { + this.emitLine( + "return ", + this.writerGetterName(topLevelName), + "().writeValueAsString(obj);", + ); + }, + ); + }, + ); + this.forEachTopLevel( + "leading-and-interposing", + (topLevelType, topLevelName) => { + const readerName = this.fieldOrMethodName( + "reader", + topLevelName, + ); + const writerName = this.fieldOrMethodName( + "writer", + topLevelName, + ); + this.emitLine( + "private static ObjectReader ", + readerName, + ";", + ); + this.emitLine( + "private static ObjectWriter ", + writerName, + ";", + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "private static void ", + this.methodName( + "instantiate", + "Mapper", + topLevelName, + ), + "()", + ], + () => { + const renderedForClass = + this.javaTypeWithoutGenerics( + false, + topLevelType, + ); + this.emitLine( + "ObjectMapper mapper = new ObjectMapper();", + ); + this.emitLine("mapper.findAndRegisterModules();"); + this.emitLine( + "mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);", + ); + this.emitLine( + "mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);", + ); + this.emitOffsetDateTimeConverterModule(); + this.emitLine( + readerName, + " = mapper.readerFor(", + renderedForClass, + ".class);", + ); + this.emitLine( + writerName, + " = mapper.writerFor(", + renderedForClass, + ".class);", + ); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "private static ObjectReader ", + this.readerGetterName(topLevelName), + "()", + ], + () => { + this.emitLine( + "if (", + readerName, + " == null) ", + this.methodName( + "instantiate", + "Mapper", + topLevelName, + ), + "();", + ); + this.emitLine("return ", readerName, ";"); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "private static ObjectWriter ", + this.writerGetterName(topLevelName), + "()", + ], + () => { + this.emitLine( + "if (", + writerName, + " == null) ", + this.methodName( + "instantiate", + "Mapper", + topLevelName, + ), + "();", + ); + this.emitLine("return ", writerName, ";"); + }, + ); + }, + ); + }); + this.finishFile(); + } + + protected emitSourceStructure(): void { + this.emitConverterClass(); + super.emitSourceStructure(); + } +} diff --git a/packages/quicktype-core/src/language/Java/JavaRenderer.ts b/packages/quicktype-core/src/language/Java/JavaRenderer.ts new file mode 100644 index 000000000..5d24de999 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/JavaRenderer.ts @@ -0,0 +1,713 @@ +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { + DependencyName, + type Name, + type Namer, + funPrefixNamer, +} from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { capitalize } from "../../support/Strings"; +import { assert, assertNever, defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + MapType, + type Type, + UnionType, +} from "../../Type"; +import { + directlyReachableSingleNamedType, + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { javaKeywords } from "./constants"; +import { + Java8DateTimeProvider, + type JavaDateTimeProvider, + JavaLegacyDateTimeProvider, +} from "./DateTimeProvider"; +import type { javaOptions } from "./language"; +import { javaNameStyle, stringEscape } from "./utils"; + +export class JavaRenderer extends ConvenienceRenderer { + private _currentFilename: string | undefined; + + private readonly _gettersAndSettersForPropertyName = new Map< + Name, + [Name, Name] + >(); + + private _haveEmittedLeadingComments = false; + + protected readonly _dateTimeProvider: JavaDateTimeProvider; + + protected readonly _converterClassname: string = "Converter"; + + protected readonly _converterKeywords: string[] = []; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + + switch (_options.dateTimeProvider) { + case "legacy": + this._dateTimeProvider = new JavaLegacyDateTimeProvider( + this, + this._converterClassname, + ); + break; + case "java8": + default: + this._dateTimeProvider = new Java8DateTimeProvider( + this, + this._converterClassname, + ); + break; + } + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + const keywords = [ + ...javaKeywords, + ...this._converterKeywords, + this._converterClassname, + ...this._dateTimeProvider.keywords, + ]; + return keywords; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return this.getNameStyling("typeNamingFunction"); + } + + protected namerForObjectProperty(): Namer { + return this.getNameStyling("propertyNamingFunction"); + } + + protected makeUnionMemberNamer(): Namer { + return this.getNameStyling("propertyNamingFunction"); + } + + protected makeEnumCaseNamer(): Namer { + return this.getNameStyling("enumCaseNamingFunction"); + } + + protected unionNeedsName(u: UnionType): boolean { + return nullableFromUnion(u) === null; + } + + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + // If the top-level type doesn't contain any classes or unions + // we have to define a class just for the `FromJson` method, in + // emitFromJsonForTopLevel. + return directlyReachableSingleNamedType(type); + } + + protected makeNamesForPropertyGetterAndSetter( + _c: ClassType, + _className: Name, + _p: ClassProperty, + _jsonName: string, + name: Name, + ): [Name, Name] { + const getterName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `get_${lookup(name)}`, + ); + const setterName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `set_${lookup(name)}`, + ); + return [getterName, setterName]; + } + + protected makePropertyDependencyNames( + c: ClassType, + className: Name, + p: ClassProperty, + jsonName: string, + name: Name, + ): Name[] { + const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter( + c, + className, + p, + jsonName, + name, + ); + this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); + return getterAndSetterNames; + } + + private getNameStyling(convention: string): Namer { + const styling: { [key: string]: Namer } = { + typeNamingFunction: funPrefixNamer("types", (n) => + javaNameStyle( + true, + false, + n, + acronymStyle(this._options.acronymStyle), + ), + ), + propertyNamingFunction: funPrefixNamer("properties", (n) => + javaNameStyle( + false, + false, + n, + acronymStyle(this._options.acronymStyle), + ), + ), + enumCaseNamingFunction: funPrefixNamer("enum-cases", (n) => + javaNameStyle( + true, + true, + n, + acronymStyle(this._options.acronymStyle), + ), + ), + }; + return styling[convention]; + } + + protected fieldOrMethodName( + methodName: string, + topLevelName: Name, + ): Sourcelike { + if (this.topLevels.size === 1) { + return methodName; + } + + return [topLevelName, capitalize(methodName)]; + } + + protected methodName( + prefix: string, + suffix: string, + topLevelName: Name, + ): Sourcelike { + if (this.topLevels.size === 1) { + return [prefix, suffix]; + } + + return [prefix, topLevelName, suffix]; + } + + protected decoderName(topLevelName: Name): Sourcelike { + return this.fieldOrMethodName("fromJsonString", topLevelName); + } + + protected encoderName(topLevelName: Name): Sourcelike { + return this.fieldOrMethodName("toJsonString", topLevelName); + } + + protected readerGetterName(topLevelName: Name): Sourcelike { + return this.methodName("get", "ObjectReader", topLevelName); + } + + protected writerGetterName(topLevelName: Name): Sourcelike { + return this.methodName("get", "ObjectWriter", topLevelName); + } + + protected startFile(basename: Sourcelike): void { + assert( + this._currentFilename === undefined, + "Previous file wasn't finished", + ); + // FIXME: The filenames should actually be Sourcelikes, too + this._currentFilename = `${this.sourcelikeToString(basename)}.java`; + // FIXME: Why is this necessary? + this.ensureBlankLine(); + if ( + !this._haveEmittedLeadingComments && + this.leadingComments !== undefined + ) { + this.emitComments(this.leadingComments); + this.ensureBlankLine(); + this._haveEmittedLeadingComments = true; + } + } + + protected finishFile(): void { + super.finishFile(defined(this._currentFilename)); + this._currentFilename = undefined; + } + + protected emitPackageAndImports(imports: string[]): void { + this.emitLine("package ", this._options.packageName, ";"); + this.ensureBlankLine(); + for (const pkg of imports) { + this.emitLine("import ", pkg, ";"); + } + } + + protected emitFileHeader(fileName: Sourcelike, imports: string[]): void { + this.startFile(fileName); + this.emitPackageAndImports(imports); + this.ensureBlankLine(); + } + + public emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); + } + + public emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + public emitTryCatch( + main: () => void, + handler: () => void, + exception = "Exception", + ): void { + this.emitLine("try {"); + this.indent(main); + this.emitLine("} catch (", exception, " ex) {"); + this.indent(handler); + this.emitLine("}"); + } + + public emitIgnoredTryCatchBlock(f: () => void): void { + this.emitTryCatch(f, () => this.emitLine("// Ignored")); + } + + protected javaType( + reference: boolean, + t: Type, + withIssues = false, + ): Sourcelike { + return matchType( + t, + (_anyType) => + maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Object"), + (_nullType) => + maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Object"), + (_boolType) => (reference ? "Boolean" : "boolean"), + (_integerType) => (reference ? "Long" : "long"), + (_doubleType) => (reference ? "Double" : "double"), + (_stringType) => "String", + (arrayType) => { + if (this._options.useList) { + return [ + "List<", + this.javaType(true, arrayType.items, withIssues), + ">", + ]; + } + + return [ + this.javaType(false, arrayType.items, withIssues), + "[]", + ]; + }, + (classType) => this.nameForNamedType(classType), + (mapType) => [ + "Map", + ], + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) + return this.javaType(true, nullable, withIssues); + return this.nameForNamedType(unionType); + }, + (transformedStringType) => { + if (transformedStringType.kind === "time") { + return this._dateTimeProvider.timeType; + } + + if (transformedStringType.kind === "date") { + return this._dateTimeProvider.dateType; + } + + if (transformedStringType.kind === "date-time") { + return this._dateTimeProvider.dateTimeType; + } + + if (transformedStringType.kind === "uuid") { + return "UUID"; + } + + return "String"; + }, + ); + } + + protected javaImport(t: Type): string[] { + return matchType( + t, + (_anyType) => [], + (_nullType) => [], + (_boolType) => [], + (_integerType) => [], + (_doubleType) => [], + (_stringType) => [], + (arrayType) => { + if (this._options.useList) { + return [ + ...this.javaImport(arrayType.items), + "java.util.List", + ]; + } + + return [...this.javaImport(arrayType.items)]; + }, + (_classType) => [], + (mapType) => [...this.javaImport(mapType.values), "java.util.Map"], + (_enumType) => [], + (unionType) => { + const imports: string[] = []; + unionType.members.forEach((type) => + this.javaImport(type).forEach((imp) => imports.push(imp)), + ); + return imports; + }, + (transformedStringType) => { + if (transformedStringType.kind === "time") { + return this._dateTimeProvider.timeImports; + } + + if (transformedStringType.kind === "date") { + return this._dateTimeProvider.dateImports; + } + + if (transformedStringType.kind === "date-time") { + return this._dateTimeProvider.dateTimeImports; + } + + if (transformedStringType.kind === "uuid") { + return ["java.util.UUID"]; + } + + return []; + }, + ); + } + + protected javaTypeWithoutGenerics(reference: boolean, t: Type): Sourcelike { + if (t instanceof ArrayType) { + if (this._options.useList) { + return ["List"]; + } + + return [this.javaTypeWithoutGenerics(false, t.items), "[]"]; + } + if (t instanceof MapType) { + return "Map"; + } + if (t instanceof UnionType) { + const nullable = nullableFromUnion(t); + if (nullable !== null) + return this.javaTypeWithoutGenerics(true, nullable); + return this.nameForNamedType(t); + } + + return this.javaType(reference, t); + } + + protected emitClassAttributes(_c: ClassType, _className: Name): void { + if (this._options.lombok) { + this.emitLine("@lombok.Data"); + } + } + + protected annotationsForAccessor( + _c: ClassType, + _className: Name, + _propertyName: Name, + _jsonName: string, + _p: ClassProperty, + _isSetter: boolean, + ): string[] { + return []; + } + + protected importsForType(t: ClassType | UnionType | EnumType): string[] { + if (t instanceof ClassType) { + return []; + } + + if (t instanceof UnionType) { + return ["java.io.IOException"]; + } + + if (t instanceof EnumType) { + return ["java.io.IOException"]; + } + + return assertNever(t); + } + + protected importsForClass(c: ClassType): string[] { + const imports: string[] = []; + this.forEachClassProperty(c, "none", (_name, _jsonName, p) => { + this.javaImport(p.type).forEach((imp) => imports.push(imp)); + }); + imports.sort(); + return [...new Set(imports)]; + } + + protected importsForUnionMembers(u: UnionType): string[] { + const imports: string[] = []; + const [, nonNulls] = removeNullFromUnion(u); + this.forEachUnionMember(u, nonNulls, "none", null, (_fieldName, t) => { + this.javaImport(t).forEach((imp) => imports.push(imp)); + }); + imports.sort(); + return [...new Set(imports)]; + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + const imports = [...this.importsForType(c), ...this.importsForClass(c)]; + + this.emitFileHeader(className, imports); + this.emitDescription(this.descriptionForType(c)); + this.emitClassAttributes(c, className); + this.emitBlock(["public class ", className], () => { + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + if ( + this._options.lombok && + this._options.lombokCopyAnnotations + ) { + const getter = this.annotationsForAccessor( + c, + className, + name, + jsonName, + p, + false, + ); + const setter = this.annotationsForAccessor( + c, + className, + name, + jsonName, + p, + true, + ); + if (getter.length !== 0) { + this.emitLine( + `@lombok.Getter(onMethod_ = {${getter.join(", ")}})`, + ); + } + + if (setter.length !== 0) { + this.emitLine( + `@lombok.Setter(onMethod_ = {${setter.join(", ")}})`, + ); + } + } + + this.emitLine( + "private ", + this.javaType(false, p.type, true), + " ", + name, + ";", + ); + }); + if (!this._options.lombok) { + this.forEachClassProperty( + c, + "leading-and-interposing", + (name, jsonName, p) => { + this.emitDescription( + this.descriptionForClassProperty(c, jsonName), + ); + const [getterName, setterName] = defined( + this._gettersAndSettersForPropertyName.get(name), + ); + const rendered = this.javaType(false, p.type); + this.annotationsForAccessor( + c, + className, + name, + jsonName, + p, + false, + ).forEach((annotation) => this.emitLine(annotation)); + this.emitLine( + "public ", + rendered, + " ", + getterName, + "() { return ", + name, + "; }", + ); + this.annotationsForAccessor( + c, + className, + name, + jsonName, + p, + true, + ).forEach((annotation) => this.emitLine(annotation)); + this.emitLine( + "public void ", + setterName, + "(", + rendered, + " value) { this.", + name, + " = value; }", + ); + }, + ); + } + }); + this.finishFile(); + } + + protected unionField( + u: UnionType, + t: Type, + withIssues = false, + ): { fieldName: Sourcelike; fieldType: Sourcelike } { + const fieldType = this.javaType(true, t, withIssues); + // FIXME: "Value" should be part of the name. + const fieldName = [this.nameForUnionMember(u, t), "Value"]; + return { fieldType, fieldName }; + } + + protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { + // empty + } + + protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { + // empty + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + const imports = [ + ...this.importsForType(u), + ...this.importsForUnionMembers(u), + ]; + + this.emitFileHeader(unionName, imports); + this.emitDescription(this.descriptionForType(u)); + const [, nonNulls] = removeNullFromUnion(u); + + this.emitUnionAttributes(u, unionName); + this.emitBlock(["public class ", unionName], () => { + for (const t of nonNulls) { + const { fieldType, fieldName } = this.unionField(u, t, true); + this.emitLine("public ", fieldType, " ", fieldName, ";"); + } + + this.emitUnionSerializer(u, unionName); + }); + this.finishFile(); + } + + protected emitEnumSerializationAttributes(_e: EnumType): void { + // Empty + } + + protected emitEnumDeserializationAttributes(_e: EnumType): void { + // Empty + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitFileHeader(enumName, this.importsForType(e)); + this.emitDescription(this.descriptionForType(e)); + const caseNames: Sourcelike[] = []; + this.forEachEnumCase(e, "none", (name) => { + if (caseNames.length > 0) caseNames.push(", "); + caseNames.push(name); + }); + caseNames.push(";"); + this.emitBlock(["public enum ", enumName], () => { + this.emitLine(caseNames); + this.ensureBlankLine(); + + this.emitEnumSerializationAttributes(e); + this.emitBlock("public String toValue()", () => { + this.emitLine("switch (this) {"); + this.indent(() => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine( + "case ", + name, + ': return "', + stringEscape(jsonName), + '";', + ); + }); + }); + this.emitLine("}"); + this.emitLine("return null;"); + }); + this.ensureBlankLine(); + + this.emitEnumDeserializationAttributes(e); + this.emitBlock( + [ + "public static ", + enumName, + " forValue(String value) throws IOException", + ], + () => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine( + 'if (value.equals("', + stringEscape(jsonName), + '")) return ', + name, + ";", + ); + }); + this.emitLine( + 'throw new IOException("Cannot deserialize ', + enumName, + '");', + ); + }, + ); + }); + this.finishFile(); + } + + protected emitSourceStructure(): void { + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n), + ); + } +} diff --git a/packages/quicktype-core/src/language/Java/constants.ts b/packages/quicktype-core/src/language/Java/constants.ts new file mode 100644 index 000000000..c16c58cd1 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/constants.ts @@ -0,0 +1,69 @@ +export const javaKeywords = [ + "_", // as of release 9, '_' is a keyword, and may not be used as an identifier + "Object", + "Class", + "System", + "Long", + "Double", + "Boolean", + "String", + "List", + "Map", + "UUID", + "Exception", + "IOException", + "Override", + "abstract", + "continue", + "for", + "new", + "switch", + "assert", + "default", + "goto", + "package", + "synchronized", + "boolean", + "do", + "if", + "private", + "this", + "break", + "double", + "implements", + "protected", + "throw", + "byte", + "else", + "import", + "public", + "throws", + "case", + "enum", + "instanceof", + "return", + "transient", + "catch", + "extends", + "int", + "short", + "try", + "char", + "final", + "interface", + "static", + "void", + "class", + "finally", + "long", + "strictfp", + "volatile", + "const", + "float", + "native", + "super", + "while", + "null", + "false", + "true", +] as const; diff --git a/packages/quicktype-core/src/language/Java/index.ts b/packages/quicktype-core/src/language/Java/index.ts new file mode 100644 index 000000000..ea2ba695e --- /dev/null +++ b/packages/quicktype-core/src/language/Java/index.ts @@ -0,0 +1,3 @@ +export { JavaTargetLanguage, javaOptions } from "./language"; +export { JavaRenderer } from "./JavaRenderer"; +export { JacksonRenderer } from "./JavaJacksonRenderer"; diff --git a/packages/quicktype-core/src/language/Java/language.ts b/packages/quicktype-core/src/language/Java/language.ts new file mode 100644 index 000000000..e8bf57b86 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/language.ts @@ -0,0 +1,93 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { JacksonRenderer } from "./JavaJacksonRenderer"; +import { JavaRenderer } from "./JavaRenderer"; + +export const javaOptions = { + useList: new EnumOption( + "array-type", + "Use T[] or List", + { array: false, list: true } as const, + "array", + ), + justTypes: new BooleanOption("just-types", "Plain types only", false), + dateTimeProvider: new EnumOption( + "datetime-provider", + "Date time provider type", + { java8: "java8", legacy: "legacy" } as const, + "java8", + ), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + // FIXME: Do this via a configurable named eventually. + packageName: new StringOption( + "package", + "Generated package name", + "NAME", + "io.quicktype", + ), + lombok: new BooleanOption("lombok", "Use lombok", false, "primary"), + lombokCopyAnnotations: new BooleanOption( + "lombok-copy-annotations", + "Copy accessor annotations", + true, + "secondary", + ), +}; + +export const javaLanguageConfig = { + displayName: "Java", + names: ["java"], + extension: "java", +} as const; + +export class JavaTargetLanguage extends TargetLanguage< + typeof javaLanguageConfig +> { + public constructor() { + super(javaLanguageConfig); + } + + public getOptions(): typeof javaOptions { + return javaOptions; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): JavaRenderer { + const options = getOptionValues(javaOptions, untypedOptionValues); + if (options.justTypes) { + return new JavaRenderer(this, renderContext, options); + } + + return new JacksonRenderer(this, renderContext, options); + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + mapping.set("date", "date"); + mapping.set("time", "time"); + mapping.set("date-time", "date-time"); + mapping.set("uuid", "uuid"); + return mapping; + } +} diff --git a/packages/quicktype-core/src/language/Java/utils.ts b/packages/quicktype-core/src/language/Java/utils.ts new file mode 100644 index 000000000..8e27c72b6 --- /dev/null +++ b/packages/quicktype-core/src/language/Java/utils.ts @@ -0,0 +1,57 @@ +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + isAscii, + isDigit, + isLetter, + splitIntoWords, + standardUnicodeHexEscape, + utf16ConcatMap, + utf16LegalizeCharacters, +} from "../../support/Strings"; + +export const stringEscape = utf16ConcatMap( + escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape), +); + +function isStartCharacter(codePoint: number): boolean { + if (codePoint === 0x5f) return true; // underscore + return isAscii(codePoint) && isLetter(codePoint); +} + +function isPartCharacter(codePoint: number): boolean { + return ( + isStartCharacter(codePoint) || + (isAscii(codePoint) && isDigit(codePoint)) + ); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export function javaNameStyle( + startWithUpper: boolean, + upperUnderscore: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle, +): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upperUnderscore + ? allUpperWordStyle + : startWithUpper + ? firstUpperWordStyle + : allLowerWordStyle, + upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, + upperUnderscore || startWithUpper + ? allUpperWordStyle + : allLowerWordStyle, + acronymsStyle, + upperUnderscore ? "_" : "", + isStartCharacter, + ); +} diff --git a/packages/quicktype-core/src/language/JavaScript.ts b/packages/quicktype-core/src/language/JavaScript/JavaScriptRenderer.ts similarity index 65% rename from packages/quicktype-core/src/language/JavaScript.ts rename to packages/quicktype-core/src/language/JavaScript/JavaScriptRenderer.ts index 36f78a12c..daf635690 100644 --- a/packages/quicktype-core/src/language/JavaScript.ts +++ b/packages/quicktype-core/src/language/JavaScript/JavaScriptRenderer.ts @@ -1,118 +1,55 @@ import { arrayIntercalate } from "collection-utils"; +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { ConvertersOptions } from "../../support/Converters"; import { - TransformedStringTypeKind, - PrimitiveStringTypeKind, - Type, - ClassProperty, - ClassType, - ObjectType -} from "../Type"; -import { matchType, directlyReachableSingleNamedType } from "../TypeUtils"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { convertersOption, ConvertersOptions } from "../support/Converters"; - -import { - utf16LegalizeCharacters, - utf16StringEscape, - splitIntoWords, + allLowerWordStyle, + camelCase, capitalize, combineWords, firstUpperWordStyle, - camelCase, - allLowerWordStyle -} from "../support/Strings"; -import { panic } from "../support/Support"; - -import { Sourcelike, modifySource } from "../Source"; -import { Namer, Name, funPrefixNamer } from "../Naming"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { TargetLanguage } from "../TargetLanguage"; -import { StringTypeMapping } from "../TypeBuilder"; -import { BooleanOption, Option, OptionValues, getOptionValues, EnumOption } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; -import { isES3IdentifierPart, isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; - -export const javaScriptOptions = { - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - runtimeTypecheck: new BooleanOption("runtime-typecheck", "Verify JSON.parse results at runtime", true), - runtimeTypecheckIgnoreUnknownProperties: new BooleanOption( - "runtime-typecheck-ignore-unknown-properties", - "Ignore unknown properties when verifying at runtime", - false, - "secondary" - ), - converters: convertersOption(), - rawType: new EnumOption<"json" | "any">( - "raw-type", - "Type of raw input (json by default)", - [ - ["json", "json"], - ["any", "any"] - ], - "json", - "secondary" - ) -}; - -export type JavaScriptTypeAnnotations = { + splitIntoWords, + utf16StringEscape, +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import type { + ClassProperty, + ClassType, + ObjectType, + Type, +} from "../../Type"; +import { + directlyReachableSingleNamedType, + matchType, +} from "../../Type/TypeUtils"; + +import type { javaScriptOptions } from "./language"; +import { isES3IdentifierStart } from "./unicodeMaps"; +import { legalizeName } from "./utils"; + +export interface JavaScriptTypeAnnotations { any: string; anyArray: string; anyMap: string; - string: string; - stringArray: string; boolean: string; never: string; -}; - -export class JavaScriptTargetLanguage extends TargetLanguage { - constructor(displayName = "JavaScript", names: string[] = ["javascript", "js", "jsx"], extension = "js") { - super(displayName, names, extension); - } - - protected getOptions(): Option[] { - return [ - javaScriptOptions.runtimeTypecheck, - javaScriptOptions.runtimeTypecheckIgnoreUnknownProperties, - javaScriptOptions.acronymStyle, - javaScriptOptions.converters, - javaScriptOptions.rawType - ]; - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - const dateTimeType = "date-time"; - mapping.set("date", dateTimeType); - mapping.set("date-time", dateTimeType); - return mapping; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsFullObjectType(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): JavaScriptRenderer { - return new JavaScriptRenderer(this, renderContext, getOptionValues(javaScriptOptions, untypedOptionValues)); - } + string: string; + stringArray: string; } -export const legalizeName = utf16LegalizeCharacters(isES3IdentifierPart); - -const identityNamingFunction = funPrefixNamer("properties", s => s); +const identityNamingFunction = funPrefixNamer("properties", (s) => s); export class JavaScriptRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _jsOptions: OptionValues + private readonly _jsOptions: OptionValues, ) { super(targetLanguage, renderContext); } @@ -125,15 +62,15 @@ export class JavaScriptRenderer extends ConvenienceRenderer { legalizeName, upper ? firstUpperWordStyle : allLowerWordStyle, firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isES3IdentifierStart + isES3IdentifierStart, ); } protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("types", s => this.nameStyle(s, true)); + return funPrefixNamer("types", (s) => this.nameStyle(s, true)); } protected namerForObjectProperty(): Namer { @@ -145,7 +82,7 @@ export class JavaScriptRenderer extends ConvenienceRenderer { } protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enum-cases", s => this.nameStyle(s, true)); + return funPrefixNamer("enum-cases", (s) => this.nameStyle(s, true)); } protected namedTypeToNameForTopLevel(type: Type): Type | undefined { @@ -157,80 +94,99 @@ export class JavaScriptRenderer extends ConvenienceRenderer { className: Name, p: ClassProperty, jsonName: string, - _assignedName: string | undefined + _assignedName: string | undefined, ): Name | undefined { // Ignore the assigned name return super.makeNameForProperty(c, className, p, jsonName, undefined); } protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); } - typeMapTypeFor(t: Type): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + private typeMapTypeFor(t: Type): Sourcelike { + if (["class", "object", "enum"].includes(t.kind)) { return ['r("', this.nameForNamedType(t), '")']; } + return matchType( t, - _anyType => '"any"', - _nullType => `null`, - _boolType => `true`, - _integerType => `0`, - _doubleType => `3.14`, - _stringType => `""`, - arrayType => ["a(", this.typeMapTypeFor(arrayType.items), ")"], - _classType => panic("We handled this above"), - mapType => ["m(", this.typeMapTypeFor(mapType.values), ")"], - _enumType => panic("We handled this above"), - unionType => { - const children = Array.from(unionType.getChildren()).map((type: Type) => this.typeMapTypeFor(type)); + (_anyType) => '"any"', + (_nullType) => "null", + (_boolType) => "true", + (_integerType) => "0", + (_doubleType) => "3.14", + (_stringType) => '""', + (arrayType) => ["a(", this.typeMapTypeFor(arrayType.items), ")"], + (_classType) => panic("We handled this above"), + (mapType) => ["m(", this.typeMapTypeFor(mapType.values), ")"], + (_enumType) => panic("We handled this above"), + (unionType) => { + const children = Array.from(unionType.getChildren()).map( + (type: Type) => this.typeMapTypeFor(type), + ); return ["u(", ...arrayIntercalate(", ", children), ")"]; }, - transformedStringType => { + (transformedStringType) => { if (transformedStringType.kind === "date-time") { return "Date"; } - return `""`; - } + + return '""'; + }, ); } - typeMapTypeForProperty(p: ClassProperty): Sourcelike { + private typeMapTypeForProperty(p: ClassProperty): Sourcelike { const typeMap = this.typeMapTypeFor(p.type); if (!p.isOptional) { return typeMap; } + return ["u(undefined, ", typeMap, ")"]; } - emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock( + source: Sourcelike, + end: Sourcelike, + emit: () => void, + ): void { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); } - emitTypeMap() { + private emitTypeMap(): void { const { any: anyAnnotation } = this.typeAnnotations; this.emitBlock(`const typeMap${anyAnnotation} = `, ";", () => { this.forEachObject("none", (t: ObjectType, name: Name) => { const additionalProperties = t.getAdditionalProperties(); const additional = - additionalProperties !== undefined ? this.typeMapTypeFor(additionalProperties) : "false"; + additionalProperties !== undefined + ? this.typeMapTypeFor(additionalProperties) + : "false"; this.emitLine('"', name, '": o(['); this.indent(() => { - this.forEachClassProperty(t, "none", (propName, jsonName, property) => { - this.emitLine( - '{ json: "', - utf16StringEscape(jsonName), - '", js: "', - modifySource(utf16StringEscape, propName), - '", typ: ', - this.typeMapTypeForProperty(property), - " }," - ); - }); + this.forEachClassProperty( + t, + "none", + (propName, jsonName, property) => { + this.emitLine( + '{ json: "', + utf16StringEscape(jsonName), + '", js: "', + modifySource(utf16StringEscape, propName), + '", typ: ', + this.typeMapTypeForProperty(property), + " },", + ); + }, + ); }); this.emitLine("], ", additional, "),"); }); @@ -279,38 +235,63 @@ export class JavaScriptRenderer extends ConvenienceRenderer { string: "", stringArray: "", boolean: "", - never: "" + never: "", }; } protected emitConvertModuleBody(): void { - const converter = (t: Type, name: Name) => { + const converter = (t: Type, name: Name): void => { const typeMap = this.typeMapTypeFor(t); - this.emitBlock([this.deserializerFunctionLine(t, name), " "], "", () => { - const parsedJson = this._jsOptions.rawType === "json" ? "JSON.parse(json)" : "json"; - if (!this._jsOptions.runtimeTypecheck) { - this.emitLine("return ", parsedJson, ";"); - } else { - this.emitLine("return cast(", parsedJson, ", ", typeMap, ");"); - } - }); - this.ensureBlankLine(); - - this.emitBlock([this.serializerFunctionLine(t, name), " "], "", () => { - if (this._jsOptions.rawType === "json") { + this.emitBlock( + [this.deserializerFunctionLine(t, name), " "], + "", + () => { + const parsedJson = + this._jsOptions.rawType === "json" + ? "JSON.parse(json)" + : "json"; if (!this._jsOptions.runtimeTypecheck) { - this.emitLine("return JSON.stringify(value);"); + this.emitLine("return ", parsedJson, ";"); } else { - this.emitLine("return JSON.stringify(uncast(value, ", typeMap, "), null, 2);"); + this.emitLine( + "return cast(", + parsedJson, + ", ", + typeMap, + ");", + ); } - } else { - if (!this._jsOptions.runtimeTypecheck) { - this.emitLine("return value;"); + }, + ); + this.ensureBlankLine(); + + this.emitBlock( + [this.serializerFunctionLine(t, name), " "], + "", + () => { + if (this._jsOptions.rawType === "json") { + if (!this._jsOptions.runtimeTypecheck) { + this.emitLine("return JSON.stringify(value);"); + } else { + this.emitLine( + "return JSON.stringify(uncast(value, ", + typeMap, + "), null, 2);", + ); + } } else { - this.emitLine("return uncast(value, ", typeMap, ");"); + if (!this._jsOptions.runtimeTypecheck) { + this.emitLine("return value;"); + } else { + this.emitLine( + "return uncast(value, ", + typeMap, + ");", + ); + } } - } - }); + }, + ); }; switch (this._jsOptions.converters) { @@ -332,11 +313,10 @@ export class JavaScriptRenderer extends ConvenienceRenderer { anyMap: anyMapAnnotation, string: stringAnnotation, stringArray: stringArrayAnnotation, - never: neverAnnotation + never: neverAnnotation, } = this.typeAnnotations; this.ensureBlankLine(); - this - .emitMultiline(`function invalidValue(typ${anyAnnotation}, val${anyAnnotation}, key${anyAnnotation}, parent${anyAnnotation} = '')${neverAnnotation} { + this.emitMultiline(`function invalidValue(typ${anyAnnotation}, val${anyAnnotation}, key${anyAnnotation}, parent${anyAnnotation} = '')${neverAnnotation} { const prettyTyp = prettyTypeName(typ); const parentText = parent ? \` on \${parent}\` : ''; const keyText = key ? \` for key "\${key}"\` : ''; @@ -429,8 +409,8 @@ function transform(val${anyAnnotation}, typ${anyAnnotation}, getProps${anyAnnota if (!Object.prototype.hasOwnProperty.call(props, key)) { result[key] = ${ this._jsOptions.runtimeTypecheckIgnoreUnknownProperties - ? `val[key]` - : `transform(val[key], additional, getProps, key, ref)` + ? "val[key]" + : "transform(val[key], additional, getProps, key, ref)" }; } }); @@ -499,18 +479,21 @@ function r(name${stringAnnotation}) { protected emitConvertModule(): void { this.ensureBlankLine(); this.emitMultiline( - `// Converts JSON ${this._jsOptions.rawType === "json" ? "strings" : "types"} to/from your types` + `// Converts JSON ${this._jsOptions.rawType === "json" ? "strings" : "types"} to/from your types`, ); if (this._jsOptions.runtimeTypecheck) { this.emitMultiline( - `// and asserts the results${this._jsOptions.rawType === "json" ? " of JSON.parse" : ""} at runtime` + `// and asserts the results${this._jsOptions.rawType === "json" ? " of JSON.parse" : ""} at runtime`, ); } + const moduleLine = this.moduleLine; if (moduleLine === undefined) { this.emitConvertModuleBody(); } else { - this.emitBlock([moduleLine, " "], "", () => this.emitConvertModuleBody()); + this.emitBlock([moduleLine, " "], "", () => + this.emitConvertModuleBody(), + ); } } @@ -530,12 +513,22 @@ function r(name${stringAnnotation}) { this.emitLine("//"); this.forEachTopLevel("none", (_t, name) => { const camelCaseName = modifySource(camelCase, name); - this.emitLine("// const ", camelCaseName, " = Convert.to", name, "(json);"); + this.emitLine( + "// const ", + camelCaseName, + " = Convert.to", + name, + "(json);", + ); }); if (this._jsOptions.runtimeTypecheck) { this.emitLine("//"); - this.emitLine("// These functions will throw an error if the JSON doesn't"); - this.emitLine("// match the expected interface, even if the JSON is valid."); + this.emitLine( + "// These functions will throw an error if the JSON doesn't", + ); + this.emitLine( + "// match the expected interface, even if the JSON is valid.", + ); } } @@ -552,9 +545,9 @@ function r(name${stringAnnotation}) { }); } - protected emitSourceStructure() { + protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); + this.emitComments(this.leadingComments); } else { this.emitUsageComments(); } diff --git a/packages/quicktype-core/src/language/JavaScript/index.ts b/packages/quicktype-core/src/language/JavaScript/index.ts new file mode 100644 index 000000000..aedefb9aa --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/index.ts @@ -0,0 +1,5 @@ +export { JavaScriptTargetLanguage, javaScriptOptions } from "./language"; +export { + JavaScriptRenderer, + type JavaScriptTypeAnnotations, +} from "./JavaScriptRenderer"; diff --git a/packages/quicktype-core/src/language/JavaScript/language.ts b/packages/quicktype-core/src/language/JavaScript/language.ts new file mode 100644 index 000000000..33690bbc6 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/language.ts @@ -0,0 +1,89 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + getOptionValues, +} from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { convertersOption } from "../../support/Converters"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { JavaScriptRenderer } from "./JavaScriptRenderer"; + +export const javaScriptOptions = { + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + runtimeTypecheck: new BooleanOption( + "runtime-typecheck", + "Verify JSON.parse results at runtime", + true, + ), + runtimeTypecheckIgnoreUnknownProperties: new BooleanOption( + "runtime-typecheck-ignore-unknown-properties", + "Ignore unknown properties when verifying at runtime", + false, + "secondary", + ), + converters: convertersOption(), + rawType: new EnumOption( + "raw-type", + "Type of raw input (json by default)", + { + json: "json", + any: "any", + } as const, + "json", + "secondary", + ), +}; + +export const javaScriptLanguageConfig = { + displayName: "JavaScript", + names: ["javascript", "js", "jsx"], + extension: "js", +} as const; + +export class JavaScriptTargetLanguage extends TargetLanguage< + typeof javaScriptLanguageConfig +> { + public constructor() { + super(javaScriptLanguageConfig); + } + + public getOptions(): typeof javaScriptOptions { + return javaScriptOptions; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("date-time", dateTimeType); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsFullObjectType(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): JavaScriptRenderer { + return new JavaScriptRenderer( + this, + renderContext, + getOptionValues(javaScriptOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/JavaScript/unicodeMaps.ts b/packages/quicktype-core/src/language/JavaScript/unicodeMaps.ts new file mode 100644 index 000000000..fde130b6b --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/unicodeMaps.ts @@ -0,0 +1,194 @@ +/* eslint-disable */ +// Taken from https://github.com/Microsoft/TypeScript + +function lookupInUnicodeMap(code: number, map: readonly number[]): boolean { + // Bail out quickly if it couldn't possibly be in the map. + if (code < map[0]) { + return false; + } + + // Perform binary search in one of the Unicode range maps + let lo = 0; + let hi: number = map.length; + let mid: number; + + while (lo + 1 < hi) { + mid = lo + (hi - lo) / 2; + // mid has to be even to catch a range's beginning + mid -= mid % 2; + if (map[mid] <= code && code <= map[mid + 1]) { + return true; + } + + if (code < map[mid]) { + hi = mid; + } else { + lo = mid + 2; + } + } + + return false; +} + +enum CharacterCodes { + maxAsciiCharacter = 0x7f, + + _ = 0x5f, + $ = 0x24, + + _0 = 0x30, + _9 = 0x39, + + a = 0x61, + z = 0x7a, + + A = 0x41, + Z = 0x5a, +} + +export function isES3IdentifierStart(ch: number): boolean { + return ( + (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || + (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || + ch === CharacterCodes.$ || + ch === CharacterCodes._ || + (ch > CharacterCodes.maxAsciiCharacter && + lookupInUnicodeMap(ch, unicodeES3IdentifierStart)) + ); +} + +export function isES3IdentifierPart(ch: number): boolean { + return ( + (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || + (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || + (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) || + ch === CharacterCodes.$ || + ch === CharacterCodes._ || + (ch > CharacterCodes.maxAsciiCharacter && + lookupInUnicodeMap(ch, unicodeES3IdentifierPart)) + ); +} + +/* + As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers + IdentifierStart :: + Can contain Unicode 3.0.0 categories: + Uppercase letter (Lu), + Lowercase letter (Ll), + Titlecase letter (Lt), + Modifier letter (Lm), + Other letter (Lo), or + Letter number (Nl). + IdentifierPart :: = + Can contain IdentifierStart + Unicode 3.0.0 categories: + Non-spacing mark (Mn), + Combining spacing mark (Mc), + Decimal number (Nd), or + Connector punctuation (Pc). + Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at: + http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt +*/ +const unicodeES3IdentifierStart = [ + 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, + 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 890, 890, 902, 902, + 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, + 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, + 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, 1569, 1594, 1600, 1610, + 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, + 1920, 1957, 2309, 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, + 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2524, 2525, + 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, + 2610, 2611, 2613, 2614, 2616, 2617, 2649, 2652, 2654, 2654, 2674, 2676, + 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, + 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, + 2835, 2856, 2858, 2864, 2866, 2867, 2870, 2873, 2877, 2877, 2908, 2909, + 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, + 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, + 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, 3169, 3205, 3212, + 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, + 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, + 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, 3635, + 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, + 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, + 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, + 3840, 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, + 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, 4352, 4441, 4447, 4514, + 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, + 4696, 4696, 4698, 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, + 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, 4814, + 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, + 4896, 4934, 4936, 4954, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, + 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, + 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, + 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, + 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, + 8182, 8188, 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, + 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, + 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, + 12346, 12353, 12436, 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, + 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, + 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, + 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, + 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65136, 65138, + 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, + 65479, 65482, 65487, 65490, 65495, 65498, 65500, +]; +const unicodeES3IdentifierPart = [ + 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, + 685, 688, 696, 699, 705, 720, 721, 736, 740, 750, 750, 768, 846, 864, 866, + 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, + 1011, 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, + 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1425, 1441, 1443, + 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, + 1522, 1569, 1594, 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, + 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, 1968, 2305, + 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, + 2435, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, + 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, + 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, + 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, 2617, 2620, 2620, 2622, + 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, + 2691, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, + 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, 2768, 2768, 2784, + 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, + 2864, 2866, 2867, 2870, 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, + 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, 2958, + 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, + 2986, 2990, 2997, 2999, 3001, 3006, 3010, 3014, 3016, 3018, 3021, 3031, + 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, + 3123, 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, + 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, 3216, 3218, 3240, 3242, + 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, + 3294, 3296, 3297, 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, + 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, 3415, 3424, + 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, + 3517, 3520, 3526, 3530, 3530, 3535, 3540, 3542, 3542, 3544, 3551, 3570, + 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, + 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, + 3749, 3751, 3751, 3754, 3755, 3757, 3769, 3771, 3773, 3776, 3780, 3782, + 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, + 3881, 3893, 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, + 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, 4096, 4129, 4131, + 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, + 4293, 4304, 4342, 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, + 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, 4704, + 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, + 4798, 4800, 4800, 4802, 4805, 4808, 4814, 4816, 4822, 4824, 4846, 4848, + 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, + 4977, 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, + 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, 6313, 7680, 7835, 7840, + 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, + 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, + 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, + 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, + 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, + 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, + 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, + 12445, 12446, 12449, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, + 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, + 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, + 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, + 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, 65138, 65140, + 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, + 65381, 65470, 65474, 65479, 65482, 65487, 65490, 65495, 65498, 65500, +]; diff --git a/packages/quicktype-core/src/language/JavaScript/utils.ts b/packages/quicktype-core/src/language/JavaScript/utils.ts new file mode 100644 index 000000000..7acc4c931 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScript/utils.ts @@ -0,0 +1,5 @@ +import { utf16LegalizeCharacters } from "../../support/Strings"; + +import { isES3IdentifierPart } from "./unicodeMaps"; + +export const legalizeName = utf16LegalizeCharacters(isES3IdentifierPart); diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts similarity index 53% rename from packages/quicktype-core/src/language/JavaScriptPropTypes.ts rename to packages/quicktype-core/src/language/JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts index c2d6f34bb..7bd6d68d6 100644 --- a/packages/quicktype-core/src/language/JavaScriptPropTypes.ts +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/JavaScriptPropTypesRenderer.ts @@ -1,72 +1,47 @@ -import { TargetLanguage } from "../TargetLanguage"; -import { getOptionValues, Option, OptionValues, EnumOption } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { funPrefixNamer, Name, Namer } from "../Naming"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; +import { arrayIntercalate } from "collection-utils"; + +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import type { Sourcelike } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; import { + allLowerWordStyle, capitalize, - ClassProperty, - ClassType, combineWords, firstUpperWordStyle, - matchType, - ObjectType, - panic, - Sourcelike, splitIntoWords, - Type -} from ".."; -import { allLowerWordStyle, utf16StringEscape } from "../support/Strings"; -import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; -import { legalizeName } from "./JavaScript"; -import { convertersOption } from "../support/Converters"; -import { directlyReachableSingleNamedType } from "../TypeUtils"; -import { arrayIntercalate } from "collection-utils"; -import { PrimitiveType } from "../Type"; - -export const javaScriptPropTypesOptions = { - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - converters: convertersOption(), - moduleSystem: new EnumOption( - "module-system", - "Which module system to use", - [ - ["common-js", false], - ["es6", true] - ], - "es6" - ) -}; - -export class JavaScriptPropTypesTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return [javaScriptPropTypesOptions.acronymStyle, javaScriptPropTypesOptions.converters]; - } - - constructor(displayName = "JavaScript PropTypes", names: string[] = ["javascript-prop-types"], extension = "js") { - super(displayName, names, extension); - } + utf16StringEscape, +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + type ArrayType, + type ClassProperty, + type ClassType, + type ObjectType, + PrimitiveType, + type Type, +} from "../../Type"; +import { + directlyReachableSingleNamedType, + matchType, +} from "../../Type/TypeUtils"; +import { isES3IdentifierStart } from "../JavaScript/unicodeMaps"; +import { legalizeName } from "../JavaScript/utils"; - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): JavaScriptPropTypesRenderer { - return new JavaScriptPropTypesRenderer( - this, - renderContext, - getOptionValues(javaScriptPropTypesOptions, untypedOptionValues) - ); - } -} +import type { javaScriptPropTypesOptions } from "./language"; -const identityNamingFunction = funPrefixNamer("properties", s => s); +const identityNamingFunction = funPrefixNamer("properties", (s) => s); export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { - constructor( + public constructor( targetLanguage: TargetLanguage, renderContext: RenderContext, - private readonly _jsOptions: OptionValues + private readonly _jsOptions: OptionValues< + typeof javaScriptPropTypesOptions + >, ) { super(targetLanguage, renderContext); } @@ -79,15 +54,15 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { legalizeName, upper ? firstUpperWordStyle : allLowerWordStyle, firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, acronyms, "", - isES3IdentifierStart + isES3IdentifierStart, ); } protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("types", s => this.nameStyle(s, true)); + return funPrefixNamer("types", (s) => this.nameStyle(s, true)); } protected namerForObjectProperty(): Namer { @@ -99,7 +74,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); + return funPrefixNamer("enum-cases", (s) => this.nameStyle(s, false)); } protected namedTypeToNameForTopLevel(type: Type): Type | undefined { @@ -111,38 +86,46 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { className: Name, p: ClassProperty, jsonName: string, - _assignedName: string | undefined + _assignedName: string | undefined, ): Name | undefined { // Ignore the assigned name return super.makeNameForProperty(c, className, p, jsonName, undefined); } - typeMapTypeFor(t: Type, required = true): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + private typeMapTypeFor(t: Type, required = true): Sourcelike { + if (["class", "object", "enum"].includes(t.kind)) { return ["_", this.nameForNamedType(t)]; } const match = matchType( t, - _anyType => "PropTypes.any", - _nullType => "PropTypes.any", - _boolType => "PropTypes.bool", - _integerType => "PropTypes.number", - _doubleType => "PropTypes.number", - _stringType => "PropTypes.string", - arrayType => ["PropTypes.arrayOf(", this.typeMapTypeFor(arrayType.items, false), ")"], - _classType => panic("Should already be handled."), - _mapType => "PropTypes.object", - _enumType => panic("Should already be handled."), - unionType => { - const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false) + (_anyType) => "PropTypes.any", + (_nullType) => "PropTypes.any", + (_boolType) => "PropTypes.bool", + (_integerType) => "PropTypes.number", + (_doubleType) => "PropTypes.number", + (_stringType) => "PropTypes.string", + (arrayType) => [ + "PropTypes.arrayOf(", + this.typeMapTypeFor(arrayType.items, false), + ")", + ], + (_classType) => panic("Should already be handled."), + (_mapType) => "PropTypes.object", + (_enumType) => panic("Should already be handled."), + (unionType) => { + const children = Array.from(unionType.getChildren()).map( + (type: Type) => this.typeMapTypeFor(type, false), ); - return ["PropTypes.oneOfType([", ...arrayIntercalate(", ", children), "])"]; + return [ + "PropTypes.oneOfType([", + ...arrayIntercalate(", ", children), + "])", + ]; }, - _transformedStringType => { + (_transformedStringType) => { return "PropTypes.string"; - } + }, ); if (required) { @@ -152,16 +135,19 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { return match; } - typeMapTypeForProperty(p: ClassProperty): Sourcelike { + private typeMapTypeForProperty(p: ClassProperty): Sourcelike { return this.typeMapTypeFor(p.type); } - private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { + private importStatement( + lhs: Sourcelike, + moduleName: Sourcelike, + ): Sourcelike { if (this._jsOptions.moduleSystem) { return ["import ", lhs, " from ", moduleName, ";"]; - } else { - return ["const ", lhs, " = require(", moduleName, ");"]; } + + return ["const ", lhs, " = require(", moduleName, ");"]; } protected emitUsageComments(): void { @@ -178,13 +164,17 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { "", "MyComponent.propTypes = {", " input: MyShape", - "};" + "};", ], - "// " + { lineStart: "// " }, ); } - protected emitBlock(source: Sourcelike, end: Sourcelike, emit: () => void) { + protected emitBlock( + source: Sourcelike, + end: Sourcelike, + emit: () => void, + ): void { this.emitLine(source, "{"); this.indent(emit); this.emitLine("}", end); @@ -199,7 +189,13 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { if (this._jsOptions.moduleSystem) { this.emitLine("export const ", name, " = ", value, ";"); } else { - this.emitLine("module.exports = exports = { ", name, ": ", value, " };"); + this.emitLine( + "module.exports = exports = { ", + name, + ": ", + value, + " };", + ); } } @@ -212,15 +208,25 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { this.forEachEnum("none", (enumType, enumName) => { const options: Sourcelike = []; - this.forEachEnumCase(enumType, "none", (name: Name, _jsonName, _position) => { - options.push("'"); - options.push(name); - options.push("'"); - options.push(", "); - }); + this.forEachEnumCase( + enumType, + "none", + (name: Name, _jsonName, _position) => { + options.push("'"); + options.push(name); + options.push("'"); + options.push(", "); + }, + ); options.pop(); - this.emitLine(["const _", enumName, " = PropTypes.oneOfType([", ...options, "]);"]); + this.emitLine([ + "const _", + enumName, + " = PropTypes.oneOfType([", + ...options, + "]);", + ]); }); const order: number[] = []; @@ -238,28 +244,28 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { // pull out all names const source = mapValue[index]; - const names = source.filter(value => value as Name); + const names = source.filter((value) => value as Name); // must be behind all these names - for (let i = 0; i < names.length; i++) { - const depName = names[i]; + names.forEach((name) => { + const depName = name; // find this name's ordinal, if it has already been added - for (let j = 0; j < order.length; j++) { - const depIndex = order[j]; + order.forEach((orderItem) => { + const depIndex = orderItem; if (mapKey[depIndex] === depName) { // this is the index of the dependency, so make sure we come after it ordinal = Math.max(ordinal, depIndex + 1); } - } - } + }); + }); // insert index order.splice(ordinal, 0, index); }); // now emit ordered source - order.forEach(i => this.emitGatheredSource(mapValue[i])); + order.forEach((i) => this.emitGatheredSource(mapValue[i])); // now emit top levels this.forEachTopLevel("none", (type, name) => { @@ -269,7 +275,11 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { } else { if (type.kind === "array") { this.ensureBlankLine(); - this.emitExport(name, ["PropTypes.arrayOf(", this.typeMapTypeFor((type as any).items), ")"]); + this.emitExport(name, [ + "PropTypes.arrayOf(", + this.typeMapTypeFor((type as ArrayType).items), + ")", + ]); } else { this.ensureBlankLine(); this.emitExport(name, ["_", name]); @@ -278,12 +288,17 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { }); } - private emitObject(name: Name, t: ObjectType) { + private emitObject(name: Name, t: ObjectType): void { this.ensureBlankLine(); this.emitLine("_", name, " = PropTypes.shape({"); this.indent(() => { this.forEachClassProperty(t, "none", (_, jsonName, property) => { - this.emitLine(`"${utf16StringEscape(jsonName)}"`, ": ", this.typeMapTypeForProperty(property), ","); + this.emitLine( + `"${utf16StringEscape(jsonName)}"`, + ": ", + this.typeMapTypeForProperty(property), + ",", + ); }); }); this.emitLine("});"); @@ -291,7 +306,7 @@ export class JavaScriptPropTypesRenderer extends ConvenienceRenderer { protected emitSourceStructure(): void { if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); + this.emitComments(this.leadingComments); } else { this.emitUsageComments(); } diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts new file mode 100644 index 000000000..f17587d28 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/index.ts @@ -0,0 +1,5 @@ +export { + JavaScriptPropTypesTargetLanguage, + javaScriptPropTypesOptions, +} from "./language"; +export { JavaScriptPropTypesRenderer } from "./JavaScriptPropTypesRenderer"; diff --git a/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts new file mode 100644 index 000000000..9c9cb1ec5 --- /dev/null +++ b/packages/quicktype-core/src/language/JavaScriptPropTypes/language.ts @@ -0,0 +1,51 @@ +import type { RenderContext } from "../../Renderer"; +import { EnumOption, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { convertersOption } from "../../support/Converters"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { JavaScriptPropTypesRenderer } from "./JavaScriptPropTypesRenderer"; + +export const javaScriptPropTypesOptions = { + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + converters: convertersOption(), + moduleSystem: new EnumOption( + "module-system", + "Which module system to use", + { + "common-js": false, + es6: true, + } as const, + "es6", + ), +}; + +export const javaScriptPropTypesLanguageConfig = { + displayName: "JavaScript PropTypes", + names: ["javascript-prop-types"], + extension: "js", +} as const; + +export class JavaScriptPropTypesTargetLanguage extends TargetLanguage< + typeof javaScriptPropTypesLanguageConfig +> { + public constructor() { + super(javaScriptPropTypesLanguageConfig); + } + + public getOptions(): typeof javaScriptPropTypesOptions { + return javaScriptPropTypesOptions; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): JavaScriptPropTypesRenderer { + return new JavaScriptPropTypesRenderer( + this, + renderContext, + getOptionValues(javaScriptPropTypesOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts b/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts deleted file mode 100644 index c3f105010..000000000 --- a/packages/quicktype-core/src/language/JavaScriptUnicodeMaps.ts +++ /dev/null @@ -1,156 +0,0 @@ -// Taken from https://github.com/Microsoft/TypeScript - -function lookupInUnicodeMap(code: number, map: ReadonlyArray): boolean { - // Bail out quickly if it couldn't possibly be in the map. - if (code < map[0]) { - return false; - } - - // Perform binary search in one of the Unicode range maps - let lo = 0; - let hi: number = map.length; - let mid: number; - - while (lo + 1 < hi) { - mid = lo + (hi - lo) / 2; - // mid has to be even to catch a range's beginning - mid -= mid % 2; - if (map[mid] <= code && code <= map[mid + 1]) { - return true; - } - - if (code < map[mid]) { - hi = mid; - } else { - lo = mid + 2; - } - } - - return false; -} - -const enum CharacterCodes { - maxAsciiCharacter = 0x7f, - - _ = 0x5f, - $ = 0x24, - - _0 = 0x30, - _9 = 0x39, - - a = 0x61, - z = 0x7a, - - A = 0x41, - Z = 0x5a -} - -export function isES3IdentifierStart(ch: number): boolean { - return ( - (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || - (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || - ch === CharacterCodes.$ || - ch === CharacterCodes._ || - (ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierStart)) - ); -} - -export function isES3IdentifierPart(ch: number): boolean { - return ( - (ch >= CharacterCodes.A && ch <= CharacterCodes.Z) || - (ch >= CharacterCodes.a && ch <= CharacterCodes.z) || - (ch >= CharacterCodes._0 && ch <= CharacterCodes._9) || - ch === CharacterCodes.$ || - ch === CharacterCodes._ || - (ch > CharacterCodes.maxAsciiCharacter && lookupInUnicodeMap(ch, unicodeES3IdentifierPart)) - ); -} - -/* - As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers - IdentifierStart :: - Can contain Unicode 3.0.0 categories: - Uppercase letter (Lu), - Lowercase letter (Ll), - Titlecase letter (Lt), - Modifier letter (Lm), - Other letter (Lo), or - Letter number (Nl). - IdentifierPart :: = - Can contain IdentifierStart + Unicode 3.0.0 categories: - Non-spacing mark (Mn), - Combining spacing mark (Mc), - Decimal number (Nd), or - Connector punctuation (Pc). - Codepoint ranges for ES3 Identifiers are extracted from the Unicode 3.0.0 specification at: - http://www.unicode.org/Public/3.0-Update/UnicodeData-3.0.0.txt -*/ -const unicodeES3IdentifierStart = [ - 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, - 740, 750, 750, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, 1024, 1153, 1164, - 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, 1415, 1488, 1514, 1520, 1522, - 1569, 1594, 1600, 1610, 1649, 1747, 1749, 1749, 1765, 1766, 1786, 1788, 1808, 1808, 1810, 1836, 1920, 1957, 2309, - 2361, 2365, 2365, 2384, 2384, 2392, 2401, 2437, 2444, 2447, 2448, 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, - 2524, 2525, 2527, 2529, 2544, 2545, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, 2616, - 2617, 2649, 2652, 2654, 2654, 2674, 2676, 2693, 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, - 2741, 2745, 2749, 2749, 2768, 2768, 2784, 2784, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, - 2873, 2877, 2877, 2908, 2909, 2911, 2913, 2949, 2954, 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, - 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, 3125, 3129, 3168, - 3169, 3205, 3212, 3214, 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3294, 3294, 3296, 3297, 3333, 3340, 3342, 3344, - 3346, 3368, 3370, 3385, 3424, 3425, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3585, 3632, 3634, - 3635, 3648, 3654, 3713, 3714, 3716, 3716, 3719, 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, - 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3760, 3762, 3763, 3773, 3773, 3776, 3780, 3782, 3782, 3804, 3805, 3840, - 3840, 3904, 3911, 3913, 3946, 3976, 3979, 4096, 4129, 4131, 4135, 4137, 4138, 4176, 4181, 4256, 4293, 4304, 4342, - 4352, 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, - 4701, 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, - 4808, 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 5024, - 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6067, 6176, 6263, 6272, 6312, 7680, 7835, 7840, 7929, - 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, 8029, 8029, 8031, 8061, 8064, - 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, 8172, 8178, 8180, 8182, 8188, - 8319, 8319, 8450, 8450, 8455, 8455, 8458, 8467, 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, - 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, 12295, 12321, 12329, 12337, 12341, 12344, 12346, 12353, 12436, - 12445, 12446, 12449, 12538, 12540, 12542, 12549, 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, - 40960, 42124, 44032, 55203, 63744, 64045, 64256, 64262, 64275, 64279, 64285, 64285, 64287, 64296, 64298, 64310, - 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, 64433, 64467, 64829, 64848, 64911, 64914, 64967, - 65008, 65019, 65136, 65138, 65140, 65140, 65142, 65276, 65313, 65338, 65345, 65370, 65382, 65470, 65474, 65479, - 65482, 65487, 65490, 65495, 65498, 65500 -]; -const unicodeES3IdentifierPart = [ - 170, 170, 181, 181, 186, 186, 192, 214, 216, 246, 248, 543, 546, 563, 592, 685, 688, 696, 699, 705, 720, 721, 736, - 740, 750, 750, 768, 846, 864, 866, 890, 890, 902, 902, 904, 906, 908, 908, 910, 929, 931, 974, 976, 983, 986, 1011, - 1024, 1153, 1155, 1158, 1164, 1220, 1223, 1224, 1227, 1228, 1232, 1269, 1272, 1273, 1329, 1366, 1369, 1369, 1377, - 1415, 1425, 1441, 1443, 1465, 1467, 1469, 1471, 1471, 1473, 1474, 1476, 1476, 1488, 1514, 1520, 1522, 1569, 1594, - 1600, 1621, 1632, 1641, 1648, 1747, 1749, 1756, 1759, 1768, 1770, 1773, 1776, 1788, 1808, 1836, 1840, 1866, 1920, - 1968, 2305, 2307, 2309, 2361, 2364, 2381, 2384, 2388, 2392, 2403, 2406, 2415, 2433, 2435, 2437, 2444, 2447, 2448, - 2451, 2472, 2474, 2480, 2482, 2482, 2486, 2489, 2492, 2492, 2494, 2500, 2503, 2504, 2507, 2509, 2519, 2519, 2524, - 2525, 2527, 2531, 2534, 2545, 2562, 2562, 2565, 2570, 2575, 2576, 2579, 2600, 2602, 2608, 2610, 2611, 2613, 2614, - 2616, 2617, 2620, 2620, 2622, 2626, 2631, 2632, 2635, 2637, 2649, 2652, 2654, 2654, 2662, 2676, 2689, 2691, 2693, - 2699, 2701, 2701, 2703, 2705, 2707, 2728, 2730, 2736, 2738, 2739, 2741, 2745, 2748, 2757, 2759, 2761, 2763, 2765, - 2768, 2768, 2784, 2784, 2790, 2799, 2817, 2819, 2821, 2828, 2831, 2832, 2835, 2856, 2858, 2864, 2866, 2867, 2870, - 2873, 2876, 2883, 2887, 2888, 2891, 2893, 2902, 2903, 2908, 2909, 2911, 2913, 2918, 2927, 2946, 2947, 2949, 2954, - 2958, 2960, 2962, 2965, 2969, 2970, 2972, 2972, 2974, 2975, 2979, 2980, 2984, 2986, 2990, 2997, 2999, 3001, 3006, - 3010, 3014, 3016, 3018, 3021, 3031, 3031, 3047, 3055, 3073, 3075, 3077, 3084, 3086, 3088, 3090, 3112, 3114, 3123, - 3125, 3129, 3134, 3140, 3142, 3144, 3146, 3149, 3157, 3158, 3168, 3169, 3174, 3183, 3202, 3203, 3205, 3212, 3214, - 3216, 3218, 3240, 3242, 3251, 3253, 3257, 3262, 3268, 3270, 3272, 3274, 3277, 3285, 3286, 3294, 3294, 3296, 3297, - 3302, 3311, 3330, 3331, 3333, 3340, 3342, 3344, 3346, 3368, 3370, 3385, 3390, 3395, 3398, 3400, 3402, 3405, 3415, - 3415, 3424, 3425, 3430, 3439, 3458, 3459, 3461, 3478, 3482, 3505, 3507, 3515, 3517, 3517, 3520, 3526, 3530, 3530, - 3535, 3540, 3542, 3542, 3544, 3551, 3570, 3571, 3585, 3642, 3648, 3662, 3664, 3673, 3713, 3714, 3716, 3716, 3719, - 3720, 3722, 3722, 3725, 3725, 3732, 3735, 3737, 3743, 3745, 3747, 3749, 3749, 3751, 3751, 3754, 3755, 3757, 3769, - 3771, 3773, 3776, 3780, 3782, 3782, 3784, 3789, 3792, 3801, 3804, 3805, 3840, 3840, 3864, 3865, 3872, 3881, 3893, - 3893, 3895, 3895, 3897, 3897, 3902, 3911, 3913, 3946, 3953, 3972, 3974, 3979, 3984, 3991, 3993, 4028, 4038, 4038, - 4096, 4129, 4131, 4135, 4137, 4138, 4140, 4146, 4150, 4153, 4160, 4169, 4176, 4185, 4256, 4293, 4304, 4342, 4352, - 4441, 4447, 4514, 4520, 4601, 4608, 4614, 4616, 4678, 4680, 4680, 4682, 4685, 4688, 4694, 4696, 4696, 4698, 4701, - 4704, 4742, 4744, 4744, 4746, 4749, 4752, 4782, 4784, 4784, 4786, 4789, 4792, 4798, 4800, 4800, 4802, 4805, 4808, - 4814, 4816, 4822, 4824, 4846, 4848, 4878, 4880, 4880, 4882, 4885, 4888, 4894, 4896, 4934, 4936, 4954, 4969, 4977, - 5024, 5108, 5121, 5740, 5743, 5750, 5761, 5786, 5792, 5866, 6016, 6099, 6112, 6121, 6160, 6169, 6176, 6263, 6272, - 6313, 7680, 7835, 7840, 7929, 7936, 7957, 7960, 7965, 7968, 8005, 8008, 8013, 8016, 8023, 8025, 8025, 8027, 8027, - 8029, 8029, 8031, 8061, 8064, 8116, 8118, 8124, 8126, 8126, 8130, 8132, 8134, 8140, 8144, 8147, 8150, 8155, 8160, - 8172, 8178, 8180, 8182, 8188, 8255, 8256, 8319, 8319, 8400, 8412, 8417, 8417, 8450, 8450, 8455, 8455, 8458, 8467, - 8469, 8469, 8473, 8477, 8484, 8484, 8486, 8486, 8488, 8488, 8490, 8493, 8495, 8497, 8499, 8505, 8544, 8579, 12293, - 12295, 12321, 12335, 12337, 12341, 12344, 12346, 12353, 12436, 12441, 12442, 12445, 12446, 12449, 12542, 12549, - 12588, 12593, 12686, 12704, 12727, 13312, 19893, 19968, 40869, 40960, 42124, 44032, 55203, 63744, 64045, 64256, - 64262, 64275, 64279, 64285, 64296, 64298, 64310, 64312, 64316, 64318, 64318, 64320, 64321, 64323, 64324, 64326, - 64433, 64467, 64829, 64848, 64911, 64914, 64967, 65008, 65019, 65056, 65059, 65075, 65076, 65101, 65103, 65136, - 65138, 65140, 65140, 65142, 65276, 65296, 65305, 65313, 65338, 65343, 65343, 65345, 65370, 65381, 65470, 65474, - 65479, 65482, 65487, 65490, 65495, 65498, 65500 -]; diff --git a/packages/quicktype-core/src/language/Kotlin.ts b/packages/quicktype-core/src/language/Kotlin.ts deleted file mode 100644 index 3b08e8a3f..000000000 --- a/packages/quicktype-core/src/language/Kotlin.ts +++ /dev/null @@ -1,1110 +0,0 @@ -import { iterableSome, arrayIntercalate } from "collection-utils"; - -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - camelCase, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - intToHex, - isDigit, - isLetterOrUnderscore, - isNumeric, - isPrintable, - legalizeCharacters, - splitIntoWords, - utf32ConcatMap -} from "../support/Strings"; -import { assertNever, mustNotHappen } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayType, - ClassProperty, - ClassType, - EnumType, - MapType, - ObjectType, - PrimitiveType, - Type, - UnionType -} from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { RenderContext } from "../Renderer"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; - -export enum Framework { - None, - Jackson, - Klaxon, - KotlinX -} - -export const kotlinOptions = { - framework: new EnumOption( - "framework", - "Serialization framework", - [ - ["just-types", Framework.None], - ["jackson", Framework.Jackson], - ["klaxon", Framework.Klaxon], - ["kotlinx", Framework.KotlinX] - ], - "klaxon" - ), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") -}; - -export class KotlinTargetLanguage extends TargetLanguage { - constructor() { - super("Kotlin", ["kotlin"], "kt"); - } - - protected getOptions(): Option[] { - return [kotlinOptions.framework, kotlinOptions.acronymStyle, kotlinOptions.packageName]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { - const options = getOptionValues(kotlinOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new KotlinRenderer(this, renderContext, options); - case Framework.Jackson: - return new KotlinJacksonRenderer(this, renderContext, options); - case Framework.Klaxon: - return new KotlinKlaxonRenderer(this, renderContext, options); - case Framework.KotlinX: - return new KotlinXRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } - } -} - -const keywords = [ - "package", - "as", - "typealias", - "class", - "this", - "super", - "val", - "var", - "fun", - "for", - "null", - "true", - "false", - "is", - "in", - "throw", - "return", - "break", - "continue", - "object", - "if", - "try", - "else", - "while", - "do", - "when", - "interface", - "typeof", - "klaxon", - "toJson", - "Any", - "Boolean", - "Double", - "Float", - "Long", - "Int", - "Short", - "System", - "Byte", - "String", - "Array", - "List", - "Map", - "Enum", - "Class", - "JsonObject", - "JsonValue", - "Converter", - "Klaxon" -]; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function kotlinNameStyle( - isUpper: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - "", - isStartCharacter - ); -} - -function unicodeEscape(codePoint: number): string { - return "\\u" + intToHex(codePoint, 4); -} - -const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -function stringEscape(s: string): string { - // "$this" is a template string in Kotlin so we have to escape $ - return _stringEscape(s).replace(/\$/g, "\\$"); -} - -export class KotlinRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_o: ObjectType, _classNamed: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: false }; - } - - protected topLevelNameStyle(rawName: string): string { - return kotlinNameStyle(true, rawName); - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); - } - - protected namerForObjectProperty(): Namer { - return funPrefixNamer("lower", s => kotlinNameStyle(false, s, acronymStyle(this._kotlinOptions.acronymStyle))); - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("upper", s => kotlinNameStyle(true, s) + "Value"); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("upper", s => kotlinNameStyle(true, s, acronymStyle(this._kotlinOptions.acronymStyle))); - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); - } - - protected emitBlock(line: Sourcelike, f: () => void, delimiter: "curly" | "paren" | "lambda" = "curly"): void { - const [open, close] = delimiter === "curly" ? ["{", "}"] : delimiter === "paren" ? ["(", ")"] : ["{", "})"]; - this.emitLine(line, " ", open); - this.indent(f); - this.emitLine(close); - } - - protected anySourceType(optional: string): Sourcelike { - return ["Any", optional]; - } - - // (asarazan): I've broken out the following two functions - // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, withIssues = false, _noOptional = false): Sourcelike { - return ["List<", this.kotlinType(arrayType.items, withIssues), ">"]; - } - - protected mapType(mapType: MapType, withIssues = false, _noOptional = false): Sourcelike { - return ["Map"]; - } - - protected kotlinType(t: Type, withIssues = false, noOptional = false): Sourcelike { - const optional = noOptional ? "" : "?"; - return matchType( - t, - _anyType => { - return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(optional)); - }, - _nullType => { - return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(optional)); - }, - _boolType => "Boolean", - _integerType => "Long", - _doubleType => "Double", - _stringType => "String", - arrayType => this.arrayType(arrayType, withIssues), - classType => this.nameForNamedType(classType), - mapType => this.mapType(mapType, withIssues), - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return [this.kotlinType(nullable, withIssues), optional]; - return this.nameForNamedType(unionType); - } - ); - } - - protected emitUsageHeader(): void { - // To be overridden - } - - protected emitHeader(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else { - this.emitUsageHeader(); - } - - this.ensureBlankLine(); - this.emitLine("package ", this._kotlinOptions.packageName); - this.ensureBlankLine(); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitLine(["typealias ", name, " = ArrayList<", elementType, ">"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - this.emitLine(["typealias ", name, " = HashMap"]); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitClassAnnotations(c, className); - this.emitLine("class ", className, "()"); - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - if (c.getProperties().size === 0) { - this.emitEmptyClassDefinition(c, className); - return; - } - - const kotlinType = (p: ClassProperty) => { - if (p.isOptional) { - return [this.kotlinType(p.type, true, true), "?"]; - } else { - return this.kotlinType(p.type, true); - } - }; - - this.emitDescription(this.descriptionForType(c)); - this.emitClassAnnotations(c, className); - this.emitLine("data class ", className, " ("); - this.indent(() => { - let count = c.getProperties().size; - let first = true; - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; - const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; - const last = --count === 0; - let meta: Array<() => void> = []; - - const description = this.descriptionForClassProperty(c, jsonName); - if (description !== undefined) { - meta.push(() => this.emitDescription(description)); - } - - this.renameAttribute(name, jsonName, !nullableOrOptional, meta); - - if (meta.length > 0 && !first) { - this.ensureBlankLine(); - } - - for (const emit of meta) { - emit(); - } - - this.emitLine("val ", name, ": ", kotlinType(p), nullableOrOptional ? " = null" : "", last ? "" : ","); - - if (meta.length > 0 && !last) { - this.ensureBlankLine(); - } - - first = false; - }); - }); - - this.emitClassDefinitionMethods(c, className); - } - - protected emitClassDefinitionMethods(_c: ClassType, _className: Name) { - this.emitLine(")"); - } - - protected emitClassAnnotations(_c: Type, _className: Name) { - // to be overridden - } - - protected renameAttribute(_name: Name, _jsonName: string, _required: boolean, _meta: Array<() => void>) { - // to be overridden - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock(["enum class ", enumName], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", name => { - this.emitLine(name, --count === 0 ? "" : ","); - }); - }); - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - this.emitClassAnnotations(u, unionName); - this.emitBlock(["sealed class ", unionName], () => { - { - let table: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - table.push([ - ["class ", name, "(val value: ", this.kotlinType(t), ")"], - [" : ", unionName, "()"] - ]); - }); - if (maybeNull !== null) { - table.push([ - ["class ", this.nameForUnionMember(u, maybeNull), "()"], - [" : ", unionName, "()"] - ]); - } - this.emitTable(table); - } - - this.emitUnionDefinitionMethods(u, nonNulls, maybeNull, unionName); - }); - } - - protected emitUnionDefinitionMethods( - _u: UnionType, - _nonNulls: ReadonlySet, - _maybeNull: PrimitiveType | null, - _unionName: Name - ) { - // to be overridden - } - - protected emitSourceStructure(): void { - this.emitHeader(); - - // Top-level arrays, maps - this.forEachTopLevel("leading", (t, name) => { - if (t instanceof ArrayType) { - this.emitTopLevelArray(t, name); - } else if (t instanceof MapType) { - this.emitTopLevelMap(t, name); - } - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - } -} - -export class KotlinKlaxonRenderer extends KotlinRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext, _kotlinOptions); - } - - private unionMemberFromJsonValue(t: Type, e: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => [e, ".inside"], - _nullType => "null", - _boolType => [e, ".boolean"], - _integerType => ["(", e, ".int?.toLong() ?: ", e, ".longValue)"], - _doubleType => [e, ".double"], - _stringType => [e, ".string"], - arrayType => [e, ".array?.let { klaxon.parseFromJsonArray<", this.kotlinType(arrayType.items), ">(it) }"], - _classType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], - _mapType => [e, ".obj?.let { klaxon.parseFromJsonObject<", this.kotlinType(t), ">(it) }"], - enumType => [e, ".string?.let { ", this.kotlinType(enumType), ".fromValue(it) }"], - _unionType => mustNotHappen() - ); - } - - private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => "is Any", - _nullType => "null", - _boolType => "is Boolean", - _integerType => "is Int, is Long", - _doubleType => "is Double", - _stringType => "is String", - _arrayType => "is JsonArray<*>", - // These could be stricter, but for now we don't allow maps - // and objects in the same union - _classType => "is JsonObject", - _mapType => "is JsonObject", - // This could be stricter, but for now we don't allow strings - // and enums in the same union - _enumType => "is String", - _unionType => mustNotHappen() - ); - } - - protected emitUsageHeader(): void { - this.emitLine("// To parse the JSON, install Klaxon and do:"); - this.emitLine("//"); - this.forEachTopLevel("none", (_, name) => { - this.emitLine("// val ", modifySource(camelCase, name), " = ", name, ".fromJson(jsonString)"); - }); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import com.beust.klaxon.*"); - - const hasUnions = iterableSome( - this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null - ); - const hasEmptyObjects = iterableSome( - this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0 - ); - if (hasUnions || this.haveEnums || hasEmptyObjects) { - this.emitGenericConverter(); - } - - let converters: Sourcelike[][] = []; - if (hasEmptyObjects) { - converters.push([[".convert(JsonObject::class,"], [" { it.obj!! },"], [" { it.toJsonString() })"]]); - } - this.forEachEnum("none", (_, name) => { - converters.push([ - [".convert(", name, "::class,"], - [" { ", name, ".fromValue(it.string!!) },"], - [' { "\\"${it.value}\\"" })'] - ]); - }); - this.forEachUnion("none", (_, name) => { - converters.push([ - [".convert(", name, "::class,"], - [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"] - ]); - }); - - this.ensureBlankLine(); - this.emitLine("private val klaxon = Klaxon()"); - if (converters.length > 0) { - this.indent(() => this.emitTable(converters)); - } - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitBlock( - ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], - () => { - this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine( - "public fun fromJson(json: String) = ", - name, - "(klaxon.parseArray<", - elementType, - ">(json)!!)" - ); - }); - } - ); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - this.emitBlock( - [ - "class ", - name, - "(elements: Map) : HashMap(elements)" - ], - () => { - this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitBlock( - ["public fun fromJson(json: String) = ", name], - () => { - this.emitLine( - "klaxon.parseJsonObject(java.io.StringReader(json)) as Map" - ); - }, - "paren" - ); - }); - } - ); - } - - private klaxonRenameAttribute(propName: Name, jsonName: string, ignore = false): Sourcelike | undefined { - const escapedName = stringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - const properties: Sourcelike[] = []; - if (namesDiffer) { - properties.push(['name = "', escapedName, '"']); - } - if (ignore) { - properties.push("ignored = true"); - } - return properties.length === 0 ? undefined : ["@Json(", arrayIntercalate(", ", properties), ")"]; - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - - this.emitLine("typealias ", className, " = JsonObject"); - } - - protected emitClassDefinitionMethods(c: ClassType, className: Name) { - const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); - if (isTopLevel) { - this.emitBlock(")", () => { - this.emitLine("public fun toJson() = klaxon.toJsonString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("public fun fromJson(json: String) = klaxon.parse<", className, ">(json)"); - }); - }); - } else { - this.emitLine(")"); - } - } - - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { - const rename = this.klaxonRenameAttribute(name, jsonName); - if (rename !== undefined) { - meta.push(() => this.emitLine(rename)); - } - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, json) => { - this.emitLine(name, `("${stringEscape(json)}")`, --count === 0 ? ";" : ","); - }); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitBlock(["public fun fromValue(value: String): ", enumName, " = when (value)"], () => { - let table: Sourcelike[][] = []; - this.forEachEnumCase(e, "none", (name, json) => { - table.push([[`"${stringEscape(json)}"`], [" -> ", name]]); - }); - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - }); - }); - } - - private emitGenericConverter(): void { - this.ensureBlankLine(); - this.emitLine( - "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =" - ); - this.indent(() => { - this.emitLine("this.converter(object: Converter {"); - this.indent(() => { - this.emitLine(`@Suppress("UNCHECKED_CAST")`); - this.emitTable([ - ["override fun toJson(value: Any)", " = toJson(value as T)"], - ["override fun fromJson(jv: JsonValue)", " = fromJson(jv) as Any"], - [ - "override fun canConvert(cls: Class<*>)", - " = cls == k.java || (isUnion && cls.superclass == k.java)" - ] - ]); - }); - this.emitLine("})"); - }); - } - - protected emitUnionDefinitionMethods( - u: UnionType, - nonNulls: ReadonlySet, - maybeNull: PrimitiveType | null, - unionName: Name - ) { - this.ensureBlankLine(); - this.emitLine("public fun toJson(): String = klaxon.toJsonString(when (this) {"); - this.indent(() => { - let toJsonTable: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, name => { - toJsonTable.push([["is ", name], [" -> this.value"]]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [' -> "null"']]); - } - this.emitTable(toJsonTable); - }); - this.emitLine("})"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("public fun fromJson(jv: JsonValue): ", unionName, " = when (jv.inside) {"); - this.indent(() => { - let table: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - table.push([ - [this.unionMemberJsonValueGuard(t, "jv.inside")], - [" -> ", name, "(", this.unionMemberFromJsonValue(t, "jv"), "!!)"] - ]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - table.push([[this.unionMemberJsonValueGuard(maybeNull, "jv.inside")], [" -> ", name, "()"]]); - } - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - this.emitLine("}"); - }); - } -} - -export class KotlinJacksonRenderer extends KotlinRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext, _kotlinOptions); - } - - private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => "is Any", - _nullType => "null", - _boolType => "is BooleanNode", - _integerType => "is IntNode, is LongNode", - _doubleType => "is DoubleNode", - _stringType => "is TextNode", - _arrayType => "is ArrayNode", - // These could be stricter, but for now we don't allow maps - // and objects in the same union - _classType => "is ObjectNode", - _mapType => "is ObjectNode", - // This could be stricter, but for now we don't allow strings - // and enums in the same union - _enumType => "is TextNode", - _unionType => mustNotHappen() - ); - } - - protected emitUsageHeader(): void { - this.emitLine("// To parse the JSON, install jackson-module-kotlin and do:"); - this.emitLine("//"); - this.forEachTopLevel("none", (_, name) => { - this.emitLine("// val ", modifySource(camelCase, name), " = ", name, ".fromJson(jsonString)"); - }); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitMultiline(`import com.fasterxml.jackson.annotation.* -import com.fasterxml.jackson.core.* -import com.fasterxml.jackson.databind.* -import com.fasterxml.jackson.databind.deser.std.StdDeserializer -import com.fasterxml.jackson.databind.module.SimpleModule -import com.fasterxml.jackson.databind.node.* -import com.fasterxml.jackson.databind.ser.std.StdSerializer -import com.fasterxml.jackson.module.kotlin.*`); - - const hasUnions = iterableSome( - this.typeGraph.allNamedTypes(), - t => t instanceof UnionType && nullableFromUnion(t) === null - ); - const hasEmptyObjects = iterableSome( - this.typeGraph.allNamedTypes(), - c => c instanceof ClassType && c.getProperties().size === 0 - ); - if (hasUnions || this.haveEnums || hasEmptyObjects) { - this.emitGenericConverter(); - } - - let converters: Sourcelike[][] = []; - // if (hasEmptyObjects) { - // converters.push([["convert(JsonNode::class,"], [" { it },"], [" { writeValueAsString(it) })"]]); - // } - this.forEachEnum("none", (_, name) => { - converters.push([ - ["convert(", name, "::class,"], - [" { ", name, ".fromValue(it.asText()) },"], - [' { "\\"${it.value}\\"" })'] - ]); - }); - this.forEachUnion("none", (_, name) => { - converters.push([ - ["convert(", name, "::class,"], - [" { ", name, ".fromJson(it) },"], - [" { it.toJson() }, true)"] - ]); - }); - - this.ensureBlankLine(); - this.emitLine("val mapper = jacksonObjectMapper().apply {"); - this.indent(() => { - this.emitLine("propertyNamingStrategy = PropertyNamingStrategy.LOWER_CAMEL_CASE"); - this.emitLine("setSerializationInclusion(JsonInclude.Include.NON_NULL)"); - }); - - if (converters.length > 0) { - this.indent(() => this.emitTable(converters)); - } - - this.emitLine("}"); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitBlock( - ["class ", name, "(elements: Collection<", elementType, ">) : ArrayList<", elementType, ">(elements)"], - () => { - this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); - }); - } - ); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - this.emitBlock( - [ - "class ", - name, - "(elements: Map) : HashMap(elements)" - ], - () => { - this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(json: String) = mapper.readValue<", name, ">(json)"); - }); - } - ); - } - - private jacksonRenameAttribute( - propName: Name, - jsonName: string, - required: boolean, - ignore = false - ): Sourcelike | undefined { - const escapedName = stringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - const properties: Sourcelike[] = []; - const isPrefixBool = jsonName.startsWith("is"); // https://github.com/FasterXML/jackson-module-kotlin/issues/80 - const propertyOpts: Sourcelike[] = []; - - if (namesDiffer || isPrefixBool) { - propertyOpts.push('"' + escapedName + '"'); - } - if (required) { - propertyOpts.push("required=true"); - } - - if (propertyOpts.length > 0) { - properties.push(["@get:JsonProperty(", arrayIntercalate(", ", propertyOpts), ")"]); - properties.push(["@field:JsonProperty(", arrayIntercalate(", ", propertyOpts), ")"]); - } - - if (ignore) { - properties.push("@get:JsonIgnore"); - properties.push("@field:JsonIgnore"); - } - return properties.length === 0 ? undefined : properties; - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - - this.emitLine("typealias ", className, " = JsonNode"); - } - - protected emitClassDefinitionMethods(c: ClassType, className: Name) { - const isTopLevel = iterableSome(this.topLevels, ([_, top]) => top === c); - if (isTopLevel) { - this.emitBlock(")", () => { - this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(json: String) = mapper.readValue<", className, ">(json)"); - }); - }); - } else { - this.emitLine(")"); - } - } - - protected renameAttribute(name: Name, jsonName: string, required: boolean, meta: Array<() => void>) { - const rename = this.jacksonRenameAttribute(name, jsonName, required); - if (rename !== undefined) { - meta.push(() => this.emitLine(rename)); - } - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, json) => { - this.emitLine(name, `("${stringEscape(json)}")`, --count === 0 ? ";" : ","); - }); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitBlock(["fun fromValue(value: String): ", enumName, " = when (value)"], () => { - let table: Sourcelike[][] = []; - this.forEachEnumCase(e, "none", (name, json) => { - table.push([[`"${stringEscape(json)}"`], [" -> ", name]]); - }); - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - }); - }); - } - - private emitGenericConverter(): void { - this.ensureBlankLine(); - this.emitMultiline(` -@Suppress("UNCHECKED_CAST") -private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonNode) -> T, toJson: (T) -> String, isUnion: Boolean = false) = registerModule(SimpleModule().apply { - addSerializer(k.java as Class, object : StdSerializer(k.java as Class) { - override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) = gen.writeRawValue(toJson(value)) - }) - addDeserializer(k.java as Class, object : StdDeserializer(k.java as Class) { - override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = fromJson(p.readValueAsTree()) - }) -})`); - } - - protected emitUnionDefinitionMethods( - u: UnionType, - nonNulls: ReadonlySet, - maybeNull: PrimitiveType | null, - unionName: Name - ) { - this.ensureBlankLine(); - this.emitLine("fun toJson(): String = mapper.writeValueAsString(when (this) {"); - this.indent(() => { - let toJsonTable: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, name => { - toJsonTable.push([["is ", name], [" -> this.value"]]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - toJsonTable.push([["is ", name], [' -> "null"']]); - } - this.emitTable(toJsonTable); - }); - this.emitLine("})"); - this.ensureBlankLine(); - this.emitBlock("companion object", () => { - this.emitLine("fun fromJson(jn: JsonNode): ", unionName, " = when (jn) {"); - this.indent(() => { - let table: Sourcelike[][] = []; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - table.push([[this.unionMemberJsonValueGuard(t, "jn")], [" -> ", name, "(mapper.treeToValue(jn))"]]); - }); - if (maybeNull !== null) { - const name = this.nameForUnionMember(u, maybeNull); - table.push([[this.unionMemberJsonValueGuard(maybeNull, "jn")], [" -> ", name, "()"]]); - } - table.push([["else"], [" -> throw IllegalArgumentException()"]]); - this.emitTable(table); - }); - this.emitLine("}"); - }); - } -} - -/** - * Currently supports simple classes, enums, and TS string unions (which are also enums). - * TODO: Union, Any, Top Level Array, Top Level Map - */ -export class KotlinXRenderer extends KotlinRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - _kotlinOptions: OptionValues - ) { - super(targetLanguage, renderContext, _kotlinOptions); - } - - protected anySourceType(optional: string): Sourcelike { - return ["JsonElement", optional]; - } - - protected arrayType(arrayType: ArrayType, withIssues = false, noOptional = false): Sourcelike { - const valType = this.kotlinType(arrayType.items, withIssues, true); - const name = this.sourcelikeToString(valType); - if (name === "JsonObject" || name === "JsonElement") { - return "JsonArray"; - } - return super.arrayType(arrayType, withIssues, noOptional); - } - - protected mapType(mapType: MapType, withIssues = false, noOptional = false): Sourcelike { - const valType = this.kotlinType(mapType.values, withIssues, true); - const name = this.sourcelikeToString(valType); - if (name === "JsonObject" || name === "JsonElement") { - return "JsonObject"; - } - return super.mapType(mapType, withIssues, noOptional); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.kotlinType(t.values); - if (elementType === "JsonObject") { - this.emitLine(["typealias ", name, " = JsonObject"]); - } else { - super.emitTopLevelMap(t, name); - } - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.kotlinType(t.items); - this.emitLine(["typealias ", name, " = JsonArray<", elementType, ">"]); - } - - protected emitUsageHeader(): void { - this.emitLine("// To parse the JSON, install kotlin's serialization plugin and do:"); - this.emitLine("//"); - const table: Sourcelike[][] = []; - table.push(["// val ", "json", " = Json { allowStructuredMapKeys = true }"]); - this.forEachTopLevel("none", (_, name) => { - table.push([ - "// val ", - modifySource(camelCase, name), - ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)` - ]); - }); - this.emitTable(table); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import kotlinx.serialization.*"); - this.emitLine("import kotlinx.serialization.json.*"); - this.emitLine("import kotlinx.serialization.descriptors.*"); - this.emitLine("import kotlinx.serialization.encoding.*"); - } - - protected emitClassAnnotations(_c: Type, _className: Name) { - this.emitLine("@Serializable"); - } - - protected renameAttribute(name: Name, jsonName: string, _required: boolean, meta: Array<() => void>) { - const rename = this._rename(name, jsonName); - if (rename !== undefined) { - meta.push(() => this.emitLine(rename)); - } - } - - private _rename(propName: Name, jsonName: string): Sourcelike | undefined { - const escapedName = stringEscape(jsonName); - const namesDiffer = this.sourcelikeToString(propName) !== escapedName; - if (namesDiffer) { - return ['@SerialName("', escapedName, '")']; - } - return undefined; - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitLine(["@Serializable"]); - this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, json) => { - const jsonEnum = stringEscape(json); - this.emitLine(`@SerialName("${jsonEnum}") `, name, `("${jsonEnum}")`, --count === 0 ? ";" : ","); - }); - }); - } -} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts new file mode 100644 index 000000000..3401ed1fe --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinJacksonRenderer.ts @@ -0,0 +1,379 @@ +import { arrayIntercalate, iterableSome } from "collection-utils"; + +import type { Name } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase } from "../../support/Strings"; +import { mustNotHappen } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + type ArrayType, + ClassType, + type EnumType, + type MapType, + type PrimitiveType, + type Type, + UnionType, +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../Type/TypeUtils"; + +import { KotlinRenderer } from "./KotlinRenderer"; +import type { kotlinOptions } from "./language"; +import { stringEscape } from "./utils"; + +export class KotlinJacksonRenderer extends KotlinRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + _kotlinOptions: OptionValues, + ) { + super(targetLanguage, renderContext, _kotlinOptions); + } + + private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { + return matchType( + t, + (_anyType) => "is Any", + (_nullType) => "null", + (_boolType) => "is BooleanNode", + (_integerType) => "is IntNode, is LongNode", + (_doubleType) => "is DoubleNode", + (_stringType) => "is TextNode", + (_arrayType) => "is ArrayNode", + // These could be stricter, but for now we don't allow maps + // and objects in the same union + (_classType) => "is ObjectNode", + (_mapType) => "is ObjectNode", + // This could be stricter, but for now we don't allow strings + // and enums in the same union + (_enumType) => "is TextNode", + (_unionType) => mustNotHappen(), + ); + } + + protected emitUsageHeader(): void { + this.emitLine( + "// To parse the JSON, install jackson-module-kotlin and do:", + ); + this.emitLine("//"); + this.forEachTopLevel("none", (_, name) => { + this.emitLine( + "// val ", + modifySource(camelCase, name), + " = ", + name, + ".fromJson(jsonString)", + ); + }); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitMultiline(`import com.fasterxml.jackson.annotation.* +import com.fasterxml.jackson.core.* +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.databind.deser.std.StdDeserializer +import com.fasterxml.jackson.databind.module.SimpleModule +import com.fasterxml.jackson.databind.node.* +import com.fasterxml.jackson.databind.ser.std.StdSerializer +import com.fasterxml.jackson.module.kotlin.*`); + + const hasUnions = iterableSome( + this.typeGraph.allNamedTypes(), + (t) => t instanceof UnionType && nullableFromUnion(t) === null, + ); + const hasEmptyObjects = iterableSome( + this.typeGraph.allNamedTypes(), + (c) => c instanceof ClassType && c.getProperties().size === 0, + ); + if (hasUnions || this.haveEnums || hasEmptyObjects) { + this.emitGenericConverter(); + } + + const converters: Sourcelike[][] = []; + // if (hasEmptyObjects) { + // converters.push([["convert(JsonNode::class,"], [" { it },"], [" { writeValueAsString(it) })"]]); + // } + this.forEachEnum("none", (_, name) => { + converters.push([ + ["convert(", name, "::class,"], + [" { ", name, ".fromValue(it.asText()) },"], + [' { "\\"${it.value}\\"" })'], + ]); + }); + this.forEachUnion("none", (_, name) => { + converters.push([ + ["convert(", name, "::class,"], + [" { ", name, ".fromJson(it) },"], + [" { it.toJson() }, true)"], + ]); + }); + + this.ensureBlankLine(); + this.emitLine("val mapper = jacksonObjectMapper().apply {"); + this.indent(() => { + this.emitLine( + "propertyNamingStrategy = PropertyNamingStrategy.LOWER_CAMEL_CASE", + ); + this.emitLine( + "setSerializationInclusion(JsonInclude.Include.NON_NULL)", + ); + }); + + if (converters.length > 0) { + this.indent(() => this.emitTable(converters)); + } + + this.emitLine("}"); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitBlock( + [ + "class ", + name, + "(elements: Collection<", + elementType, + ">) : ArrayList<", + elementType, + ">(elements)", + ], + () => { + this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "fun fromJson(json: String) = mapper.readValue<", + name, + ">(json)", + ); + }); + }, + ); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + this.emitBlock( + [ + "class ", + name, + "(elements: Map) : HashMap(elements)", + ], + () => { + this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "fun fromJson(json: String) = mapper.readValue<", + name, + ">(json)", + ); + }); + }, + ); + } + + private jacksonRenameAttribute( + propName: Name, + jsonName: string, + required: boolean, + ignore = false, + ): Sourcelike | undefined { + const escapedName = stringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + const properties: Sourcelike[] = []; + const isPrefixBool = jsonName.startsWith("is"); // https://github.com/FasterXML/jackson-module-kotlin/issues/80 + const propertyOpts: Sourcelike[] = []; + + if (namesDiffer || isPrefixBool) { + propertyOpts.push(`"${escapedName}"`); + } + + if (required) { + propertyOpts.push("required=true"); + } + + if (propertyOpts.length > 0) { + properties.push([ + "@get:JsonProperty(", + arrayIntercalate(", ", propertyOpts), + ")", + ]); + properties.push([ + "@field:JsonProperty(", + arrayIntercalate(", ", propertyOpts), + ")", + ]); + } + + if (ignore) { + properties.push("@get:JsonIgnore"); + properties.push("@field:JsonIgnore"); + } + + return properties.length === 0 ? undefined : properties; + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + + this.emitLine("typealias ", className, " = JsonNode"); + } + + protected emitClassDefinitionMethods(c: ClassType, className: Name): void { + const isTopLevel = iterableSome( + this.topLevels, + ([_, top]) => top === c, + ); + if (isTopLevel) { + this.emitBlock(")", () => { + this.emitLine("fun toJson() = mapper.writeValueAsString(this)"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "fun fromJson(json: String) = mapper.readValue<", + className, + ">(json)", + ); + }); + }); + } else { + this.emitLine(")"); + } + } + + protected renameAttribute( + name: Name, + jsonName: string, + required: boolean, + meta: Array<() => void>, + ): void { + const rename = this.jacksonRenameAttribute(name, jsonName, required); + if (rename !== undefined) { + meta.push(() => this.emitLine(rename)); + } + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name, json) => { + this.emitLine( + name, + `("${stringEscape(json)}")`, + --count === 0 ? ";" : ",", + ); + }); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitBlock( + [ + "fun fromValue(value: String): ", + enumName, + " = when (value)", + ], + () => { + const table: Sourcelike[][] = []; + this.forEachEnumCase(e, "none", (name, json) => { + table.push([ + [`"${stringEscape(json)}"`], + [" -> ", name], + ]); + }); + table.push([ + ["else"], + [" -> throw IllegalArgumentException()"], + ]); + this.emitTable(table); + }, + ); + }); + }); + } + + private emitGenericConverter(): void { + this.ensureBlankLine(); + this.emitMultiline(` +@Suppress("UNCHECKED_CAST") +private fun ObjectMapper.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonNode) -> T, toJson: (T) -> String, isUnion: Boolean = false) = registerModule(SimpleModule().apply { + addSerializer(k.java as Class, object : StdSerializer(k.java as Class) { + override fun serialize(value: T, gen: JsonGenerator, provider: SerializerProvider) = gen.writeRawValue(toJson(value)) + }) + addDeserializer(k.java as Class, object : StdDeserializer(k.java as Class) { + override fun deserialize(p: JsonParser, ctxt: DeserializationContext) = fromJson(p.readValueAsTree()) + }) +})`); + } + + protected emitUnionDefinitionMethods( + u: UnionType, + nonNulls: ReadonlySet, + maybeNull: PrimitiveType | null, + unionName: Name, + ): void { + this.ensureBlankLine(); + this.emitLine( + "fun toJson(): String = mapper.writeValueAsString(when (this) {", + ); + this.indent(() => { + const toJsonTable: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (name) => { + toJsonTable.push([["is ", name], [" -> this.value"]]); + }); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + toJsonTable.push([["is ", name], [' -> "null"']]); + } + + this.emitTable(toJsonTable); + }); + this.emitLine("})"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "fun fromJson(jn: JsonNode): ", + unionName, + " = when (jn) {", + ); + this.indent(() => { + const table: Sourcelike[][] = []; + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (name, t) => { + table.push([ + [this.unionMemberJsonValueGuard(t, "jn")], + [" -> ", name, "(mapper.treeToValue(jn))"], + ]); + }, + ); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + table.push([ + [this.unionMemberJsonValueGuard(maybeNull, "jn")], + [" -> ", name, "()"], + ]); + } + + table.push([ + ["else"], + [" -> throw IllegalArgumentException()"], + ]); + this.emitTable(table); + }); + this.emitLine("}"); + }); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts new file mode 100644 index 000000000..e0dbbf25c --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinKlaxonRenderer.ts @@ -0,0 +1,420 @@ +import { arrayIntercalate, iterableSome } from "collection-utils"; + +import type { Name } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase } from "../../support/Strings"; +import { mustNotHappen } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + type ArrayType, + ClassType, + type EnumType, + type MapType, + type PrimitiveType, + type Type, + UnionType, +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../Type/TypeUtils"; + +import { KotlinRenderer } from "./KotlinRenderer"; +import type { kotlinOptions } from "./language"; +import { stringEscape } from "./utils"; + +export class KotlinKlaxonRenderer extends KotlinRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + _kotlinOptions: OptionValues, + ) { + super(targetLanguage, renderContext, _kotlinOptions); + } + + private unionMemberFromJsonValue(t: Type, e: Sourcelike): Sourcelike { + return matchType( + t, + (_anyType) => [e, ".inside"], + (_nullType) => "null", + (_boolType) => [e, ".boolean"], + (_integerType) => ["(", e, ".int?.toLong() ?: ", e, ".longValue)"], + (_doubleType) => [e, ".double"], + (_stringType) => [e, ".string"], + (arrayType) => [ + e, + ".array?.let { klaxon.parseFromJsonArray<", + this.kotlinType(arrayType.items), + ">(it) }", + ], + (_classType) => [ + e, + ".obj?.let { klaxon.parseFromJsonObject<", + this.kotlinType(t), + ">(it) }", + ], + (_mapType) => [ + e, + ".obj?.let { klaxon.parseFromJsonObject<", + this.kotlinType(t), + ">(it) }", + ], + (enumType) => [ + e, + ".string?.let { ", + this.kotlinType(enumType), + ".fromValue(it) }", + ], + (_unionType) => mustNotHappen(), + ); + } + + private unionMemberJsonValueGuard(t: Type, _e: Sourcelike): Sourcelike { + return matchType( + t, + (_anyType) => "is Any", + (_nullType) => "null", + (_boolType) => "is Boolean", + (_integerType) => "is Int, is Long", + (_doubleType) => "is Double", + (_stringType) => "is String", + (_arrayType) => "is JsonArray<*>", + // These could be stricter, but for now we don't allow maps + // and objects in the same union + (_classType) => "is JsonObject", + (_mapType) => "is JsonObject", + // This could be stricter, but for now we don't allow strings + // and enums in the same union + (_enumType) => "is String", + (_unionType) => mustNotHappen(), + ); + } + + protected emitUsageHeader(): void { + this.emitLine("// To parse the JSON, install Klaxon and do:"); + this.emitLine("//"); + this.forEachTopLevel("none", (_, name) => { + this.emitLine( + "// val ", + modifySource(camelCase, name), + " = ", + name, + ".fromJson(jsonString)", + ); + }); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import com.beust.klaxon.*"); + + const hasUnions = iterableSome( + this.typeGraph.allNamedTypes(), + (t) => t instanceof UnionType && nullableFromUnion(t) === null, + ); + const hasEmptyObjects = iterableSome( + this.typeGraph.allNamedTypes(), + (c) => c instanceof ClassType && c.getProperties().size === 0, + ); + if (hasUnions || this.haveEnums || hasEmptyObjects) { + this.emitGenericConverter(); + } + + const converters: Sourcelike[][] = []; + if (hasEmptyObjects) { + converters.push([ + [".convert(JsonObject::class,"], + [" { it.obj!! },"], + [" { it.toJsonString() })"], + ]); + } + + this.forEachEnum("none", (_, name) => { + converters.push([ + [".convert(", name, "::class,"], + [" { ", name, ".fromValue(it.string!!) },"], + [' { "\\"${it.value}\\"" })'], + ]); + }); + this.forEachUnion("none", (_, name) => { + converters.push([ + [".convert(", name, "::class,"], + [" { ", name, ".fromJson(it) },"], + [" { it.toJson() }, true)"], + ]); + }); + + this.ensureBlankLine(); + this.emitLine("private val klaxon = Klaxon()"); + if (converters.length > 0) { + this.indent(() => this.emitTable(converters)); + } + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitBlock( + [ + "class ", + name, + "(elements: Collection<", + elementType, + ">) : ArrayList<", + elementType, + ">(elements)", + ], + () => { + this.emitLine( + "public fun toJson() = klaxon.toJsonString(this)", + ); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "public fun fromJson(json: String) = ", + name, + "(klaxon.parseArray<", + elementType, + ">(json)!!)", + ); + }); + }, + ); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + this.emitBlock( + [ + "class ", + name, + "(elements: Map) : HashMap(elements)", + ], + () => { + this.emitLine( + "public fun toJson() = klaxon.toJsonString(this)", + ); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitBlock( + ["public fun fromJson(json: String) = ", name], + () => { + this.emitLine( + "klaxon.parseJsonObject(java.io.StringReader(json)) as Map", + ); + }, + "paren", + ); + }); + }, + ); + } + + private klaxonRenameAttribute( + propName: Name, + jsonName: string, + ignore = false, + ): Sourcelike | undefined { + const escapedName = stringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + const properties: Sourcelike[] = []; + if (namesDiffer) { + properties.push(['name = "', escapedName, '"']); + } + + if (ignore) { + properties.push("ignored = true"); + } + + return properties.length === 0 + ? undefined + : ["@Json(", arrayIntercalate(", ", properties), ")"]; + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + + this.emitLine("typealias ", className, " = JsonObject"); + } + + protected emitClassDefinitionMethods(c: ClassType, className: Name): void { + const isTopLevel = iterableSome( + this.topLevels, + ([_, top]) => top === c, + ); + if (isTopLevel) { + this.emitBlock(")", () => { + this.emitLine( + "public fun toJson() = klaxon.toJsonString(this)", + ); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "public fun fromJson(json: String) = klaxon.parse<", + className, + ">(json)", + ); + }); + }); + } else { + this.emitLine(")"); + } + } + + protected renameAttribute( + name: Name, + jsonName: string, + _required: boolean, + meta: Array<() => void>, + ): void { + const rename = this.klaxonRenameAttribute(name, jsonName); + if (rename !== undefined) { + meta.push(() => this.emitLine(rename)); + } + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name, json) => { + this.emitLine( + name, + `("${stringEscape(json)}")`, + --count === 0 ? ";" : ",", + ); + }); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitBlock( + [ + "public fun fromValue(value: String): ", + enumName, + " = when (value)", + ], + () => { + const table: Sourcelike[][] = []; + this.forEachEnumCase(e, "none", (name, json) => { + table.push([ + [`"${stringEscape(json)}"`], + [" -> ", name], + ]); + }); + table.push([ + ["else"], + [" -> throw IllegalArgumentException()"], + ]); + this.emitTable(table); + }, + ); + }); + }); + } + + private emitGenericConverter(): void { + this.ensureBlankLine(); + this.emitLine( + "private fun Klaxon.convert(k: kotlin.reflect.KClass<*>, fromJson: (JsonValue) -> T, toJson: (T) -> String, isUnion: Boolean = false) =", + ); + this.indent(() => { + this.emitLine("this.converter(object: Converter {"); + this.indent(() => { + this.emitLine('@Suppress("UNCHECKED_CAST")'); + this.emitTable([ + [ + "override fun toJson(value: Any)", + " = toJson(value as T)", + ], + [ + "override fun fromJson(jv: JsonValue)", + " = fromJson(jv) as Any", + ], + [ + "override fun canConvert(cls: Class<*>)", + " = cls == k.java || (isUnion && cls.superclass == k.java)", + ], + ]); + }); + this.emitLine("})"); + }); + } + + protected emitUnionDefinitionMethods( + u: UnionType, + nonNulls: ReadonlySet, + maybeNull: PrimitiveType | null, + unionName: Name, + ): void { + this.ensureBlankLine(); + this.emitLine( + "public fun toJson(): String = klaxon.toJsonString(when (this) {", + ); + this.indent(() => { + const toJsonTable: Sourcelike[][] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (name) => { + toJsonTable.push([["is ", name], [" -> this.value"]]); + }); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + toJsonTable.push([["is ", name], [' -> "null"']]); + } + + this.emitTable(toJsonTable); + }); + this.emitLine("})"); + this.ensureBlankLine(); + this.emitBlock("companion object", () => { + this.emitLine( + "public fun fromJson(jv: JsonValue): ", + unionName, + " = when (jv.inside) {", + ); + this.indent(() => { + const table: Sourcelike[][] = []; + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (name, t) => { + table.push([ + [this.unionMemberJsonValueGuard(t, "jv.inside")], + [ + " -> ", + name, + "(", + this.unionMemberFromJsonValue(t, "jv"), + "!!)", + ], + ]); + }, + ); + if (maybeNull !== null) { + const name = this.nameForUnionMember(u, maybeNull); + table.push([ + [ + this.unionMemberJsonValueGuard( + maybeNull, + "jv.inside", + ), + ], + [" -> ", name, "()"], + ]); + } + + table.push([ + ["else"], + [" -> throw IllegalArgumentException()"], + ]); + this.emitTable(table); + }); + this.emitLine("}"); + }); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts new file mode 100644 index 000000000..5e1c45b6b --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinRenderer.ts @@ -0,0 +1,417 @@ +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type PrimitiveType, + type Type, + type UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { kotlinOptions } from "./language"; +import { kotlinNameStyle } from "./utils"; + +export class KotlinRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _kotlinOptions: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties( + _o: ObjectType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: false }; + } + + protected topLevelNameStyle(rawName: string): string { + return kotlinNameStyle(true, rawName); + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("upper", (s) => + kotlinNameStyle( + true, + s, + acronymStyle(this._kotlinOptions.acronymStyle), + ), + ); + } + + protected namerForObjectProperty(): Namer { + return funPrefixNamer("lower", (s) => + kotlinNameStyle( + false, + s, + acronymStyle(this._kotlinOptions.acronymStyle), + ), + ); + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer( + "upper", + (s) => `${kotlinNameStyle(true, s)}Value`, + ); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("upper", (s) => + kotlinNameStyle( + true, + s, + acronymStyle(this._kotlinOptions.acronymStyle), + ), + ); + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); + } + + protected emitBlock( + line: Sourcelike, + f: () => void, + delimiter: "curly" | "paren" | "lambda" = "curly", + ): void { + const [open, close] = + delimiter === "curly" + ? ["{", "}"] + : delimiter === "paren" + ? ["(", ")"] + : ["{", "})"]; + this.emitLine(line, " ", open); + this.indent(f); + this.emitLine(close); + } + + protected anySourceType(optional: string): Sourcelike { + return ["Any", optional]; + } + + // (asarazan): I've broken out the following two functions + // because some renderers, such as kotlinx, can cope with `any`, while some get mad. + protected arrayType( + arrayType: ArrayType, + withIssues = false, + _noOptional = false, + ): Sourcelike { + return ["List<", this.kotlinType(arrayType.items, withIssues), ">"]; + } + + protected mapType( + mapType: MapType, + withIssues = false, + _noOptional = false, + ): Sourcelike { + return [ + "Map", + ]; + } + + protected kotlinType( + t: Type, + withIssues = false, + noOptional = false, + ): Sourcelike { + const optional = noOptional ? "" : "?"; + return matchType( + t, + (_anyType) => { + return maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + this.anySourceType(optional), + ); + }, + (_nullType) => { + return maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + this.anySourceType(optional), + ); + }, + (_boolType) => "Boolean", + (_integerType) => "Long", + (_doubleType) => "Double", + (_stringType) => "String", + (arrayType) => this.arrayType(arrayType, withIssues), + (classType) => this.nameForNamedType(classType), + (mapType) => this.mapType(mapType, withIssues), + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) + return [this.kotlinType(nullable, withIssues), optional]; + return this.nameForNamedType(unionType); + }, + ); + } + + protected emitUsageHeader(): void { + // To be overridden + } + + protected emitHeader(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitUsageHeader(); + } + + this.ensureBlankLine(); + this.emitLine("package ", this._kotlinOptions.packageName); + this.ensureBlankLine(); + } + + protected emitTopLevelPrimitive(t: PrimitiveType, name: Name): void { + const elementType = this.kotlinType(t); + this.emitLine(["typealias ", name, " = ", elementType, ""]); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitLine(["typealias ", name, " = ArrayList<", elementType, ">"]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + this.emitLine([ + "typealias ", + name, + " = HashMap", + ]); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitClassAnnotations(c, className); + this.emitLine("class ", className, "()"); + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + if (c.getProperties().size === 0) { + this.emitEmptyClassDefinition(c, className); + return; + } + + const kotlinType = (p: ClassProperty): Sourcelike => { + if (p.isOptional) { + return [this.kotlinType(p.type, true, true), "?"]; + } + + return this.kotlinType(p.type, true); + }; + + this.emitDescription(this.descriptionForType(c)); + this.emitClassAnnotations(c, className); + this.emitLine("data class ", className, " ("); + this.indent(() => { + let count = c.getProperties().size; + let first = true; + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + const nullable = + p.type.kind === "union" && + nullableFromUnion(p.type as UnionType) !== null; + const nullableOrOptional = + p.isOptional || p.type.kind === "null" || nullable; + const last = --count === 0; + const meta: Array<() => void> = []; + + const description = this.descriptionForClassProperty( + c, + jsonName, + ); + if (description !== undefined) { + meta.push(() => this.emitDescription(description)); + } + + this.renameAttribute(name, jsonName, !nullableOrOptional, meta); + + if (meta.length > 0 && !first) { + this.ensureBlankLine(); + } + + for (const emit of meta) { + emit(); + } + + this.emitLine( + "val ", + name, + ": ", + kotlinType(p), + nullableOrOptional ? " = null" : "", + last ? "" : ",", + ); + + if (meta.length > 0 && !last) { + this.ensureBlankLine(); + } + + first = false; + }); + }); + + this.emitClassDefinitionMethods(c, className); + } + + protected emitClassDefinitionMethods( + _c: ClassType, + _className: Name, + ): void { + this.emitLine(")"); + } + + protected emitClassAnnotations(_c: Type, _className: Name): void { + // to be overridden + } + + protected renameAttribute( + _name: Name, + _jsonName: string, + _required: boolean, + _meta: Array<() => void>, + ): void { + // to be overridden + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock(["enum class ", enumName], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name) => { + this.emitLine(name, --count === 0 ? "" : ","); + }); + }); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return `_${kind}`; + } + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + this.emitClassAnnotations(u, unionName); + this.emitBlock(["sealed class ", unionName], () => { + { + const table: Sourcelike[][] = []; + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (name, t) => { + table.push([ + [ + "class ", + name, + "(val value: ", + this.kotlinType(t), + ")", + ], + [" : ", unionName, "()"], + ]); + }, + ); + if (maybeNull !== null) { + table.push([ + ["class ", this.nameForUnionMember(u, maybeNull), "()"], + [" : ", unionName, "()"], + ]); + } + + this.emitTable(table); + } + + this.emitUnionDefinitionMethods(u, nonNulls, maybeNull, unionName); + }); + } + + protected emitUnionDefinitionMethods( + _u: UnionType, + _nonNulls: ReadonlySet, + _maybeNull: PrimitiveType | null, + _unionName: Name, + ): void { + // to be overridden + } + + protected emitSourceStructure(): void { + this.emitHeader(); + + // Top-level arrays, maps + this.forEachTopLevel("leading", (t, name) => { + if (t instanceof ArrayType) { + this.emitTopLevelArray(t, name); + } else if (t instanceof MapType) { + this.emitTopLevelMap(t, name); + } else if (t.isPrimitive()) { + this.emitTopLevelPrimitive(t, name); + } + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n), + ); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts b/packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts new file mode 100644 index 000000000..8084f36cc --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/KotlinXRenderer.ts @@ -0,0 +1,150 @@ +import type { Name } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase } from "../../support/Strings"; +import type { TargetLanguage } from "../../TargetLanguage"; +import type { + ArrayType, + EnumType, + MapType, + Type, +} from "../../Type"; + +import { KotlinRenderer } from "./KotlinRenderer"; +import type { kotlinOptions } from "./language"; +import { stringEscape } from "./utils"; + +/** + * Currently supports simple classes, enums, and TS string unions (which are also enums). + * TODO: Union, Any, Top Level Array, Top Level Map + */ +export class KotlinXRenderer extends KotlinRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + _kotlinOptions: OptionValues, + ) { + super(targetLanguage, renderContext, _kotlinOptions); + } + + protected anySourceType(optional: string): Sourcelike { + return ["JsonElement", optional]; + } + + protected arrayType( + arrayType: ArrayType, + withIssues = false, + noOptional = false, + ): Sourcelike { + const valType = this.kotlinType(arrayType.items, withIssues, true); + const name = this.sourcelikeToString(valType); + if (name === "JsonObject" || name === "JsonElement") { + return "JsonArray"; + } + + return super.arrayType(arrayType, withIssues, noOptional); + } + + protected mapType( + mapType: MapType, + withIssues = false, + noOptional = false, + ): Sourcelike { + const valType = this.kotlinType(mapType.values, withIssues, true); + const name = this.sourcelikeToString(valType); + if (name === "JsonObject" || name === "JsonElement") { + return "JsonObject"; + } + + return super.mapType(mapType, withIssues, noOptional); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.kotlinType(t.values); + if (elementType === "JsonObject") { + this.emitLine(["typealias ", name, " = JsonObject"]); + } else { + super.emitTopLevelMap(t, name); + } + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.kotlinType(t.items); + this.emitLine(["typealias ", name, " = JsonArray<", elementType, ">"]); + } + + protected emitUsageHeader(): void { + this.emitLine( + "// To parse the JSON, install kotlin's serialization plugin and do:", + ); + this.emitLine("//"); + const table: Sourcelike[][] = []; + table.push([ + "// val ", + "json", + " = Json { allowStructuredMapKeys = true }", + ]); + this.forEachTopLevel("none", (_, name) => { + table.push([ + "// val ", + modifySource(camelCase, name), + ` = json.parse(${this.sourcelikeToString(name)}.serializer(), jsonString)`, + ]); + }); + this.emitTable(table); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import kotlinx.serialization.*"); + this.emitLine("import kotlinx.serialization.json.*"); + this.emitLine("import kotlinx.serialization.descriptors.*"); + this.emitLine("import kotlinx.serialization.encoding.*"); + } + + protected emitClassAnnotations(_c: Type, _className: Name): void { + this.emitLine("@Serializable"); + } + + protected renameAttribute( + name: Name, + jsonName: string, + _required: boolean, + meta: Array<() => void>, + ): void { + const rename = this._rename(name, jsonName); + if (rename !== undefined) { + meta.push(() => this.emitLine(rename)); + } + } + + private _rename(propName: Name, jsonName: string): Sourcelike | undefined { + const escapedName = stringEscape(jsonName); + const namesDiffer = this.sourcelikeToString(propName) !== escapedName; + if (namesDiffer) { + return ['@SerialName("', escapedName, '")']; + } + + return undefined; + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitLine(["@Serializable"]); + this.emitBlock(["enum class ", enumName, "(val value: String)"], () => { + let count = e.cases.size; + this.forEachEnumCase(e, "none", (name, json) => { + const jsonEnum = stringEscape(json); + this.emitLine( + `@SerialName("${jsonEnum}") `, + name, + `("${jsonEnum}")`, + --count === 0 ? ";" : ",", + ); + }); + }); + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/constants.ts b/packages/quicktype-core/src/language/Kotlin/constants.ts new file mode 100644 index 000000000..89993e322 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/constants.ts @@ -0,0 +1,51 @@ +export const keywords = [ + "package", + "as", + "typealias", + "class", + "this", + "super", + "val", + "var", + "fun", + "for", + "null", + "true", + "false", + "is", + "in", + "throw", + "return", + "break", + "continue", + "object", + "if", + "try", + "else", + "while", + "do", + "when", + "interface", + "typeof", + "klaxon", + "toJson", + "Any", + "Boolean", + "Double", + "Float", + "Long", + "Int", + "Short", + "System", + "Byte", + "String", + "Array", + "List", + "Map", + "Enum", + "Class", + "JsonObject", + "JsonValue", + "Converter", + "Klaxon", +] as const; diff --git a/packages/quicktype-core/src/language/Kotlin/index.ts b/packages/quicktype-core/src/language/Kotlin/index.ts new file mode 100644 index 000000000..e6459d694 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/index.ts @@ -0,0 +1,5 @@ +export { KotlinTargetLanguage, kotlinOptions } from "./language"; +export { KotlinRenderer } from "./KotlinRenderer"; +export { KotlinJacksonRenderer } from "./KotlinJacksonRenderer"; +export { KotlinKlaxonRenderer } from "./KotlinKlaxonRenderer"; +export { KotlinXRenderer } from "./KotlinXRenderer"; diff --git a/packages/quicktype-core/src/language/Kotlin/language.ts b/packages/quicktype-core/src/language/Kotlin/language.ts new file mode 100644 index 000000000..ce72896ac --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/language.ts @@ -0,0 +1,78 @@ +import type { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import type { RenderContext } from "../../Renderer"; +import { + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { KotlinJacksonRenderer } from "./KotlinJacksonRenderer"; +import { KotlinKlaxonRenderer } from "./KotlinKlaxonRenderer"; +import { KotlinRenderer } from "./KotlinRenderer"; +import { KotlinXRenderer } from "./KotlinXRenderer"; + +export const kotlinOptions = { + framework: new EnumOption( + "framework", + "Serialization framework", + { + "just-types": "None", + jackson: "Jackson", + klaxon: "Klaxon", + kotlinx: "KotlinX", + } as const, + "klaxon", + ), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), +}; + +export const kotlinLanguageConfig = { + displayName: "Kotlin", + names: ["kotlin"], + extension: "kt", +} as const; + +export class KotlinTargetLanguage extends TargetLanguage< + typeof kotlinLanguageConfig +> { + public constructor() { + super(kotlinLanguageConfig); + } + + public getOptions(): typeof kotlinOptions { + return kotlinOptions; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ConvenienceRenderer { + const options = getOptionValues(kotlinOptions, untypedOptionValues); + + switch (options.framework) { + case "None": + return new KotlinRenderer(this, renderContext, options); + case "Jackson": + return new KotlinJacksonRenderer(this, renderContext, options); + case "Klaxon": + return new KotlinKlaxonRenderer(this, renderContext, options); + case "KotlinX": + return new KotlinXRenderer(this, renderContext, options); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/Kotlin/utils.ts b/packages/quicktype-core/src/language/Kotlin/utils.ts new file mode 100644 index 000000000..d47d933e8 --- /dev/null +++ b/packages/quicktype-core/src/language/Kotlin/utils.ts @@ -0,0 +1,57 @@ +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isDigit, + isLetterOrUnderscore, + isNumeric, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap, +} from "../../support/Strings"; + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function kotlinNameStyle( + isUpper: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle, +): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + acronymsStyle, + "", + isStartCharacter, + ); +} + +function unicodeEscape(codePoint: number): string { + return "\\u" + intToHex(codePoint, 4); +} + +// eslint-disable-next-line @typescript-eslint/naming-convention +const _stringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, unicodeEscape), +); + +export function stringEscape(s: string): string { + // "$this" is a template string in Kotlin so we have to escape $ + return _stringEscape(s).replace(/\$/g, "\\$"); +} diff --git a/packages/quicktype-core/src/language/Objective-C.ts b/packages/quicktype-core/src/language/Objective-C.ts deleted file mode 100644 index b82f065fa..000000000 --- a/packages/quicktype-core/src/language/Objective-C.ts +++ /dev/null @@ -1,1084 +0,0 @@ -import { iterableSome, iterableFirst, mapContains, mapFirst, mapSome } from "collection-utils"; - -import { TargetLanguage } from "../TargetLanguage"; -import { Type, ClassType, EnumType, ArrayType, MapType, UnionType, ClassProperty } from "../Type"; -import { matchType, nullableFromUnion, isAnyOrNull } from "../TypeUtils"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { Sourcelike, modifySource } from "../Source"; -import { - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, - allLowerWordStyle, - camelCase, - utf16LegalizeCharacters, - stringEscape, - addPrefixIfNecessary, - repeatString, - fastIsUpperCase -} from "../support/Strings"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { StringOption, BooleanOption, EnumOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { assert, defined } from "../support/Support"; -import { RenderContext } from "../Renderer"; - -import unicode from "unicode-properties"; - -export type MemoryAttribute = "assign" | "strong" | "copy"; -export type OutputFeatures = { interface: boolean; implementation: boolean }; - -const DEBUG = false; -const DEFAULT_CLASS_PREFIX = "QT"; - -export const objcOptions = { - features: new EnumOption("features", "Interface and implementation", [ - ["all", { interface: true, implementation: true }], - ["interface", { interface: true, implementation: false }], - ["implementation", { interface: false, implementation: true }] - ]), - justTypes: new BooleanOption("just-types", "Plain types only", false), - marshallingFunctions: new BooleanOption("functions", "C-style functions", false), - classPrefix: new StringOption("class-prefix", "Class prefix", "PREFIX", DEFAULT_CLASS_PREFIX), - extraComments: new BooleanOption("extra-comments", "Extra comments", false) -}; - -export class ObjectiveCTargetLanguage extends TargetLanguage { - constructor() { - super("Objective-C", ["objc", "objective-c", "objectivec"], "m"); - } - - protected getOptions(): Option[] { - return [ - objcOptions.justTypes, - objcOptions.classPrefix, - objcOptions.features, - objcOptions.extraComments, - objcOptions.marshallingFunctions - ]; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ObjectiveCRenderer { - return new ObjectiveCRenderer(this, renderContext, getOptionValues(objcOptions, untypedOptionValues)); - } -} - -function typeNameStyle(prefix: string, original: string): string { - const words = splitIntoWords(original); - const result = combineWords( - words, - legalizeName, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); - return addPrefixIfNecessary(prefix, result); -} - -function propertyNameStyle(original: string, isBool = false): string { - // Objective-C developers are uncomfortable with property "id" - // so we use an alternate name in this special case. - if (original === "id") { - original = "identifier"; - } - - let words = splitIntoWords(original); - - if (isBool) { - if (words.length === 0) { - words = [{ word: "flag", isAcronym: false }]; - } else if (!words[0].isAcronym && booleanPrefixes.indexOf(words[0].word) < 0) { - words = [{ word: "is", isAcronym: false }, ...words]; - } - } - - // Properties cannot even begin with any of the forbidden names - // For example, properies named new* are treated differently by ARC - if (words.length > 0 && forbiddenPropertyNames.indexOf(words[0].word) >= 0) { - words = [{ word: "the", isAcronym: false }, ...words]; - } - - return combineWords( - words, - legalizeName, - allLowerWordStyle, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -const keywords = [ - /* - "_Bool", - "_Complex", - "_Imaginary", - */ - "asm", - "atomic", - "auto", - "bool", - "break", - "case", - "char", - "const", - "continue", - "default", - "do", - "double", - "else", - "enum", - "extern", - "false", - "float", - "for", - "goto", - "if", - "inline", - "int", - "long", - "nil", - "nonatomic", - "register", - "restrict", - "retain", - "return", - "short", - "signed", - "sizeof", - "static", - "struct", - "switch", - "typedef", - "typeof", - "true", - "union", - "unsigned", - "void", - "volatile", - "while" -]; - -const forbiddenPropertyNames = [ - "id", - "hash", - "description", - "init", - "copy", - "mutableCopy", - "superclass", - "debugDescription", - "new" -]; - -const booleanPrefixes = [ - "is", - "are", - "were", - "was", - "will", - "all", - "some", - "many", - "has", - "have", - "had", - "does", - "do", - "requires", - "require", - "needs", - "need" -]; - -function isStartCharacter(utf16Unit: number): boolean { - return unicode.isAlphabetic(utf16Unit) || utf16Unit === 0x5f; // underscore -} - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0 || isStartCharacter(utf16Unit); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -const staticEnumValuesIdentifier = "values"; -const forbiddenForEnumCases = ["new", staticEnumValuesIdentifier]; - -function splitExtension(filename: string): [string, string] { - const i = filename.lastIndexOf("."); - const extension = i !== -1 ? filename.split(".").pop() : "m"; - filename = i !== -1 ? filename.slice(0, i) : filename; - return [filename, extension === undefined ? "m" : extension]; -} - -export class ObjectiveCRenderer extends ConvenienceRenderer { - private _currentFilename: string | undefined; - private readonly _classPrefix: string; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - - // Infer the class prefix from a top-level name if it's not given - if (_options.classPrefix === DEFAULT_CLASS_PREFIX) { - const aTopLevel = defined(iterableFirst(this.topLevels.keys())); - this._classPrefix = this.inferClassPrefix(aTopLevel); - } else { - this._classPrefix = _options.classPrefix; - } - } - - private inferClassPrefix(name: string): string { - const l = name.length; - let firstNonUpper = 0; - while (firstNonUpper < l && fastIsUpperCase(name.charCodeAt(firstNonUpper))) { - firstNonUpper += 1; - } - if (firstNonUpper < 2) return DEFAULT_CLASS_PREFIX; - return name.slice(0, firstNonUpper - 1); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: forbiddenPropertyNames, includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: forbiddenForEnumCases, includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("types", rawName => typeNameStyle(this._classPrefix, rawName)); - } - - protected namerForObjectProperty(_: ClassType, p: ClassProperty): Namer { - // TODO why is underscore being removed? - return new Namer("properties", s => propertyNameStyle(s, p.type.kind === "bool"), [ - "_", - "the", - "one", - "some", - "another" - ]); - } - - protected makeUnionMemberNamer(): null { - return null; - } - - protected makeEnumCaseNamer(): Namer { - return new Namer("enum-cases", propertyNameStyle, []); - } - - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { - return type; - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, "/// "); - } - - protected emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line, " {"); - this.indent(f); - this.emitLine("}"); - } - - protected emitMethod(declaration: Sourcelike, f: () => void) { - this.emitLine(declaration); - this.emitLine("{"); - this.indent(f); - this.emitLine("}"); - } - - protected emitExtraComments(...comments: Sourcelike[]) { - if (!this._options.extraComments) return; - for (const comment of comments) { - this.emitLine("// ", comment); - } - } - - protected startFile(basename: Sourcelike, extension: string): void { - assert(this._currentFilename === undefined, "Previous file wasn't finished"); - // FIXME: The filenames should actually be Sourcelikes, too - this._currentFilename = `${this.sourcelikeToString(basename)}.${extension}`; - } - - protected finishFile(): void { - super.finishFile(defined(this._currentFilename)); - this._currentFilename = undefined; - } - - protected memoryAttribute(t: Type, isNullable: boolean): MemoryAttribute { - return matchType( - t, - _anyType => "copy", - _nullType => "copy", - _boolType => (isNullable ? "strong" : "assign"), - _integerType => (isNullable ? "strong" : "assign"), - _doubleType => (isNullable ? "strong" : "assign"), - _stringType => "copy", - _arrayType => "copy", - _classType => "strong", - _mapType => "copy", - _enumType => "assign", - unionType => { - const nullable = nullableFromUnion(unionType); - return nullable !== null ? this.memoryAttribute(nullable, true) : "copy"; - } - ); - } - - protected objcType(t: Type, nullableOrBoxed = false): [Sourcelike, string] { - return matchType<[Sourcelike, string]>( - t, - _anyType => ["id", ""], - // For now, we're treating nulls just like any - _nullType => ["id", ""], - _boolType => (nullableOrBoxed ? ["NSNumber", " *"] : ["BOOL", ""]), - _integerType => (nullableOrBoxed ? ["NSNumber", " *"] : ["NSInteger", ""]), - _doubleType => (nullableOrBoxed ? ["NSNumber", " *"] : ["double", ""]), - _stringType => ["NSString", " *"], - arrayType => { - const itemType = arrayType.items; - const itemTypeName = this.objcType(itemType, true); - // NSArray* === NSArray* - if (isAnyOrNull(itemType)) { - return ["NSArray", " *"]; - } - return [["NSArray<", itemTypeName, ">"], " *"]; - }, - classType => [this.nameForNamedType(classType), " *"], - mapType => [["NSDictionary"], " *"], - enumType => [this.nameForNamedType(enumType), " *"], - unionType => { - const nullable = nullableFromUnion(unionType); - return nullable !== null ? this.objcType(nullable, true) : ["id", ""]; - } - ); - } - - private jsonType(t: Type): [Sourcelike, string] { - return matchType<[Sourcelike, string]>( - t, - _anyType => ["id", ""], - // For now, we're treating nulls just like any - _nullType => ["id", ""], - _boolType => ["NSNumber", " *"], - _integerType => ["NSNumber", " *"], - _doubleType => ["NSNumber", " *"], - _stringType => ["NSString", " *"], - _arrayType => ["NSArray", " *"], - _classType => ["NSDictionary", " *"], - mapType => [["NSDictionary"], " *"], - _enumType => ["NSString", " *"], - unionType => { - const nullable = nullableFromUnion(unionType); - return nullable !== null ? this.jsonType(nullable) : ["id", ""]; - } - ); - } - - protected fromDynamicExpression(t: Type, ...dynamic: Sourcelike[]): Sourcelike { - return matchType( - t, - _anyType => dynamic, - _nullType => dynamic, - _boolType => dynamic, - _integerType => dynamic, - _doubleType => dynamic, - _stringType => dynamic, - arrayType => ["map(", dynamic, ", Ξ»(id x, ", this.fromDynamicExpression(arrayType.items, "x"), "))"], - classType => ["[", this.nameForNamedType(classType), " fromJSONDictionary:", dynamic, "]"], - mapType => ["map(", dynamic, ", Ξ»(id x, ", this.fromDynamicExpression(mapType.values, "x"), "))"], - enumType => ["[", this.nameForNamedType(enumType), " withValue:", dynamic, "]"], - unionType => { - const nullable = nullableFromUnion(unionType); - return nullable !== null ? this.fromDynamicExpression(nullable, dynamic) : dynamic; - } - ); - } - - protected toDynamicExpression(t: Type, typed: Sourcelike): Sourcelike { - return matchType( - t, - _anyType => ["NSNullify(", typed, ")"], - _nullType => ["NSNullify(", typed, ")"], - // Sadly, KVC - _boolType => [typed, ` ? @YES : @NO`], - _integerType => typed, - _doubleType => typed, - _stringType => typed, - arrayType => { - if (this.implicitlyConvertsFromJSON(arrayType)) { - // TODO check each value type - return typed; - } - return ["map(", typed, ", Ξ»(id x, ", this.toDynamicExpression(arrayType.items, "x"), "))"]; - }, - _classType => ["[", typed, " JSONDictionary]"], - mapType => { - if (this.implicitlyConvertsFromJSON(mapType)) { - // TODO check each value type - return typed; - } - return ["map(", typed, ", Ξ»(id x, ", this.toDynamicExpression(mapType.values, "x"), "))"]; - }, - _enumType => ["[", typed, " value]"], - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - if (this.implicitlyConvertsFromJSON(nullable)) { - return ["NSNullify(", typed, ")"]; - } else { - return ["NSNullify(", this.toDynamicExpression(nullable, typed), ")"]; - } - } else { - // TODO support unions - return typed; - } - } - ); - } - - protected implicitlyConvertsFromJSON(t: Type): boolean { - if (t instanceof ClassType) { - return false; - } else if (t instanceof EnumType) { - return false; - } else if (t instanceof ArrayType) { - return this.implicitlyConvertsFromJSON(t.items); - } else if (t instanceof MapType) { - return this.implicitlyConvertsFromJSON(t.values); - } else if (t.isPrimitive()) { - return true; - } else if (t instanceof UnionType) { - const nullable = nullableFromUnion(t); - if (nullable !== null) { - return this.implicitlyConvertsFromJSON(nullable); - } else { - // We don't support unions yet, so this is just untyped - return true; - } - } else { - return false; - } - } - - protected implicitlyConvertsToJSON(t: Type): boolean { - return this.implicitlyConvertsFromJSON(t) && "bool" !== t.kind; - } - - protected emitPropertyAssignment(propertyName: Name, jsonName: string, propertyType: Type) { - const name = ["_", propertyName]; - matchType( - propertyType, - anyType => this.emitLine(name, " = ", this.fromDynamicExpression(anyType, name), ";"), - nullType => this.emitLine(name, " = ", this.fromDynamicExpression(nullType, name), ";"), - boolType => this.emitLine(name, " = ", this.fromDynamicExpression(boolType, name), ";"), - integerType => this.emitLine(name, " = ", this.fromDynamicExpression(integerType, name), ";"), - doubleType => this.emitLine(name, " = ", this.fromDynamicExpression(doubleType, name), ";"), - stringType => this.emitLine(name, " = ", this.fromDynamicExpression(stringType, name), ";"), - arrayType => this.emitLine(name, " = ", this.fromDynamicExpression(arrayType, name), ";"), - classType => this.emitLine(name, " = ", this.fromDynamicExpression(classType, ["(id)", name]), ";"), - mapType => { - const itemType = mapType.values; - this.emitLine( - name, - " = map(", - name, - ", ", - ["Ξ»(id x, ", this.fromDynamicExpression(itemType, "x"), ")"], - ");" - ); - }, - enumType => this.emitLine(name, " = ", this.fromDynamicExpression(enumType, ["(id)", name]), ";"), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - this.emitPropertyAssignment(propertyName, jsonName, nullable); - } else { - // TODO This is a union, but for now we just leave it dynamic - this.emitLine(name, " = ", this.fromDynamicExpression(unionType, name), ";"); - } - } - ); - } - - protected emitPrivateClassInterface(_: ClassType, name: Name): void { - this.emitLine("@interface ", name, " (JSONConversion)"); - this.emitLine("+ (instancetype)fromJSONDictionary:(NSDictionary *)dict;"); - this.emitLine("- (NSDictionary *)JSONDictionary;"); - this.emitLine("@end"); - } - - protected pointerAwareTypeName(t: Type | [Sourcelike, string]): Sourcelike { - const name = t instanceof Type ? this.objcType(t) : t; - const isPointer = name[1] !== ""; - return isPointer ? name : [name, " "]; - } - - private emitNonClassTopLevelTypedef(t: Type, name: Name): void { - let nonPointerTypeName = this.objcType(t)[0]; - this.emitLine("typedef ", nonPointerTypeName, " ", name, ";"); - } - - private topLevelFromDataPrototype(name: Name): Sourcelike { - return [name, " *_Nullable ", name, "FromData(NSData *data, NSError **error)"]; - } - - private topLevelFromJSONPrototype(name: Name): Sourcelike { - return [name, " *_Nullable ", name, "FromJSON(NSString *json, NSStringEncoding encoding, NSError **error)"]; - } - - private topLevelToDataPrototype(name: Name, pad = false): Sourcelike { - const parameter = this.variableNameForTopLevel(name); - const padding = pad ? repeatString(" ", this.sourcelikeToString(name).length - "NSData".length) : ""; - return ["NSData", padding, " *_Nullable ", name, "ToData(", name, " *", parameter, ", NSError **error)"]; - } - - private topLevelToJSONPrototype(name: Name, pad = false): Sourcelike { - const parameter = this.variableNameForTopLevel(name); - const padding = pad ? repeatString(" ", this.sourcelikeToString(name).length - "NSString".length) : ""; - return [ - "NSString", - padding, - " *_Nullable ", - name, - "ToJSON(", - name, - " *", - parameter, - ", NSStringEncoding encoding, NSError **error)" - ]; - } - - private emitTopLevelFunctionDeclarations(_: Type, name: Name): void { - this.emitLine(this.topLevelFromDataPrototype(name), ";"); - this.emitLine(this.topLevelFromJSONPrototype(name), ";"); - this.emitLine(this.topLevelToDataPrototype(name, true), ";"); - this.emitLine(this.topLevelToJSONPrototype(name, true), ";"); - } - - private emitTryCatchAsError(inTry: () => void, inCatch: () => void) { - this.emitLine("@try {"); - this.indent(inTry); - this.emitLine("} @catch (NSException *exception) {"); - this.indent(() => { - this.emitLine( - `*error = [NSError errorWithDomain:@"JSONSerialization" code:-1 userInfo:@{ @"exception": exception }];` - ); - inCatch(); - }); - this.emitLine("}"); - } - - private emitTopLevelFunctions(t: Type, name: Name): void { - const parameter = this.variableNameForTopLevel(name); - - this.ensureBlankLine(); - this.emitMethod(this.topLevelFromDataPrototype(name), () => { - this.emitTryCatchAsError( - () => { - this.emitLine( - "id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:error];" - ); - this.emitLine("return *error ? nil : ", this.fromDynamicExpression(t, "json"), ";"); - }, - () => this.emitLine("return nil;") - ); - }); - - this.ensureBlankLine(); - this.emitMethod(this.topLevelFromJSONPrototype(name), () => { - this.emitLine("return ", name, "FromData([json dataUsingEncoding:encoding], error);"); - }); - - this.ensureBlankLine(); - this.emitMethod(this.topLevelToDataPrototype(name), () => { - this.emitTryCatchAsError( - () => { - this.emitLine("id json = ", this.toDynamicExpression(t, parameter), ";"); - this.emitLine( - "NSData *data = [NSJSONSerialization dataWithJSONObject:json options:kNilOptions error:error];" - ); - this.emitLine("return *error ? nil : data;"); - }, - () => this.emitLine("return nil;") - ); - }); - - this.ensureBlankLine(); - this.emitMethod(this.topLevelToJSONPrototype(name), () => { - this.emitLine("NSData *data = ", name, "ToData(", parameter, ", error);"); - this.emitLine("return data ? [[NSString alloc] initWithData:data encoding:encoding] : nil;"); - }); - } - - private emitClassInterface(t: ClassType, className: Name): void { - const isTopLevel = mapContains(this.topLevels, t); - - this.emitDescription(this.descriptionForType(t)); - - this.emitLine("@interface ", className, " : NSObject"); - if (DEBUG) this.emitLine("@property NSDictionary *_json;"); - this.emitPropertyTable(t, (name, _json, property) => { - let attributes = ["nonatomic"]; - // TODO offer a 'readonly' option - // TODO We must add "copy" if it's NSCopy, otherwise "strong" - if (property.type.isNullable) { - attributes.push("nullable"); - } - attributes.push(this.memoryAttribute(property.type, property.type.isNullable)); - return [ - ["@property ", ["(", attributes.join(", "), ")"], " "], - [this.pointerAwareTypeName(property.type), name, ";"] - ]; - }); - - if (!this._options.justTypes && isTopLevel) { - if (t.getProperties().size > 0) this.ensureBlankLine(); - - this.emitLine( - "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;" - ); - this.emitLine("+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error;"); - this.emitLine( - "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;" - ); - this.emitLine("- (NSData *_Nullable)toData:(NSError *_Nullable *)error;"); - } - this.emitLine("@end"); - } - - protected hasIrregularProperties(t: ClassType) { - let irregular = false; - this.forEachClassProperty(t, "none", (name, jsonName) => { - irregular = irregular || stringEscape(jsonName) !== this.sourcelikeToString(name); - }); - return irregular; - } - - protected hasUnsafeProperties(t: ClassType) { - let unsafe = false; - this.forEachClassProperty(t, "none", (_, __, property) => { - unsafe = unsafe || !this.implicitlyConvertsToJSON(property.type); - }); - return unsafe; - } - - // TODO Implement NSCopying - private emitClassImplementation(t: ClassType, className: Name): void { - const isTopLevel = mapContains(this.topLevels, t); - - const hasIrregularProperties = this.hasIrregularProperties(t); - const hasUnsafeProperties = this.hasUnsafeProperties(t); - - this.emitLine("@implementation ", className); - if (!this._options.justTypes) { - this.emitMethod("+ (NSDictionary *)properties", () => { - this.emitLine("static NSDictionary *properties;"); - this.emitLine("return properties = properties ? properties : @{"); - this.indent(() => { - this.forEachClassProperty(t, "none", (name, jsonName) => - this.emitLine(`@"${stringEscape(jsonName)}": @"`, name, `",`) - ); - }); - this.emitLine("};"); - }); - this.ensureBlankLine(); - - if (isTopLevel) { - this.emitMethod( - "+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error", - () => { - this.emitLine("return ", className, "FromData(data, error);"); - } - ); - this.ensureBlankLine(); - this.emitMethod( - "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", - () => { - this.emitLine("return ", className, "FromJSON(json, encoding, error);"); - } - ); - this.ensureBlankLine(); - } - - this.emitMethod("+ (instancetype)fromJSONDictionary:(NSDictionary *)dict", () => { - this.emitLine("return dict ? [[", className, " alloc] initWithJSONDictionary:dict] : nil;"); - }); - this.ensureBlankLine(); - this.emitMethod("- (instancetype)initWithJSONDictionary:(NSDictionary *)dict", () => { - this.emitBlock("if (self = [super init])", () => { - if (DEBUG) this.emitLine("__json = dict;"); - - this.emitLine("[self setValuesForKeysWithDictionary:dict];"); - this.forEachClassProperty(t, "none", (name, jsonName, property) => { - if (!this.implicitlyConvertsFromJSON(property.type)) { - this.emitPropertyAssignment(name, jsonName, property.type); - } - }); - }); - this.emitLine("return self;"); - }); - - this.ensureBlankLine(); - this.emitMethod("- (void)setValue:(nullable id)value forKey:(NSString *)key", () => { - this.emitLine("id resolved = ", className, ".properties[key];"); - this.emitLine("if (resolved) [super setValue:value forKey:resolved];"); - }); - - // setNilValueForKey: is automatically invoked by the NSObject setValue:forKey: when it is passed nil for a scalar (a.k.a. non-nullable) object - // The approach below sets the scalar to 0 in this case, and therefore assumes an initializer with incomplete data shouldn't be grounds for raising an exception. - // Put another way, if the initializer didn't have a key at all, there wouldn't be an exception raised, so sending nil for something probably shouldn't cause one. - this.ensureBlankLine(); - this.emitMethod("- (void)setNilValueForKey:(NSString *)key", () => { - this.emitLine("id resolved = ", className, ".properties[key];"); - this.emitLine("if (resolved) [super setValue:@(0) forKey:resolved];"); - }); - - this.ensureBlankLine(); - this.emitMethod("- (NSDictionary *)JSONDictionary", () => { - if (!hasIrregularProperties && !hasUnsafeProperties) { - this.emitLine("return [self dictionaryWithValuesForKeys:", className, ".properties.allValues];"); - return; - } - - this.emitLine( - "id dict = [[self dictionaryWithValuesForKeys:", - className, - ".properties.allValues] mutableCopy];" - ); - this.ensureBlankLine(); - - if (hasIrregularProperties) { - this.emitExtraComments("Rewrite property names that differ in JSON"); - this.emitBlock(["for (id jsonName in ", className, ".properties)"], () => { - this.emitLine(`id propertyName = `, className, `.properties[jsonName];`); - this.emitBlock(`if (![jsonName isEqualToString:propertyName])`, () => { - this.emitLine(`dict[jsonName] = dict[propertyName];`); - this.emitLine(`[dict removeObjectForKey:propertyName];`); - }); - }); - } - - if (hasUnsafeProperties) { - this.ensureBlankLine(); - this.emitExtraComments("Map values that need translation"); - this.emitLine("[dict addEntriesFromDictionary:@{"); - this.indent(() => { - this.forEachClassProperty(t, "none", (propertyName, jsonKey, property) => { - if (!this.implicitlyConvertsToJSON(property.type)) { - const key = stringEscape(jsonKey); - const name = ["_", propertyName]; - this.emitLine('@"', key, '": ', this.toDynamicExpression(property.type, name), ","); - } - }); - }); - this.emitLine("}];"); - } - - this.ensureBlankLine(); - this.emitLine("return dict;"); - }); - - if (isTopLevel) { - this.ensureBlankLine(); - this.emitMethod(`- (NSData *_Nullable)toData:(NSError *_Nullable *)error`, () => { - this.emitLine("return ", className, "ToData(self, error);"); - }); - this.ensureBlankLine(); - this.emitMethod( - `- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error`, - () => { - this.emitLine("return ", className, "ToJSON(self, encoding, error);"); - } - ); - } - } - - this.emitLine("@end"); - } - - protected emitMark(label: string) { - this.ensureBlankLine(); - this.emitLine(`#pragma mark - ${label}`); - this.ensureBlankLine(); - } - - protected variableNameForTopLevel(name: Name): Sourcelike { - const camelCaseName = modifySource(serialized => { - // 1. remove class prefix - serialized = serialized.slice(this._classPrefix.length); - // 2. camel case - return camelCase(serialized); - }, name); - return camelCaseName; - } - - private emitPseudoEnumInterface(enumType: EnumType, enumName: Name) { - this.emitDescription(this.descriptionForType(enumType)); - - this.emitLine("@interface ", enumName, " : NSObject"); - this.emitLine("@property (nonatomic, readonly, copy) NSString *value;"); - this.emitLine("+ (instancetype _Nullable)withValue:(NSString *)value;"); - this.forEachEnumCase(enumType, "none", (name, _) => { - this.emitLine("+ (", enumName, " *)", name, ";"); - }); - this.emitLine("@end"); - } - - private emitPseudoEnumImplementation(enumType: EnumType, enumName: Name) { - this.emitLine("@implementation ", enumName); - - const instances = [enumName, ".", staticEnumValuesIdentifier]; - this.emitMethod(["+ (NSDictionary *)", staticEnumValuesIdentifier], () => { - this.emitLine("static NSDictionary *", staticEnumValuesIdentifier, ";"); - this.emitLine( - "return ", - staticEnumValuesIdentifier, - " = ", - staticEnumValuesIdentifier, - " ? ", - staticEnumValuesIdentifier, - " : @{" - ); - this.indent(() => { - this.forEachEnumCase(enumType, "none", (_, jsonValue) => { - const value = ['@"', stringEscape(jsonValue), '"']; - this.emitLine(value, ": [[", enumName, " alloc] initWithValue:", value, "],"); - }); - }); - this.emitLine("};"); - }); - - this.ensureBlankLine(); - this.forEachEnumCase(enumType, "none", (name, jsonValue) => { - this.emitLine( - "+ (", - enumName, - " *)", - name, - " { return ", - instances, - '[@"', - stringEscape(jsonValue), - '"]; }' - ); - }); - this.ensureBlankLine(); - - this.emitMethod("+ (instancetype _Nullable)withValue:(NSString *)value", () => - this.emitLine("return ", instances, "[value];") - ); - - this.ensureBlankLine(); - this.emitMethod("- (instancetype)initWithValue:(NSString *)value", () => { - this.emitLine("if (self = [super init]) _value = value;"); - this.emitLine("return self;"); - }); - this.ensureBlankLine(); - - this.emitLine("- (NSUInteger)hash { return _value.hash; }"); - this.emitLine("@end"); - } - - protected emitSourceStructure(proposedFilename: string): void { - const fileMode = proposedFilename !== "stdout"; - if (!fileMode) { - // We don't have a filename, so we use a top-level name - const firstTopLevel = defined(mapFirst(this.topLevels)); - proposedFilename = this.sourcelikeToString(this.nameForNamedType(firstTopLevel)) + ".m"; - } - const [filename, extension] = splitExtension(proposedFilename); - - if (this._options.features.interface) { - this.startFile(filename, "h"); - - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else if (!this._options.justTypes) { - this.emitCommentLines(["To parse this JSON:", ""]); - this.emitLine("// NSError *error;"); - this.forEachTopLevel("none", (t, topLevelName) => { - const fromJsonExpression = - t instanceof ClassType - ? ["[", topLevelName, " fromJSON:json encoding:NSUTF8Encoding error:&error];"] - : [topLevelName, "FromJSON(json, NSUTF8Encoding, &error);"]; - this.emitLine( - "// ", - topLevelName, - " *", - this.variableNameForTopLevel(topLevelName), - " = ", - fromJsonExpression - ); - }); - } - - this.ensureBlankLine(); - this.emitLine(`#import `); - this.ensureBlankLine(); - - // Emit @class declarations for top-level array+maps and classes - this.forEachNamedType( - "none", - (_: ClassType, className: Name) => this.emitLine("@class ", className, ";"), - (_, enumName) => this.emitLine("@class ", enumName, ";"), - () => null - ); - this.ensureBlankLine(); - - this.ensureBlankLine(); - this.emitLine("NS_ASSUME_NONNULL_BEGIN"); - this.ensureBlankLine(); - - if (this.haveEnums) { - this.emitMark("Boxed enums"); - this.forEachEnum("leading-and-interposing", (t, n) => this.emitPseudoEnumInterface(t, n)); - } - - // Emit interfaces for top-level array+maps and classes - this.forEachTopLevel( - "leading-and-interposing", - (t, n) => this.emitNonClassTopLevelTypedef(t, n), - t => !(t instanceof ClassType) - ); - - const hasTopLevelNonClassTypes = iterableSome(this.topLevels, ([_, t]) => !(t instanceof ClassType)); - if (!this._options.justTypes && (hasTopLevelNonClassTypes || this._options.marshallingFunctions)) { - this.ensureBlankLine(); - this.emitMark("Top-level marshaling functions"); - this.forEachTopLevel( - "leading-and-interposing", - (t, n) => this.emitTopLevelFunctionDeclarations(t, n), - // Objective-C developers get freaked out by C functions, so we don't - // declare them for top-level object types (we always need them for non-object types) - t => this._options.marshallingFunctions || !(t instanceof ClassType) - ); - } - - this.emitMark("Object interfaces"); - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassInterface(c, className), - () => null, - () => null - ); - - this.ensureBlankLine(); - this.emitLine("NS_ASSUME_NONNULL_END"); - this.finishFile(); - } - - if (this._options.features.implementation) { - this.startFile(filename, extension); - - this.emitLine(`#import "${filename}.h"`); - this.ensureBlankLine(); - - if (!this._options.justTypes) { - this.ensureBlankLine(); - this.emitExtraComments("Shorthand for simple blocks"); - this.emitLine(`#define Ξ»(decl, expr) (^(decl) { return (expr); })`); - this.ensureBlankLine(); - this.emitExtraComments("nil β†’ NSNull conversion for JSON dictionaries"); - this.emitBlock("static id NSNullify(id _Nullable x)", () => - this.emitLine("return (x == nil || x == NSNull.null) ? NSNull.null : x;") - ); - this.ensureBlankLine(); - this.emitLine("NS_ASSUME_NONNULL_BEGIN"); - this.ensureBlankLine(); - - // We wouldn't need to emit these private iterfaces if we emitted implementations in forward-order - // but the code is more readable and explicit if we do this. - if (this._options.extraComments) { - this.emitMark("Private model interfaces"); - } - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, className: Name) => this.emitPrivateClassInterface(c, className), - () => null, - () => null - ); - - if (this.haveEnums) { - if (this._options.extraComments) { - this.ensureBlankLine(); - this.emitExtraComments( - "These enum-like reference types are needed so that enum", - "values can be contained by NSArray and NSDictionary." - ); - this.ensureBlankLine(); - } - this.forEachEnum("leading-and-interposing", (t, n) => this.emitPseudoEnumImplementation(t, n)); - } - - this.ensureBlankLine(); - this.emitMapFunction(); - this.ensureBlankLine(); - - this.emitMark("JSON serialization"); - this.forEachTopLevel("leading-and-interposing", (t, n) => this.emitTopLevelFunctions(t, n)); - } - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassImplementation(c, className), - () => null, - () => null - ); - - if (!this._options.justTypes) { - this.ensureBlankLine(); - this.emitLine("NS_ASSUME_NONNULL_END"); - } - - this.finishFile(); - } - } - private get needsMap(): boolean { - // TODO this isn't complete (needs union support, for example) - function needsMap(t: Type): boolean { - return ( - t instanceof MapType || - t instanceof ArrayType || - (t instanceof ClassType && mapSome(t.getProperties(), p => needsMap(p.type))) - ); - } - return iterableSome(this.typeGraph.allTypesUnordered(), needsMap); - } - - protected emitMapFunction() { - if (this.needsMap) { - this.emitMultiline(`static id map(id collection, id (^f)(id value)) { - id result = nil; - if ([collection isKindOfClass:NSArray.class]) { - result = [NSMutableArray arrayWithCapacity:[collection count]]; - for (id x in collection) [result addObject:f(x)]; - } else if ([collection isKindOfClass:NSDictionary.class]) { - result = [NSMutableDictionary dictionaryWithCapacity:[collection count]]; - for (id key in collection) [result setObject:f([collection objectForKey:key]) forKey:key]; - } - return result; -}`); - } - } -} diff --git a/packages/quicktype-core/src/language/Objective-C/ObjectiveCRenderer.ts b/packages/quicktype-core/src/language/Objective-C/ObjectiveCRenderer.ts new file mode 100644 index 000000000..5d0917db5 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/ObjectiveCRenderer.ts @@ -0,0 +1,1309 @@ +import { + iterableFirst, + iterableSome, + mapContains, + mapFirst, + mapSome, +} from "collection-utils"; + +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { + camelCase, + fastIsUpperCase, + repeatString, + stringEscape, +} from "../../support/Strings"; +import { assert, defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + EnumType, + MapType, + Type, + UnionType, +} from "../../Type"; +import { + isAnyOrNull, + matchType, + nullableFromUnion, +} from "../../Type/TypeUtils"; + +import { forbiddenPropertyNames, keywords } from "./constants"; +import type { objectiveCOptions } from "./language"; +import { + DEFAULT_CLASS_PREFIX, + forbiddenForEnumCases, + propertyNameStyle, + splitExtension, + staticEnumValuesIdentifier, + typeNameStyle, +} from "./utils"; + +type MemoryAttribute = "assign" | "strong" | "copy"; + +const DEBUG = false; + +export class ObjectiveCRenderer extends ConvenienceRenderer { + private _currentFilename: string | undefined; + + private readonly _classPrefix: string; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + + // Infer the class prefix from a top-level name if it's not given + if (_options.classPrefix === DEFAULT_CLASS_PREFIX) { + const aTopLevel = defined(iterableFirst(this.topLevels.keys())); + this._classPrefix = this.inferClassPrefix(aTopLevel); + } else { + this._classPrefix = _options.classPrefix; + } + } + + private inferClassPrefix(name: string): string { + const l = name.length; + let firstNonUpper = 0; + while ( + firstNonUpper < l && + fastIsUpperCase(name.charCodeAt(firstNonUpper)) + ) { + firstNonUpper += 1; + } + + if (firstNonUpper < 2) return DEFAULT_CLASS_PREFIX; + return name.slice(0, firstNonUpper - 1); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { + return { + names: forbiddenPropertyNames as unknown as string[], + includeGlobalForbidden: true, + }; + } + + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: forbiddenForEnumCases, includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("types", (rawName) => + typeNameStyle(this._classPrefix, rawName), + ); + } + + protected namerForObjectProperty(_: ClassType, p: ClassProperty): Namer { + // TODO why is underscore being removed? + return new Namer( + "properties", + (s) => propertyNameStyle(s, p.type.kind === "bool"), + ["_", "the", "one", "some", "another"], + ); + } + + protected makeUnionMemberNamer(): null { + return null; + } + + protected makeEnumCaseNamer(): Namer { + return new Namer("enum-cases", propertyNameStyle, []); + } + + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + return type; + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { lineStart: "/// " }); + } + + protected emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + protected emitMethod(declaration: Sourcelike, f: () => void): void { + this.emitLine(declaration); + this.emitLine("{"); + this.indent(f); + this.emitLine("}"); + } + + protected emitExtraComments(...comments: Sourcelike[]): void { + if (!this._options.extraComments) return; + for (const comment of comments) { + this.emitLine("// ", comment); + } + } + + protected startFile(basename: Sourcelike, extension: string): void { + assert( + this._currentFilename === undefined, + "Previous file wasn't finished", + ); + // FIXME: The filenames should actually be Sourcelikes, too + this._currentFilename = `${this.sourcelikeToString(basename)}.${extension}`; + } + + protected finishFile(): void { + super.finishFile(defined(this._currentFilename)); + this._currentFilename = undefined; + } + + protected memoryAttribute(t: Type, isNullable: boolean): MemoryAttribute { + return matchType( + t, + (_anyType) => "copy", + (_nullType) => "copy", + (_boolType) => (isNullable ? "strong" : "assign"), + (_integerType) => (isNullable ? "strong" : "assign"), + (_doubleType) => (isNullable ? "strong" : "assign"), + (_stringType) => "copy", + (_arrayType) => "copy", + (_classType) => "strong", + (_mapType) => "copy", + (_enumType) => "assign", + (unionType) => { + const nullable = nullableFromUnion(unionType); + return nullable !== null + ? this.memoryAttribute(nullable, true) + : "copy"; + }, + ); + } + + protected objcType(t: Type, nullableOrBoxed = false): [Sourcelike, string] { + return matchType<[Sourcelike, string]>( + t, + (_anyType) => ["id", ""], + // For now, we're treating nulls just like any + (_nullType) => ["id", ""], + (_boolType) => + nullableOrBoxed ? ["NSNumber", " *"] : ["BOOL", ""], + (_integerType) => + nullableOrBoxed ? ["NSNumber", " *"] : ["NSInteger", ""], + (_doubleType) => + nullableOrBoxed ? ["NSNumber", " *"] : ["double", ""], + (_stringType) => ["NSString", " *"], + (arrayType) => { + const itemType = arrayType.items; + const itemTypeName = this.objcType(itemType, true); + // NSArray* === NSArray* + if (isAnyOrNull(itemType)) { + return ["NSArray", " *"]; + } + + return [["NSArray<", itemTypeName, ">"], " *"]; + }, + (classType) => [this.nameForNamedType(classType), " *"], + (mapType) => [ + [ + "NSDictionary", + ], + " *", + ], + (enumType) => [this.nameForNamedType(enumType), " *"], + (unionType) => { + const nullable = nullableFromUnion(unionType); + return nullable !== null + ? this.objcType(nullable, true) + : ["id", ""]; + }, + ); + } + + private jsonType(t: Type): [Sourcelike, string] { + return matchType<[Sourcelike, string]>( + t, + (_anyType) => ["id", ""], + // For now, we're treating nulls just like any + (_nullType) => ["id", ""], + (_boolType) => ["NSNumber", " *"], + (_integerType) => ["NSNumber", " *"], + (_doubleType) => ["NSNumber", " *"], + (_stringType) => ["NSString", " *"], + (_arrayType) => ["NSArray", " *"], + (_classType) => ["NSDictionary", " *"], + (mapType) => [ + [ + "NSDictionary", + ], + " *", + ], + (_enumType) => ["NSString", " *"], + (unionType) => { + const nullable = nullableFromUnion(unionType); + return nullable !== null ? this.jsonType(nullable) : ["id", ""]; + }, + ); + } + + protected fromDynamicExpression( + t: Type, + ...dynamic: Sourcelike[] + ): Sourcelike { + return matchType( + t, + (_anyType) => dynamic, + (_nullType) => dynamic, + (_boolType) => dynamic, + (_integerType) => dynamic, + (_doubleType) => dynamic, + (_stringType) => dynamic, + (arrayType) => [ + "map(", + dynamic, + ", Ξ»(id x, ", + this.fromDynamicExpression(arrayType.items, "x"), + "))", + ], + (classType) => [ + "[", + this.nameForNamedType(classType), + " fromJSONDictionary:", + dynamic, + "]", + ], + (mapType) => [ + "map(", + dynamic, + ", Ξ»(id x, ", + this.fromDynamicExpression(mapType.values, "x"), + "))", + ], + (enumType) => [ + "[", + this.nameForNamedType(enumType), + " withValue:", + dynamic, + "]", + ], + (unionType) => { + const nullable = nullableFromUnion(unionType); + return nullable !== null + ? this.fromDynamicExpression(nullable, dynamic) + : dynamic; + }, + ); + } + + protected toDynamicExpression(t: Type, typed: Sourcelike): Sourcelike { + return matchType( + t, + (_anyType) => ["NSNullify(", typed, ")"], + (_nullType) => ["NSNullify(", typed, ")"], + // Sadly, KVC + (_boolType) => [typed, " ? @YES : @NO"], + (_integerType) => typed, + (_doubleType) => typed, + (_stringType) => typed, + (arrayType) => { + if (this.implicitlyConvertsFromJSON(arrayType)) { + // TODO check each value type + return typed; + } + + return [ + "map(", + typed, + ", Ξ»(id x, ", + this.toDynamicExpression(arrayType.items, "x"), + "))", + ]; + }, + (_classType) => ["[", typed, " JSONDictionary]"], + (mapType) => { + if (this.implicitlyConvertsFromJSON(mapType)) { + // TODO check each value type + return typed; + } + + return [ + "map(", + typed, + ", Ξ»(id x, ", + this.toDynamicExpression(mapType.values, "x"), + "))", + ]; + }, + (_enumType) => ["[", typed, " value]"], + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (this.implicitlyConvertsFromJSON(nullable)) { + return ["NSNullify(", typed, ")"]; + } + + return [ + "NSNullify(", + this.toDynamicExpression(nullable, typed), + ")", + ]; + } + + // TODO support unions + return typed; + }, + ); + } + + protected implicitlyConvertsFromJSON(t: Type): boolean { + if (t instanceof ClassType) { + return false; + } + if (t instanceof EnumType) { + return false; + } + if (t instanceof ArrayType) { + return this.implicitlyConvertsFromJSON(t.items); + } + if (t instanceof MapType) { + return this.implicitlyConvertsFromJSON(t.values); + } + if (t.isPrimitive()) { + return true; + } + if (t instanceof UnionType) { + const nullable = nullableFromUnion(t); + if (nullable !== null) { + return this.implicitlyConvertsFromJSON(nullable); + } + + // We don't support unions yet, so this is just untyped + return true; + } + + return false; + } + + protected implicitlyConvertsToJSON(t: Type): boolean { + return this.implicitlyConvertsFromJSON(t) && "bool" !== t.kind; + } + + protected emitPropertyAssignment( + propertyName: Name, + jsonName: string, + propertyType: Type, + ): void { + const name = ["_", propertyName]; + matchType( + propertyType, + (anyType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(anyType, name), + ";", + ), + (nullType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(nullType, name), + ";", + ), + (boolType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(boolType, name), + ";", + ), + (integerType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(integerType, name), + ";", + ), + (doubleType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(doubleType, name), + ";", + ), + (stringType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(stringType, name), + ";", + ), + (arrayType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(arrayType, name), + ";", + ), + (classType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(classType, ["(id)", name]), + ";", + ), + (mapType) => { + const itemType = mapType.values; + this.emitLine( + name, + " = map(", + name, + ", ", + [ + "Ξ»(id x, ", + this.fromDynamicExpression(itemType, "x"), + ")", + ], + ");", + ); + }, + (enumType) => + this.emitLine( + name, + " = ", + this.fromDynamicExpression(enumType, ["(id)", name]), + ";", + ), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + this.emitPropertyAssignment( + propertyName, + jsonName, + nullable, + ); + } else { + // TODO This is a union, but for now we just leave it dynamic + this.emitLine( + name, + " = ", + this.fromDynamicExpression(unionType, name), + ";", + ); + } + }, + ); + } + + protected emitPrivateClassInterface(_: ClassType, name: Name): void { + this.emitLine("@interface ", name, " (JSONConversion)"); + this.emitLine( + "+ (instancetype)fromJSONDictionary:(NSDictionary *)dict;", + ); + this.emitLine("- (NSDictionary *)JSONDictionary;"); + this.emitLine("@end"); + } + + protected pointerAwareTypeName(t: Type | [Sourcelike, string]): Sourcelike { + const name = t instanceof Type ? this.objcType(t) : t; + const isPointer = name[1] !== ""; + return isPointer ? name : [name, " "]; + } + + private emitNonClassTopLevelTypedef(t: Type, name: Name): void { + const nonPointerTypeName = this.objcType(t)[0]; + this.emitLine("typedef ", nonPointerTypeName, " ", name, ";"); + } + + private topLevelFromDataPrototype(name: Name): Sourcelike { + return [ + name, + " *_Nullable ", + name, + "FromData(NSData *data, NSError **error)", + ]; + } + + private topLevelFromJSONPrototype(name: Name): Sourcelike { + return [ + name, + " *_Nullable ", + name, + "FromJSON(NSString *json, NSStringEncoding encoding, NSError **error)", + ]; + } + + private topLevelToDataPrototype(name: Name, pad = false): Sourcelike { + const parameter = this.variableNameForTopLevel(name); + const padding = pad + ? repeatString( + " ", + this.sourcelikeToString(name).length - "NSData".length, + ) + : ""; + return [ + "NSData", + padding, + " *_Nullable ", + name, + "ToData(", + name, + " *", + parameter, + ", NSError **error)", + ]; + } + + private topLevelToJSONPrototype(name: Name, pad = false): Sourcelike { + const parameter = this.variableNameForTopLevel(name); + const padding = pad + ? repeatString( + " ", + this.sourcelikeToString(name).length - "NSString".length, + ) + : ""; + return [ + "NSString", + padding, + " *_Nullable ", + name, + "ToJSON(", + name, + " *", + parameter, + ", NSStringEncoding encoding, NSError **error)", + ]; + } + + private emitTopLevelFunctionDeclarations(_: Type, name: Name): void { + this.emitLine(this.topLevelFromDataPrototype(name), ";"); + this.emitLine(this.topLevelFromJSONPrototype(name), ";"); + this.emitLine(this.topLevelToDataPrototype(name, true), ";"); + this.emitLine(this.topLevelToJSONPrototype(name, true), ";"); + } + + private emitTryCatchAsError(inTry: () => void, inCatch: () => void): void { + this.emitLine("@try {"); + this.indent(inTry); + this.emitLine("} @catch (NSException *exception) {"); + this.indent(() => { + this.emitLine( + '*error = [NSError errorWithDomain:@"JSONSerialization" code:-1 userInfo:@{ @"exception": exception }];', + ); + inCatch(); + }); + this.emitLine("}"); + } + + private emitTopLevelFunctions(t: Type, name: Name): void { + const parameter = this.variableNameForTopLevel(name); + + this.ensureBlankLine(); + this.emitMethod(this.topLevelFromDataPrototype(name), () => { + this.emitTryCatchAsError( + () => { + this.emitLine( + "id json = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:error];", + ); + this.emitLine( + "return *error ? nil : ", + this.fromDynamicExpression(t, "json"), + ";", + ); + }, + () => this.emitLine("return nil;"), + ); + }); + + this.ensureBlankLine(); + this.emitMethod(this.topLevelFromJSONPrototype(name), () => { + this.emitLine( + "return ", + name, + "FromData([json dataUsingEncoding:encoding], error);", + ); + }); + + this.ensureBlankLine(); + this.emitMethod(this.topLevelToDataPrototype(name), () => { + this.emitTryCatchAsError( + () => { + this.emitLine( + "id json = ", + this.toDynamicExpression(t, parameter), + ";", + ); + this.emitLine( + "NSData *data = [NSJSONSerialization dataWithJSONObject:json options:kNilOptions error:error];", + ); + this.emitLine("return *error ? nil : data;"); + }, + () => this.emitLine("return nil;"), + ); + }); + + this.ensureBlankLine(); + this.emitMethod(this.topLevelToJSONPrototype(name), () => { + this.emitLine( + "NSData *data = ", + name, + "ToData(", + parameter, + ", error);", + ); + this.emitLine( + "return data ? [[NSString alloc] initWithData:data encoding:encoding] : nil;", + ); + }); + } + + private emitClassInterface(t: ClassType, className: Name): void { + const isTopLevel = mapContains(this.topLevels, t); + + this.emitDescription(this.descriptionForType(t)); + + this.emitLine("@interface ", className, " : NSObject"); + if (DEBUG) + this.emitLine("@property NSDictionary *_json;"); + this.emitPropertyTable(t, (name, _json, property) => { + const attributes = ["nonatomic"]; + // TODO offer a 'readonly' option + // TODO We must add "copy" if it's NSCopy, otherwise "strong" + if (property.type.isNullable) { + attributes.push("nullable"); + } + + attributes.push( + this.memoryAttribute(property.type, property.type.isNullable), + ); + return [ + ["@property ", ["(", attributes.join(", "), ")"], " "], + [this.pointerAwareTypeName(property.type), name, ";"], + ]; + }); + + if (!this._options.justTypes && isTopLevel) { + if (t.getProperties().size > 0) this.ensureBlankLine(); + + this.emitLine( + "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;", + ); + this.emitLine( + "+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error;", + ); + this.emitLine( + "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error;", + ); + this.emitLine( + "- (NSData *_Nullable)toData:(NSError *_Nullable *)error;", + ); + } + + this.emitLine("@end"); + } + + protected hasIrregularProperties(t: ClassType): boolean { + let irregular = false; + this.forEachClassProperty(t, "none", (name, jsonName) => { + irregular = + irregular || + stringEscape(jsonName) !== this.sourcelikeToString(name); + }); + return irregular; + } + + protected hasUnsafeProperties(t: ClassType): boolean { + let unsafe = false; + this.forEachClassProperty(t, "none", (_, __, property) => { + unsafe = unsafe || !this.implicitlyConvertsToJSON(property.type); + }); + return unsafe; + } + + // TODO Implement NSCopying + private emitClassImplementation(t: ClassType, className: Name): void { + const isTopLevel = mapContains(this.topLevels, t); + + const hasIrregularProperties = this.hasIrregularProperties(t); + const hasUnsafeProperties = this.hasUnsafeProperties(t); + + this.emitLine("@implementation ", className); + if (!this._options.justTypes) { + this.emitMethod( + "+ (NSDictionary *)properties", + () => { + this.emitLine( + "static NSDictionary *properties;", + ); + this.emitLine( + "return properties = properties ? properties : @{", + ); + this.indent(() => { + this.forEachClassProperty(t, "none", (name, jsonName) => + this.emitLine( + `@"${stringEscape(jsonName)}": @"`, + name, + '",', + ), + ); + }); + this.emitLine("};"); + }, + ); + this.ensureBlankLine(); + + if (isTopLevel) { + this.emitMethod( + "+ (_Nullable instancetype)fromData:(NSData *)data error:(NSError *_Nullable *)error", + () => { + this.emitLine( + "return ", + className, + "FromData(data, error);", + ); + }, + ); + this.ensureBlankLine(); + this.emitMethod( + "+ (_Nullable instancetype)fromJSON:(NSString *)json encoding:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", + () => { + this.emitLine( + "return ", + className, + "FromJSON(json, encoding, error);", + ); + }, + ); + this.ensureBlankLine(); + } + + this.emitMethod( + "+ (instancetype)fromJSONDictionary:(NSDictionary *)dict", + () => { + this.emitLine( + "return dict ? [[", + className, + " alloc] initWithJSONDictionary:dict] : nil;", + ); + }, + ); + this.ensureBlankLine(); + this.emitMethod( + "- (instancetype)initWithJSONDictionary:(NSDictionary *)dict", + () => { + this.emitBlock("if (self = [super init])", () => { + if (DEBUG) this.emitLine("__json = dict;"); + + this.emitLine( + "[self setValuesForKeysWithDictionary:dict];", + ); + this.forEachClassProperty( + t, + "none", + (name, jsonName, property) => { + if ( + !this.implicitlyConvertsFromJSON( + property.type, + ) + ) { + this.emitPropertyAssignment( + name, + jsonName, + property.type, + ); + } + }, + ); + }); + this.emitLine("return self;"); + }, + ); + + this.ensureBlankLine(); + this.emitMethod( + "- (void)setValue:(nullable id)value forKey:(NSString *)key", + () => { + this.emitLine( + "id resolved = ", + className, + ".properties[key];", + ); + this.emitLine( + "if (resolved) [super setValue:value forKey:resolved];", + ); + }, + ); + + // setNilValueForKey: is automatically invoked by the NSObject setValue:forKey: when it is passed nil for a scalar (a.k.a. non-nullable) object + // The approach below sets the scalar to 0 in this case, and therefore assumes an initializer with incomplete data shouldn't be grounds for raising an exception. + // Put another way, if the initializer didn't have a key at all, there wouldn't be an exception raised, so sending nil for something probably shouldn't cause one. + this.ensureBlankLine(); + this.emitMethod("- (void)setNilValueForKey:(NSString *)key", () => { + this.emitLine("id resolved = ", className, ".properties[key];"); + this.emitLine( + "if (resolved) [super setValue:@(0) forKey:resolved];", + ); + }); + + this.ensureBlankLine(); + this.emitMethod("- (NSDictionary *)JSONDictionary", () => { + if (!hasIrregularProperties && !hasUnsafeProperties) { + this.emitLine( + "return [self dictionaryWithValuesForKeys:", + className, + ".properties.allValues];", + ); + return; + } + + this.emitLine( + "id dict = [[self dictionaryWithValuesForKeys:", + className, + ".properties.allValues] mutableCopy];", + ); + this.ensureBlankLine(); + + if (hasIrregularProperties) { + this.emitExtraComments( + "Rewrite property names that differ in JSON", + ); + this.emitBlock( + ["for (id jsonName in ", className, ".properties)"], + () => { + this.emitLine( + "id propertyName = ", + className, + ".properties[jsonName];", + ); + this.emitBlock( + "if (![jsonName isEqualToString:propertyName])", + () => { + this.emitLine( + "dict[jsonName] = dict[propertyName];", + ); + this.emitLine( + "[dict removeObjectForKey:propertyName];", + ); + }, + ); + }, + ); + } + + if (hasUnsafeProperties) { + this.ensureBlankLine(); + this.emitExtraComments("Map values that need translation"); + this.emitLine("[dict addEntriesFromDictionary:@{"); + this.indent(() => { + this.forEachClassProperty( + t, + "none", + (propertyName, jsonKey, property) => { + if ( + !this.implicitlyConvertsToJSON( + property.type, + ) + ) { + const key = stringEscape(jsonKey); + const name = ["_", propertyName]; + this.emitLine( + '@"', + key, + '": ', + this.toDynamicExpression( + property.type, + name, + ), + ",", + ); + } + }, + ); + }); + this.emitLine("}];"); + } + + this.ensureBlankLine(); + this.emitLine("return dict;"); + }); + + if (isTopLevel) { + this.ensureBlankLine(); + this.emitMethod( + "- (NSData *_Nullable)toData:(NSError *_Nullable *)error", + () => { + this.emitLine( + "return ", + className, + "ToData(self, error);", + ); + }, + ); + this.ensureBlankLine(); + this.emitMethod( + "- (NSString *_Nullable)toJSON:(NSStringEncoding)encoding error:(NSError *_Nullable *)error", + () => { + this.emitLine( + "return ", + className, + "ToJSON(self, encoding, error);", + ); + }, + ); + } + } + + this.emitLine("@end"); + } + + protected emitMark(label: string): void { + this.ensureBlankLine(); + this.emitLine(`#pragma mark - ${label}`); + this.ensureBlankLine(); + } + + protected variableNameForTopLevel(name: Name): Sourcelike { + const camelCaseName = modifySource((serialized) => { + // 1. remove class prefix + serialized = serialized.slice(this._classPrefix.length); + // 2. camel case + return camelCase(serialized); + }, name); + return camelCaseName; + } + + private emitPseudoEnumInterface(enumType: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(enumType)); + + this.emitLine("@interface ", enumName, " : NSObject"); + this.emitLine("@property (nonatomic, readonly, copy) NSString *value;"); + this.emitLine("+ (instancetype _Nullable)withValue:(NSString *)value;"); + this.forEachEnumCase(enumType, "none", (name, _) => { + this.emitLine("+ (", enumName, " *)", name, ";"); + }); + this.emitLine("@end"); + } + + private emitPseudoEnumImplementation( + enumType: EnumType, + enumName: Name, + ): void { + this.emitLine("@implementation ", enumName); + + const instances = [enumName, ".", staticEnumValuesIdentifier]; + this.emitMethod( + [ + "+ (NSDictionary *)", + staticEnumValuesIdentifier, + ], + () => { + this.emitLine( + "static NSDictionary *", + staticEnumValuesIdentifier, + ";", + ); + this.emitLine( + "return ", + staticEnumValuesIdentifier, + " = ", + staticEnumValuesIdentifier, + " ? ", + staticEnumValuesIdentifier, + " : @{", + ); + this.indent(() => { + this.forEachEnumCase(enumType, "none", (_, jsonValue) => { + const value = ['@"', stringEscape(jsonValue), '"']; + this.emitLine( + value, + ": [[", + enumName, + " alloc] initWithValue:", + value, + "],", + ); + }); + }); + this.emitLine("};"); + }, + ); + + this.ensureBlankLine(); + this.forEachEnumCase(enumType, "none", (name, jsonValue) => { + this.emitLine( + "+ (", + enumName, + " *)", + name, + " { return ", + instances, + '[@"', + stringEscape(jsonValue), + '"]; }', + ); + }); + this.ensureBlankLine(); + + this.emitMethod( + "+ (instancetype _Nullable)withValue:(NSString *)value", + () => this.emitLine("return ", instances, "[value];"), + ); + + this.ensureBlankLine(); + this.emitMethod( + "- (instancetype)initWithValue:(NSString *)value", + () => { + this.emitLine("if (self = [super init]) _value = value;"); + this.emitLine("return self;"); + }, + ); + this.ensureBlankLine(); + + this.emitLine("- (NSUInteger)hash { return _value.hash; }"); + this.emitLine("@end"); + } + + protected emitSourceStructure(proposedFilename: string): void { + const fileMode = proposedFilename !== "stdout"; + if (!fileMode) { + // We don't have a filename, so we use a top-level name + const firstTopLevel = defined(mapFirst(this.topLevels)); + proposedFilename = + this.sourcelikeToString(this.nameForNamedType(firstTopLevel)) + + ".m"; + } + + const [filename, extension] = splitExtension(proposedFilename); + + if (this._options.features.interface) { + this.startFile(filename, "h"); + + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else if (!this._options.justTypes) { + this.emitCommentLines(["To parse this JSON:", ""]); + this.emitLine("// NSError *error;"); + this.forEachTopLevel("none", (t, topLevelName) => { + const fromJsonExpression = + t instanceof ClassType + ? [ + "[", + topLevelName, + " fromJSON:json encoding:NSUTF8Encoding error:&error];", + ] + : [ + topLevelName, + "FromJSON(json, NSUTF8Encoding, &error);", + ]; + this.emitLine( + "// ", + topLevelName, + " *", + this.variableNameForTopLevel(topLevelName), + " = ", + fromJsonExpression, + ); + }); + } + + this.ensureBlankLine(); + this.emitLine("#import "); + this.ensureBlankLine(); + + // Emit @class declarations for top-level array+maps and classes + this.forEachNamedType( + "none", + (_: ClassType, className: Name) => + this.emitLine("@class ", className, ";"), + (_, enumName) => this.emitLine("@class ", enumName, ";"), + () => null, + ); + this.ensureBlankLine(); + + this.ensureBlankLine(); + this.emitLine("NS_ASSUME_NONNULL_BEGIN"); + this.ensureBlankLine(); + + if (this.haveEnums) { + this.emitMark("Boxed enums"); + this.forEachEnum("leading-and-interposing", (t, n) => + this.emitPseudoEnumInterface(t, n), + ); + } + + // Emit interfaces for top-level array+maps and classes + this.forEachTopLevel( + "leading-and-interposing", + (t, n) => this.emitNonClassTopLevelTypedef(t, n), + (t) => !(t instanceof ClassType), + ); + + const hasTopLevelNonClassTypes = iterableSome( + this.topLevels, + ([_, t]) => !(t instanceof ClassType), + ); + if ( + !this._options.justTypes && + (hasTopLevelNonClassTypes || this._options.marshallingFunctions) + ) { + this.ensureBlankLine(); + this.emitMark("Top-level marshaling functions"); + this.forEachTopLevel( + "leading-and-interposing", + (t, n) => this.emitTopLevelFunctionDeclarations(t, n), + // Objective-C developers get freaked out by C functions, so we don't + // declare them for top-level object types (we always need them for non-object types) + (t) => + this._options.marshallingFunctions || + !(t instanceof ClassType), + ); + } + + this.emitMark("Object interfaces"); + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, className: Name) => + this.emitClassInterface(c, className), + () => null, + () => null, + ); + + this.ensureBlankLine(); + this.emitLine("NS_ASSUME_NONNULL_END"); + this.finishFile(); + } + + if (this._options.features.implementation) { + this.startFile(filename, extension); + + this.emitLine(`#import "${filename}.h"`); + this.ensureBlankLine(); + + if (!this._options.justTypes) { + this.ensureBlankLine(); + this.emitExtraComments("Shorthand for simple blocks"); + this.emitLine( + "#define Ξ»(decl, expr) (^(decl) { return (expr); })", + ); + this.ensureBlankLine(); + this.emitExtraComments( + "nil β†’ NSNull conversion for JSON dictionaries", + ); + this.emitBlock("static id NSNullify(id _Nullable x)", () => + this.emitLine( + "return (x == nil || x == NSNull.null) ? NSNull.null : x;", + ), + ); + this.ensureBlankLine(); + this.emitLine("NS_ASSUME_NONNULL_BEGIN"); + this.ensureBlankLine(); + + // We wouldn't need to emit these private iterfaces if we emitted implementations in forward-order + // but the code is more readable and explicit if we do this. + if (this._options.extraComments) { + this.emitMark("Private model interfaces"); + } + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, className: Name) => + this.emitPrivateClassInterface(c, className), + () => null, + () => null, + ); + + if (this.haveEnums) { + if (this._options.extraComments) { + this.ensureBlankLine(); + this.emitExtraComments( + "These enum-like reference types are needed so that enum", + "values can be contained by NSArray and NSDictionary.", + ); + this.ensureBlankLine(); + } + + this.forEachEnum("leading-and-interposing", (t, n) => + this.emitPseudoEnumImplementation(t, n), + ); + } + + this.ensureBlankLine(); + this.emitMapFunction(); + this.ensureBlankLine(); + + this.emitMark("JSON serialization"); + this.forEachTopLevel("leading-and-interposing", (t, n) => + this.emitTopLevelFunctions(t, n), + ); + } + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, className: Name) => + this.emitClassImplementation(c, className), + () => null, + () => null, + ); + + if (!this._options.justTypes) { + this.ensureBlankLine(); + this.emitLine("NS_ASSUME_NONNULL_END"); + } + + this.finishFile(); + } + } + + private get needsMap(): boolean { + // TODO this isn't complete (needs union support, for example) + function needsMap(t: Type): boolean { + return ( + t instanceof MapType || + t instanceof ArrayType || + (t instanceof ClassType && + mapSome(t.getProperties(), (p) => needsMap(p.type))) + ); + } + + return iterableSome(this.typeGraph.allTypesUnordered(), needsMap); + } + + protected emitMapFunction(): void { + if (this.needsMap) { + this.emitMultiline(`static id map(id collection, id (^f)(id value)) { + id result = nil; + if ([collection isKindOfClass:NSArray.class]) { + result = [NSMutableArray arrayWithCapacity:[collection count]]; + for (id x in collection) [result addObject:f(x)]; + } else if ([collection isKindOfClass:NSDictionary.class]) { + result = [NSMutableDictionary dictionaryWithCapacity:[collection count]]; + for (id key in collection) [result setObject:f([collection objectForKey:key]) forKey:key]; + } + return result; +}`); + } + } +} diff --git a/packages/quicktype-core/src/language/Objective-C/constants.ts b/packages/quicktype-core/src/language/Objective-C/constants.ts new file mode 100644 index 000000000..f483de6c2 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/constants.ts @@ -0,0 +1,82 @@ +export const keywords = [ + /* + "_Bool", + "_Complex", + "_Imaginary", + */ + "asm", + "atomic", + "auto", + "bool", + "break", + "case", + "char", + "const", + "continue", + "default", + "do", + "double", + "else", + "enum", + "extern", + "false", + "float", + "for", + "goto", + "if", + "inline", + "int", + "long", + "nil", + "nonatomic", + "register", + "restrict", + "retain", + "return", + "short", + "signed", + "sizeof", + "static", + "struct", + "switch", + "typedef", + "typeof", + "true", + "union", + "unsigned", + "void", + "volatile", + "while", +] as const; + +export const forbiddenPropertyNames = [ + "id", + "hash", + "description", + "init", + "copy", + "mutableCopy", + "superclass", + "debugDescription", + "new", +] as const; + +export const booleanPrefixes = [ + "is", + "are", + "were", + "was", + "will", + "all", + "some", + "many", + "has", + "have", + "had", + "does", + "do", + "requires", + "require", + "needs", + "need", +] as const; diff --git a/packages/quicktype-core/src/language/Objective-C/index.ts b/packages/quicktype-core/src/language/Objective-C/index.ts new file mode 100644 index 000000000..46926c8c6 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/index.ts @@ -0,0 +1,2 @@ +export { ObjectiveCTargetLanguage, objectiveCOptions } from "./language"; +export { ObjectiveCRenderer } from "./ObjectiveCRenderer"; diff --git a/packages/quicktype-core/src/language/Objective-C/language.ts b/packages/quicktype-core/src/language/Objective-C/language.ts new file mode 100644 index 000000000..09199da8d --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/language.ts @@ -0,0 +1,67 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { ObjectiveCRenderer } from "./ObjectiveCRenderer"; +import { DEFAULT_CLASS_PREFIX } from "./utils"; + +export const objectiveCOptions = { + features: new EnumOption( + "features", + "Interface and implementation", + { + all: { interface: true, implementation: true }, + interface: { interface: true, implementation: false }, + implementation: { interface: false, implementation: true }, + } as const, + "all", + ), + justTypes: new BooleanOption("just-types", "Plain types only", false), + marshallingFunctions: new BooleanOption( + "functions", + "C-style functions", + false, + ), + classPrefix: new StringOption( + "class-prefix", + "Class prefix", + "PREFIX", + DEFAULT_CLASS_PREFIX, + ), + extraComments: new BooleanOption("extra-comments", "Extra comments", false), +}; + +export const objectiveCLanguageConfig = { + displayName: "Objective-C", + names: ["objc", "objective-c", "objectivec"], + extension: "m", +} as const; + +export class ObjectiveCTargetLanguage extends TargetLanguage< + typeof objectiveCLanguageConfig +> { + public constructor() { + super(objectiveCLanguageConfig); + } + + public getOptions(): typeof objectiveCOptions { + return objectiveCOptions; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ObjectiveCRenderer { + return new ObjectiveCRenderer( + this, + renderContext, + getOptionValues(objectiveCOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/Objective-C/utils.ts b/packages/quicktype-core/src/language/Objective-C/utils.ts new file mode 100644 index 000000000..418dac6a0 --- /dev/null +++ b/packages/quicktype-core/src/language/Objective-C/utils.ts @@ -0,0 +1,94 @@ +import unicode from "unicode-properties"; + +import { + addPrefixIfNecessary, + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + splitIntoWords, + utf16LegalizeCharacters, +} from "../../support/Strings"; + +import { booleanPrefixes, forbiddenPropertyNames } from "./constants"; + +export const DEFAULT_CLASS_PREFIX = "QT"; + +export function typeNameStyle(prefix: string, original: string): string { + const words = splitIntoWords(original); + const result = combineWords( + words, + legalizeName, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter, + ); + return addPrefixIfNecessary(prefix, result); +} + +export function propertyNameStyle(original: string, isBool = false): string { + // Objective-C developers are uncomfortable with property "id" + // so we use an alternate name in this special case. + if (original === "id") { + original = "identifier"; + } + + let words = splitIntoWords(original); + + if (isBool) { + if (words.length === 0) { + words = [{ word: "flag", isAcronym: false }]; + } else if ( + !words[0].isAcronym && + // @ts-expect-error needs strict type + !booleanPrefixes.includes(words[0].word) + ) { + words = [{ word: "is", isAcronym: false }, ...words]; + } + } + + // Properties cannot even begin with any of the forbidden names + // For example, properies named new* are treated differently by ARC + // @ts-expect-error needs strict type + if (words.length > 0 && forbiddenPropertyNames.includes(words[0].word)) { + words = [{ word: "the", isAcronym: false }, ...words]; + } + + return combineWords( + words, + legalizeName, + allLowerWordStyle, + firstUpperWordStyle, + allLowerWordStyle, + allUpperWordStyle, + "", + isStartCharacter, + ); +} + +function isStartCharacter(utf16Unit: number): boolean { + return unicode.isAlphabetic(utf16Unit) || utf16Unit === 0x5f; // underscore +} + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + return ( + ["Nd", "Pc", "Mn", "Mc"].includes(category) || + isStartCharacter(utf16Unit) + ); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export const staticEnumValuesIdentifier = "values"; +export const forbiddenForEnumCases = ["new", staticEnumValuesIdentifier]; + +export function splitExtension(filename: string): [string, string] { + const i = filename.lastIndexOf("."); + const extension = i !== -1 ? filename.split(".").pop() : "m"; + filename = i !== -1 ? filename.slice(0, i) : filename; + return [filename, extension ?? "m"]; +} diff --git a/packages/quicktype-core/src/language/Php.ts b/packages/quicktype-core/src/language/Php.ts deleted file mode 100644 index 559bcda14..000000000 --- a/packages/quicktype-core/src/language/Php.ts +++ /dev/null @@ -1,1029 +0,0 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { DependencyName, funPrefixNamer, Name, Namer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, getOptionValues, Option, OptionValues } from "../RendererOptions"; -import { maybeAnnotated, Sourcelike } from "../Source"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - escapeNonPrintableMapper, - firstUpperWordStyle, - isAscii, - isDigit, - isLetter, - splitIntoWords, - standardUnicodeHexEscape, - utf16ConcatMap, - utf16LegalizeCharacters -} from "../support/Strings"; -import { defined } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { ClassProperty, ClassType, EnumType, Type, UnionType } from "../Type"; -import { directlyReachableSingleNamedType, matchType, nullableFromUnion } from "../TypeUtils"; -import { StringTypeMapping, TransformedStringTypeKind, PrimitiveStringTypeKind } from ".."; -import * as _ from "lodash"; - -export const phpOptions = { - withGet: new BooleanOption("with-get", "Create Getter", true), - fastGet: new BooleanOption("fast-get", "getter without validation", false), - withSet: new BooleanOption("with-set", "Create Setter", false), - withClosing: new BooleanOption("with-closing", "PHP Closing Tag", false), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal) -}; - -export class PhpTargetLanguage extends TargetLanguage { - constructor() { - super("PHP", ["php"], "php"); - } - - protected getOptions(): Option[] { - return _.values(phpOptions); - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PhpRenderer { - const options = getOptionValues(phpOptions, untypedOptionValues); - return new PhpRenderer(this, renderContext, options); - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date", "date"); // TODO is not implemented yet - mapping.set("time", "time"); // TODO is not implemented yet - mapping.set("uuid", "uuid"); // TODO is not implemented yet - mapping.set("date-time", "date-time"); - return mapping; - } -} - -export const stringEscape = utf16ConcatMap(escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape)); - -function isStartCharacter(codePoint: number): boolean { - if (codePoint === 0x5f) return true; // underscore - return isAscii(codePoint) && isLetter(codePoint); -} - -function isPartCharacter(codePoint: number): boolean { - return isStartCharacter(codePoint) || (isAscii(codePoint) && isDigit(codePoint)); -} - -const legalizeName = utf16LegalizeCharacters(isPartCharacter); - -export function phpNameStyle( - startWithUpper: boolean, - upperUnderscore: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upperUnderscore ? allUpperWordStyle : startWithUpper ? firstUpperWordStyle : allLowerWordStyle, - upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, - upperUnderscore || startWithUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - upperUnderscore ? "_" : "", - isStartCharacter - ); -} - -export interface FunctionNames { - readonly getter: Name; - readonly setter: Name; - readonly validate: Name; - readonly from: Name; - readonly to: Name; - readonly sample: Name; -} - -export class PhpRenderer extends ConvenienceRenderer { - private readonly _gettersAndSettersForPropertyName = new Map(); - private _haveEmittedLeadingComments = false; - protected readonly _converterClassname: string = "Converter"; - protected readonly _converterKeywords: string[] = []; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return this.getNameStyling("typeNamingFunction"); - } - - protected namerForObjectProperty(): Namer { - return this.getNameStyling("propertyNamingFunction"); - } - - protected makeUnionMemberNamer(): Namer { - return this.getNameStyling("propertyNamingFunction"); - } - - protected makeEnumCaseNamer(): Namer { - return this.getNameStyling("enumCaseNamingFunction"); - } - - protected unionNeedsName(u: UnionType): boolean { - return nullableFromUnion(u) === null; - } - - protected namedTypeToNameForTopLevel(type: Type): Type | undefined { - return directlyReachableSingleNamedType(type); - } - - protected makeNamesForPropertyGetterAndSetter( - _c: ClassType, - _className: Name, - _p: ClassProperty, - _jsonName: string, - name: Name - ): FunctionNames { - const getterName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `get_${lookup(name)}` - ); - const setterName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `set_${lookup(name)}` - ); - const validateName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `validate_${lookup(name)}` - ); - const fromName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `from_${lookup(name)}` - ); - const toName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `to_${lookup(name)}` - ); - const sampleName = new DependencyName( - this.getNameStyling("propertyNamingFunction"), - name.order, - lookup => `sample_${lookup(name)}` - ); - return { - getter: getterName, - setter: setterName, - validate: validateName, - from: fromName, - to: toName, - sample: sampleName - }; - } - - protected makePropertyDependencyNames( - c: ClassType, - className: Name, - p: ClassProperty, - jsonName: string, - name: Name - ): Name[] { - const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter(c, className, p, jsonName, name); - this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); - return [ - getterAndSetterNames.getter, - getterAndSetterNames.setter, - getterAndSetterNames.validate, - getterAndSetterNames.to, - getterAndSetterNames.from, - getterAndSetterNames.sample - ]; - } - - private getNameStyling(convention: string): Namer { - const styling: { [key: string]: Namer } = { - typeNamingFunction: funPrefixNamer("types", n => - phpNameStyle(true, false, n, acronymStyle(this._options.acronymStyle)) - ), - propertyNamingFunction: funPrefixNamer("properties", n => - phpNameStyle(false, false, n, acronymStyle(this._options.acronymStyle)) - ), - enumCaseNamingFunction: funPrefixNamer("enum-cases", n => - phpNameStyle(true, true, n, acronymStyle(this._options.acronymStyle)) - ) - }; - return styling[convention]; - } - - protected startFile(_basename: Sourcelike): void { - this.ensureBlankLine(); - if (!this._haveEmittedLeadingComments && this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - this.ensureBlankLine(); - this._haveEmittedLeadingComments = true; - } - } - - protected finishFile(): void { - // empty - } - - protected emitFileHeader(fileName: Sourcelike, _imports: string[]): void { - this.startFile(fileName); - this.emitLine("// This is a autogenerated file:", fileName); - this.ensureBlankLine(); - } - - public emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); - } - - public emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line, " {"); - this.indent(f); - this.emitLine("}"); - } - - protected phpType(_reference: boolean, t: Type, isOptional = false, prefix = "?", suffix = ""): Sourcelike { - function optionalize(s: Sourcelike) { - return [isOptional ? prefix : "", s, isOptional ? suffix : ""]; - } - return matchType( - t, - _anyType => maybeAnnotated(isOptional, anyTypeIssueAnnotation, "Object"), - _nullType => maybeAnnotated(isOptional, nullTypeIssueAnnotation, "Object"), - _boolType => optionalize("bool"), - _integerType => optionalize("int"), - _doubleType => optionalize("float"), - _stringType => optionalize("string"), - _arrayType => optionalize("array"), - classType => optionalize(this.nameForNamedType(classType)), - _mapType => optionalize("stdClass"), - enumType => optionalize(this.nameForNamedType(enumType)), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return this.phpType(true, nullable, true, prefix, suffix); - return this.nameForNamedType(unionType); - }, - transformedStringType => { - if (transformedStringType.kind === "time") { - throw Error('transformedStringType.kind === "time"'); - } - if (transformedStringType.kind === "date") { - throw Error('transformedStringType.kind === "date"'); - } - if (transformedStringType.kind === "date-time") { - return "DateTime"; - } - if (transformedStringType.kind === "uuid") { - throw Error('transformedStringType.kind === "uuid"'); - } - return "string"; - } - ); - } - - protected phpDocConvertType(className: Name, t: Type): Sourcelike { - return matchType( - t, - _anyType => "any", - _nullType => "null", - _boolType => "bool", - _integerType => "int", - _doubleType => "float", - _stringType => "string", - arrayType => [this.phpDocConvertType(className, arrayType.items), "[]"], - _classType => _classType.getCombinedName(), - _mapType => "stdClass", - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return [this.phpDocConvertType(className, nullable), "|null"]; - } - throw Error("union are not supported"); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return "DateTime"; - } - throw Error('transformedStringType.kind === "unknown"'); - } - ); - } - - protected phpConvertType(className: Name, t: Type): Sourcelike { - return matchType( - t, - _anyType => "any", - _nullType => "null", - _boolType => "bool", - _integerType => "int", - _doubleType => "float", - _stringType => "string", - _arrayType => "array", - _classType => "stdClass", - _mapType => "stdClass", - _enumType => "string", // TODO number this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return ["?", this.phpConvertType(className, nullable)]; - } - throw Error("union are not supported"); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return "string"; - } - throw Error('transformedStringType.kind === "unknown"'); - } - ); - } - - protected phpToObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { - return matchType( - t, - _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), - _nullType => this.emitLine(...lhs, ...args, "; /*null*/"), - _boolType => this.emitLine(...lhs, ...args, "; /*bool*/"), - _integerType => this.emitLine(...lhs, ...args, "; /*int*/"), - _doubleType => this.emitLine(...lhs, ...args, "; /*float*/"), - _stringType => this.emitLine(...lhs, ...args, "; /*string*/"), - arrayType => { - this.emitLine(...lhs, "array_map(function ($value) {"); - this.indent(() => { - this.phpToObjConvert(className, arrayType.items, ["return "], ["$value"]); - // this.emitLine("return $tmp;"); - }); - this.emitLine("}, ", ...args, ");"); - }, - _classType => this.emitLine(...lhs, ...args, "->to(); ", "/*class*/"), - mapType => { - this.emitBlock(["function to($my): stdClass"], () => { - this.emitLine("$out = new stdClass();"); - this.emitBlock(["foreach ($my as $k => $v)"], () => { - this.phpToObjConvert(className, mapType.values, ["$my->$k = "], ["$v"]); - }); - this.emitLine("return $out;"); - }); - this.emitLine("return to(", ...args, ");"); - }, - enumType => this.emitLine(...lhs, this.nameForNamedType(enumType), "::to(", ...args, "); ", "/*enum*/"), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - this.emitLine("if (!is_null(", ...args, ")) {"); - this.indent(() => this.phpToObjConvert(className, nullable, lhs, args)); - this.emitLine("} else {"); - this.indent(() => this.emitLine(...lhs, " null;")); - this.emitLine("}"); - return; - } - throw Error("union are not supported"); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - this.emitLine(...lhs, ...args, "->format(DateTimeInterface::ISO8601);"); - return; - } - throw Error('transformedStringType.kind === "unknown"'); - } - ); - } - - private transformDateTime(className: Name, attrName: Sourcelike, scopeAttrName: Sourcelike[]) { - this.emitBlock(["if (!is_a(", scopeAttrName, ", 'DateTime'))"], () => - this.emitLine("throw new Exception('Attribute Error:", className, "::", attrName, "');") - ); - // if (lhs !== undefined) { - // this.emitLine(lhs, "$tmp;"); - // } - } - - protected phpFromObjConvert(className: Name, t: Type, lhs: Sourcelike[], args: Sourcelike[]) { - return matchType( - t, - _anyType => this.emitLine(...lhs, ...args, "; /*any*/"), - _nullType => this.emitLine(...lhs, ...args, "; /*null*/"), - _boolType => this.emitLine(...lhs, ...args, "; /*bool*/"), - _integerType => this.emitLine(...lhs, ...args, "; /*int*/"), - _doubleType => this.emitLine(...lhs, ...args, "; /*float*/"), - _stringType => this.emitLine(...lhs, ...args, "; /*string*/"), - arrayType => { - this.emitLine(...lhs, " array_map(function ($value) {"); - this.indent(() => { - this.phpFromObjConvert(className, arrayType.items, ["return "], ["$value"]); - // this.emitLine("return $tmp;"); - }); - this.emitLine("}, ", ...args, ");"); - }, - classType => - this.emitLine(...lhs, this.nameForNamedType(classType), "::from(", ...args, "); ", "/*class*/"), - mapType => { - this.emitBlock(["function from($my): stdClass"], () => { - this.emitLine("$out = new stdClass();"); - this.emitBlock(["foreach ($my as $k => $v)"], () => { - this.phpFromObjConvert(className, mapType.values, ["$out->$k = "], ["$v"]); - }); - this.emitLine("return $out;"); - }); - this.emitLine("return from(", ...args, ");"); - }, - enumType => this.emitLine(...lhs, this.nameForNamedType(enumType), "::from(", ...args, "); ", "/*enum*/"), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - this.emitLine("if (!is_null(", ...args, ")) {"); - this.indent(() => this.phpFromObjConvert(className, nullable, lhs, args)); - this.emitLine("} else {"); - this.indent(() => this.emitLine("return null;")); - this.emitLine("}"); - return; - } - throw Error("union are not supported"); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - this.emitLine("$tmp = ", "DateTime::createFromFormat(DateTimeInterface::ISO8601, ", args, ");"); - this.transformDateTime(className, "", ["$tmp"]); - this.emitLine("return $tmp;"); - return; - } - throw Error('transformedStringType.kind === "unknown"'); - } - ); - } - - protected phpSampleConvert( - className: Name, - t: Type, - lhs: Sourcelike[], - args: Sourcelike[], - idx: number, - suffix: Sourcelike - ) { - return matchType( - t, - _anyType => - this.emitLine( - ...lhs, - "'AnyType::", - className, - "::", - args, - "::" + idx, - "'", - suffix, - "/*", - "" + idx, - ":", - args, - "*/" - ), - _nullType => this.emitLine(...lhs, "null", suffix, " /*", "" + idx, ":", args, "*/"), - _boolType => this.emitLine(...lhs, "true", suffix, " /*", "" + idx, ":", args, "*/"), - _integerType => this.emitLine(...lhs, "" + idx, suffix, " /*", "" + idx, ":", args, "*/"), - _doubleType => this.emitLine(...lhs, "" + (idx + idx / 1000), suffix, " /*", "" + idx, ":", args, "*/"), - _stringType => - this.emitLine( - ...lhs, - "'", - className, - "::", - args, - "::" + idx, - "'", - suffix, - " /*", - "" + idx, - ":", - args, - "*/" - ), - arrayType => { - this.emitLine(...lhs, " array("); - this.indent(() => { - this.phpSampleConvert(className, arrayType.items, [], [], idx, ""); - }); - this.emitLine("); /* ", "" + idx, ":", args, "*/"); - }, - classType => - this.emitLine( - ...lhs, - this.nameForNamedType(classType), - "::sample()", - suffix, - " /*", - "" + idx, - ":", - args, - "*/" - ), - mapType => { - this.emitBlock(["function sample(): stdClass"], () => { - this.emitLine("$out = new stdClass();"); - this.phpSampleConvert(className, mapType.values, ["$out->{'", className, "'} = "], args, idx, ";"); - this.emitLine("return $out;"); - }); - this.emitLine("return sample();"); - }, - enumType => this.emitLine(...lhs, this.nameForNamedType(enumType), "::sample()", suffix, " /*enum*/"), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - this.phpSampleConvert(className, nullable, lhs, args, idx, suffix); - return; - } - throw Error("union are not supported:" + unionType); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - const x = _.pad("" + (1 + (idx % 31)), 2, "0"); - this.emitLine( - ...lhs, - "DateTime::createFromFormat(DateTimeInterface::ISO8601, '", - `2020-12-${x}T12:${x}:${x}+00:00`, - "')", - suffix - ); - // this.emitLine("return sample();"); - return; - } - throw Error('transformedStringType.kind === "unknown"'); - } - ); - } - - private phpValidate(className: Name, t: Type, attrName: Sourcelike, scopeAttrName: string) { - const is = (isfn: string, myT: Name = className) => { - this.emitBlock(["if (!", isfn, "(", scopeAttrName, "))"], () => - this.emitLine('throw new Exception("Attribute Error:', myT, "::", attrName, '");') - ); - }; - return matchType( - t, - _anyType => is("defined"), - _nullType => is("is_null"), - _boolType => is("is_bool"), - _integerType => is("is_integer"), - _doubleType => is("is_float"), - _stringType => is("is_string"), - arrayType => { - is("is_array"); - this.emitLine("array_walk(", scopeAttrName, ", function(", scopeAttrName, "_v) {"); - this.indent(() => { - this.phpValidate(className, arrayType.items, attrName, `${scopeAttrName}_v`); - }); - this.emitLine("});"); - }, - _classType => { - this.emitLine(scopeAttrName, "->validate();"); - }, - mapType => { - this.emitLine("foreach (", scopeAttrName, " as $k => $v) {"); - this.indent(() => { - this.phpValidate(className, mapType.values, attrName, "$v"); - }); - this.emitLine("}"); - }, - enumType => { - this.emitLine(this.phpType(false, enumType), "::to(", scopeAttrName, ");"); - }, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - this.emitBlock(["if (!is_null(", scopeAttrName, "))"], () => { - this.phpValidate(className, nullable, attrName, scopeAttrName); - }); - return; - } - throw Error("not implemented"); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - this.transformDateTime(className, attrName, [scopeAttrName]); - return; - } - throw Error(`transformedStringType.kind === ${transformedStringType.kind}`); - } - ); - } - - protected emitFromMethod(names: FunctionNames, p: ClassProperty, className: Name, _name: Name, desc?: string[]) { - this.emitLine("/**"); - if (desc !== undefined) { - this.emitLine(" * ", desc); - this.emitLine(" *"); - } - // this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); - this.emitLine(" * @param ", this.phpConvertType(className, p.type), " $value"); - this.emitLine(" * @throws Exception"); - this.emitLine(" * @return ", this.phpType(false, p.type)); - this.emitLine(" */"); - this.emitBlock( - [ - "public static function ", - names.from, - "(", - this.phpConvertType(className, p.type), - " $value): ", - this.phpType(false, p.type) - ], - () => { - this.phpFromObjConvert(className, p.type, ["return "], [`$value`]); - // this.emitLine("return $ret;"); - } - ); - } - protected emitToMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { - this.emitLine("/**"); - if (desc !== undefined) { - this.emitLine(" * ", desc); - this.emitLine(" *"); - } - this.emitLine(" * @throws Exception"); - this.emitLine(" * @return ", this.phpConvertType(className, p.type)); - this.emitLine(" */"); - this.emitBlock(["public function ", names.to, "(): ", this.phpConvertType(className, p.type)], () => { - this.emitBlock(["if (", className, "::", names.validate, "($this->", name, ")) "], () => { - this.phpToObjConvert(className, p.type, ["return "], ["$this->", name]); - }); - this.emitLine("throw new Exception('never get to this ", className, "::", name, "');"); - }); - } - protected emitValidateMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { - this.emitLine("/**"); - if (desc !== undefined) { - this.emitLine(" * ", desc); - this.emitLine(" *"); - } - this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); - this.emitLine(" * @return bool"); - this.emitLine(" * @throws Exception"); - this.emitLine(" */"); - this.emitBlock( - ["public static function ", names.validate, "(", this.phpType(false, p.type), " $value): bool"], - () => { - this.phpValidate(className, p.type, name, `$value`); - this.emitLine("return true;"); - } - ); - } - protected emitGetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { - if (this._options.withGet) { - this.emitLine("/**"); - if (desc !== undefined) { - this.emitLine(" * ", desc); - this.emitLine(" *"); - } - if (!this._options.fastGet) { - this.emitLine(` * @throws Exception`); - } - const rendered = this.phpType(false, p.type); - this.emitLine(" * @return ", rendered); - this.emitLine(" */"); - this.emitBlock(["public function ", names.getter, "(): ", rendered], () => { - if (!this._options.fastGet) { - this.emitBlock(["if (", className, "::", names.validate, "($this->", name, ")) "], () => { - this.emitLine("return $this->", name, ";"); - }); - this.emitLine( - "throw new Exception('never get to ", - names.getter, - " ", - className, - "::", - name, - "');" - ); - } else { - this.emitLine("return $this->", name, ";"); - } - }); - } - } - protected emitSetMethod(names: FunctionNames, p: ClassProperty, className: Name, name: Name, desc?: string[]) { - if (this._options.withSet) { - this.emitLine("/**"); - if (desc !== undefined) { - this.emitLine(" * ", desc); - this.emitLine(" *"); - } - this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); - this.emitLine(` * @throws Exception`); - this.emitLine(" */"); - this.emitBlock(["public function ", names.setter, "(", this.phpType(false, p.type), " $value)"], () => { - this.emitBlock(["if (", className, "::", names.validate, "($value)) "], () => { - this.emitLine("$this->", name, " = $value;"); - }); - }); - } - } - protected emitSampleMethod( - names: FunctionNames, - p: ClassProperty, - className: Name, - name: Name, - desc: string[] | undefined, - idx: number - ) { - if (this._options.withGet) { - this.emitLine("/**"); - if (desc !== undefined) { - this.emitLine(" * ", desc); - this.emitLine(" *"); - } - const rendered = this.phpType(false, p.type); - this.emitLine(" * @return ", rendered); - this.emitLine(" */"); - this.emitBlock(["public static function ", names.sample, "(): ", rendered], () => { - this.phpSampleConvert(className, p.type, ["return "], [name], idx, ";"); - }); - } - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - this.emitFileHeader(className, []); - - this.emitBlock(["class ", className], () => { - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - this.emitLine( - "private ", - this.phpType(false, p.type), - " $", - name, - "; // json:", - jsonName, - " ", - p.type.isNullable ? "Optional" : "Required" - ); - }); - - this.ensureBlankLine(); - const comments: Sourcelike[][] = []; - const args: Sourcelike[][] = []; - let prefix = ""; - this.forEachClassProperty(c, "none", (name, __, p) => { - args.push([prefix, this.phpType(false, p.type), " $", name]); - prefix = ", "; - comments.push([" * @param ", this.phpType(false, p.type, false, "", "|null"), " $", name, "\n"]); - }); - this.emitBlock(["/**\n", ...comments, " */\n", "public function __construct(", ...args, ")"], () => { - this.forEachClassProperty(c, "none", name => { - this.emitLine("$this->", name, " = $", name, ";"); - }); - }); - - let idx = 31; - this.forEachClassProperty(c, "leading-and-interposing", (name, jsonName, p) => { - const desc = this.descriptionForClassProperty(c, jsonName); - const names = defined(this._gettersAndSettersForPropertyName.get(name)); - - this.ensureBlankLine(); - this.emitFromMethod(names, p, className, name, desc); - this.ensureBlankLine(); - this.emitToMethod(names, p, className, name, desc); - this.ensureBlankLine(); - this.emitValidateMethod(names, p, className, name, desc); - this.ensureBlankLine(); - this.emitGetMethod(names, p, className, name, desc); - this.ensureBlankLine(); - this.emitSetMethod(names, p, className, name, desc); - this.ensureBlankLine(); - this.emitSampleMethod(names, p, className, name, desc, idx++); - }); - - this.ensureBlankLine(); - this.emitBlock( - ["/**\n", ` * @throws Exception\n`, ` * @return bool\n`, " */\n", "public function validate(): bool"], - () => { - let lines: Sourcelike[][] = []; - let p = "return "; - this.forEachClassProperty(c, "none", (name, _jsonName, _p) => { - const names = defined(this._gettersAndSettersForPropertyName.get(name)); - lines.push([p, className, "::", names.validate, "($this->", name, ")"]); - p = "|| "; - }); - lines.forEach((line, jdx) => { - this.emitLine(...line, lines.length === jdx + 1 ? ";" : ""); - }); - } - ); - - this.ensureBlankLine(); - this.emitBlock( - [ - "/**\n", - ` * @return stdClass\n`, - ` * @throws Exception\n`, - " */\n", - "public function to(): stdClass " - ], - () => { - this.emitLine("$out = new stdClass();"); - this.forEachClassProperty(c, "none", (name, jsonName) => { - const names = defined(this._gettersAndSettersForPropertyName.get(name)); - this.emitLine("$out->{'", jsonName, "'} = $this->", names.to, "();"); - }); - this.emitLine("return $out;"); - } - ); - - this.ensureBlankLine(); - this.emitBlock( - [ - "/**\n", - ` * @param stdClass $obj\n`, - ` * @return `, - className, - `\n`, - ` * @throws Exception\n`, - " */\n", - "public static function from(stdClass $obj): ", - className - ], - () => { - if (this._options.fastGet) { - this.forEachClassProperty(c, "none", name => { - const names = defined(this._gettersAndSettersForPropertyName.get(name)); - this.emitLine(className, "::", names.validate, "($this->", name, ", true);"); - }); - } - this.emitLine("return new ", className, "("); - let comma = " "; - this.forEachClassProperty(c, "none", (name, jsonName) => { - const names = defined(this._gettersAndSettersForPropertyName.get(name)); - this.emitLine(comma, className, "::", names.from, "($obj->{'", jsonName, "'})"); - comma = ","; - }); - this.emitLine(");"); - } - ); - this.ensureBlankLine(); - this.emitBlock( - ["/**\n", " * @return ", className, "\n", " */\n", "public static function sample(): ", className], - () => { - this.emitLine("return new ", className, "("); - let comma = " "; - this.forEachClassProperty(c, "none", name => { - const names = defined(this._gettersAndSettersForPropertyName.get(name)); - this.emitLine(comma, className, "::", names.sample, "()"); - comma = ","; - }); - this.emitLine(");"); - } - ); - }); - this.finishFile(); - } - - protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { - // empty - } - - protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { - // empty - } - - protected emitUnionDefinition(_u: UnionType, _unionName: Name): void { - throw Error("emitUnionDefinition not implemented"); - } - - protected emitEnumSerializationAttributes(_e: EnumType) { - // Empty - } - - protected emitEnumDeserializationAttributes(_e: EnumType) { - // Empty - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitFileHeader(enumName, []); - this.emitDescription(this.descriptionForType(e)); - const caseNames: Sourcelike[] = []; - caseNames.push(";"); - const enumSerdeType = "string"; - this.emitBlock(["class ", enumName], () => { - this.forEachEnumCase(e, "none", (name, _jsonName) => { - this.emitLine("public static ", enumName, " $", name, ";"); - }); - - this.emitBlock("public static function init()", () => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine(enumName, "::$", name, " = new ", enumName, "('", jsonName, "');"); - }); - }); - - this.emitLine("private ", enumSerdeType, " $enum;"); - this.emitBlock(["public function __construct(", enumSerdeType, " $enum)"], () => { - this.emitLine("$this->enum = $enum;"); - }); - - this.ensureBlankLine(); - this.emitEnumSerializationAttributes(e); - - this.emitBlock( - [ - "/**\n", - ` * @param `, - enumName, - `\n`, - ` * @return `, - enumSerdeType, - `\n`, - ` * @throws Exception\n`, - " */\n", - "public static function to(", - enumName, - " $obj): ", - enumSerdeType - ], - () => { - this.emitLine("switch ($obj->enum) {"); - this.indent(() => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - // Todo String or Number - this.emitLine( - "case ", - enumName, - "::$", - name, - "->enum: return '", - stringEscape(jsonName), - "';" - ); - }); - }); - this.emitLine("}"); - this.emitLine("throw new Exception('the give value is not an enum-value.');"); - } - ); - this.ensureBlankLine(); - this.emitEnumDeserializationAttributes(e); - - this.emitBlock( - [ - "/**\n", - ` * @param mixed\n`, - ` * @return `, - enumName, - "\n", - ` * @throws Exception\n`, - " */\n", - "public static function from($obj): ", - enumName - ], - () => { - this.emitLine("switch ($obj) {"); - this.indent(() => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - // Todo String or Enum - this.emitLine("case '", stringEscape(jsonName), "': return ", enumName, "::$", name, ";"); - }); - }); - this.emitLine("}"); - this.emitLine('throw new Exception("Cannot deserialize ', enumName, '");'); - } - ); - this.ensureBlankLine(); - this.emitBlock( - ["/**\n", ` * @return `, enumName, "\n", " */\n", "public static function sample(): ", enumName], - () => { - const lines: Sourcelike[] = []; - this.forEachEnumCase(e, "none", name => { - lines.push([enumName, "::$", name]); - }); - this.emitLine("return ", lines[0], ";"); - } - ); - }); - this.emitLine(enumName, "::init();"); - this.finishFile(); - } - - protected emitSourceStructure(givenFilename: string): void { - this.emitLine(" this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - if (this._options.withClosing) { - this.emitLine("?>"); - } - super.finishFile(defined(givenFilename)); - } -} diff --git a/packages/quicktype-core/src/language/Php/PhpRenderer.ts b/packages/quicktype-core/src/language/Php/PhpRenderer.ts new file mode 100644 index 000000000..8dfb3c5e6 --- /dev/null +++ b/packages/quicktype-core/src/language/Php/PhpRenderer.ts @@ -0,0 +1,1489 @@ +import * as _ from "lodash"; + +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { + DependencyName, + type Name, + type Namer, + funPrefixNamer, +} from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import type { + ClassProperty, + ClassType, + EnumType, + Type, + UnionType, +} from "../../Type"; +import { + directlyReachableSingleNamedType, + matchType, + nullableFromUnion, +} from "../../Type/TypeUtils"; + +import type { phpOptions } from "./language"; +import { phpNameStyle, stringEscape } from "./utils"; + +export interface FunctionNames { + readonly from: Name; + readonly getter: Name; + readonly sample: Name; + readonly setter: Name; + readonly to: Name; + readonly validate: Name; +} + +export class PhpRenderer extends ConvenienceRenderer { + private readonly _gettersAndSettersForPropertyName = new Map< + Name, + FunctionNames + >(); + + private _haveEmittedLeadingComments = false; + + protected readonly _converterClassname: string = "Converter"; + + protected readonly _converterKeywords: string[] = []; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return this.getNameStyling("typeNamingFunction"); + } + + protected namerForObjectProperty(): Namer { + return this.getNameStyling("propertyNamingFunction"); + } + + protected makeUnionMemberNamer(): Namer { + return this.getNameStyling("propertyNamingFunction"); + } + + protected makeEnumCaseNamer(): Namer { + return this.getNameStyling("enumCaseNamingFunction"); + } + + protected unionNeedsName(u: UnionType): boolean { + return nullableFromUnion(u) === null; + } + + protected namedTypeToNameForTopLevel(type: Type): Type | undefined { + return directlyReachableSingleNamedType(type); + } + + protected makeNamesForPropertyGetterAndSetter( + _c: ClassType, + _className: Name, + _p: ClassProperty, + _jsonName: string, + name: Name, + ): FunctionNames { + const getterName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `get_${lookup(name)}`, + ); + const setterName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `set_${lookup(name)}`, + ); + const validateName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `validate_${lookup(name)}`, + ); + const fromName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `from_${lookup(name)}`, + ); + const toName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `to_${lookup(name)}`, + ); + const sampleName = new DependencyName( + this.getNameStyling("propertyNamingFunction"), + name.order, + (lookup) => `sample_${lookup(name)}`, + ); + return { + getter: getterName, + setter: setterName, + validate: validateName, + from: fromName, + to: toName, + sample: sampleName, + }; + } + + protected makePropertyDependencyNames( + c: ClassType, + className: Name, + p: ClassProperty, + jsonName: string, + name: Name, + ): Name[] { + const getterAndSetterNames = this.makeNamesForPropertyGetterAndSetter( + c, + className, + p, + jsonName, + name, + ); + this._gettersAndSettersForPropertyName.set(name, getterAndSetterNames); + return [ + getterAndSetterNames.getter, + getterAndSetterNames.setter, + getterAndSetterNames.validate, + getterAndSetterNames.to, + getterAndSetterNames.from, + getterAndSetterNames.sample, + ]; + } + + private getNameStyling(convention: string): Namer { + const styling: { [key: string]: Namer } = { + typeNamingFunction: funPrefixNamer("types", (n) => + phpNameStyle( + true, + false, + n, + acronymStyle(this._options.acronymStyle), + ), + ), + propertyNamingFunction: funPrefixNamer("properties", (n) => + phpNameStyle( + false, + false, + n, + acronymStyle(this._options.acronymStyle), + ), + ), + enumCaseNamingFunction: funPrefixNamer("enum-cases", (n) => + phpNameStyle( + true, + true, + n, + acronymStyle(this._options.acronymStyle), + ), + ), + }; + return styling[convention]; + } + + protected startFile(_basename: Sourcelike): void { + this.ensureBlankLine(); + if ( + !this._haveEmittedLeadingComments && + this.leadingComments !== undefined + ) { + this.emitComments(this.leadingComments); + this.ensureBlankLine(); + this._haveEmittedLeadingComments = true; + } + } + + protected finishFile(): void { + // empty + } + + protected emitFileHeader(fileName: Sourcelike, _imports: string[]): void { + this.startFile(fileName); + this.emitLine("// This is a autogenerated file:", fileName); + this.ensureBlankLine(); + } + + public emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); + } + + public emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + protected phpType( + _reference: boolean, + t: Type, + isOptional = false, + prefix = "?", + suffix = "", + ): Sourcelike { + function optionalize(s: Sourcelike): Sourcelike { + return [isOptional ? prefix : "", s, isOptional ? suffix : ""]; + } + + return matchType( + t, + (_anyType) => + maybeAnnotated(isOptional, anyTypeIssueAnnotation, "Object"), + (_nullType) => + maybeAnnotated(isOptional, nullTypeIssueAnnotation, "Object"), + (_boolType) => optionalize("bool"), + (_integerType) => optionalize("int"), + (_doubleType) => optionalize("float"), + (_stringType) => optionalize("string"), + (_arrayType) => optionalize("array"), + (classType) => optionalize(this.nameForNamedType(classType)), + (_mapType) => optionalize("stdClass"), + (enumType) => optionalize(this.nameForNamedType(enumType)), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) + return this.phpType(true, nullable, true, prefix, suffix); + return this.nameForNamedType(unionType); + }, + (transformedStringType) => { + if (transformedStringType.kind === "time") { + throw Error('transformedStringType.kind === "time"'); + } + + if (transformedStringType.kind === "date") { + throw Error('transformedStringType.kind === "date"'); + } + + if (transformedStringType.kind === "date-time") { + return "DateTime"; + } + + if (transformedStringType.kind === "uuid") { + throw Error('transformedStringType.kind === "uuid"'); + } + + return "string"; + }, + ); + } + + protected phpDocConvertType(className: Name, t: Type): Sourcelike { + return matchType( + t, + (_anyType) => "any", + (_nullType) => "null", + (_boolType) => "bool", + (_integerType) => "int", + (_doubleType) => "float", + (_stringType) => "string", + (arrayType) => [ + this.phpDocConvertType(className, arrayType.items), + "[]", + ], + (_classType) => _classType.getCombinedName(), + (_mapType) => "stdClass", + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return [ + this.phpDocConvertType(className, nullable), + "|null", + ]; + } + + throw Error("union are not supported"); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return "DateTime"; + } + + throw Error('transformedStringType.kind === "unknown"'); + }, + ); + } + + protected phpConvertType(className: Name, t: Type): Sourcelike { + return matchType( + t, + (_anyType) => "any", + (_nullType) => "null", + (_boolType) => "bool", + (_integerType) => "int", + (_doubleType) => "float", + (_stringType) => "string", + (_arrayType) => "array", + (_classType) => "stdClass", + (_mapType) => "stdClass", + (_enumType) => "string", // TODO number this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return ["?", this.phpConvertType(className, nullable)]; + } + + throw Error("union are not supported"); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return "string"; + } + + throw Error('transformedStringType.kind === "unknown"'); + }, + ); + } + + protected phpToObjConvert( + className: Name, + t: Type, + lhs: Sourcelike[], + args: Sourcelike[], + ): void { + matchType( + t, + (_anyType) => this.emitLine(...lhs, ...args, "; /*any*/"), + (_nullType) => this.emitLine(...lhs, ...args, "; /*null*/"), + (_boolType) => this.emitLine(...lhs, ...args, "; /*bool*/"), + (_integerType) => this.emitLine(...lhs, ...args, "; /*int*/"), + (_doubleType) => this.emitLine(...lhs, ...args, "; /*float*/"), + (_stringType) => this.emitLine(...lhs, ...args, "; /*string*/"), + (arrayType) => { + this.emitLine(...lhs, "array_map(function ($value) {"); + this.indent(() => { + this.phpToObjConvert( + className, + arrayType.items, + ["return "], + ["$value"], + ); + // this.emitLine("return $tmp;"); + }); + this.emitLine("}, ", ...args, ");"); + }, + (_classType) => + this.emitLine(...lhs, ...args, "->to(); ", "/*class*/"), + (mapType) => { + this.emitBlock(["function to($my): stdClass"], () => { + this.emitLine("$out = new stdClass();"); + this.emitBlock(["foreach ($my as $k => $v)"], () => { + this.phpToObjConvert( + className, + mapType.values, + ["$my->$k = "], + ["$v"], + ); + }); + this.emitLine("return $out;"); + }); + this.emitLine("return to(", ...args, ");"); + }, + (enumType) => + this.emitLine( + ...lhs, + this.nameForNamedType(enumType), + "::to(", + ...args, + "); ", + "/*enum*/", + ), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + this.emitLine("if (!is_null(", ...args, ")) {"); + this.indent(() => + this.phpToObjConvert(className, nullable, lhs, args), + ); + this.emitLine("} else {"); + this.indent(() => this.emitLine(...lhs, " null;")); + this.emitLine("}"); + return; + } + + throw Error("union are not supported"); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + this.emitLine( + ...lhs, + ...args, + "->format(DateTimeInterface::ISO8601);", + ); + return; + } + + throw Error('transformedStringType.kind === "unknown"'); + }, + ); + } + + private transformDateTime( + className: Name, + attrName: Sourcelike, + scopeAttrName: Sourcelike[], + ): void { + this.emitBlock(["if (!is_a(", scopeAttrName, ", 'DateTime'))"], () => + this.emitLine( + "throw new Exception('Attribute Error:", + className, + "::", + attrName, + "');", + ), + ); + // if (lhs !== undefined) { + // this.emitLine(lhs, "$tmp;"); + // } + } + + protected phpFromObjConvert( + className: Name, + t: Type, + lhs: Sourcelike[], + args: Sourcelike[], + ): void { + matchType( + t, + (_anyType) => this.emitLine(...lhs, ...args, "; /*any*/"), + (_nullType) => this.emitLine(...lhs, ...args, "; /*null*/"), + (_boolType) => this.emitLine(...lhs, ...args, "; /*bool*/"), + (_integerType) => this.emitLine(...lhs, ...args, "; /*int*/"), + (_doubleType) => this.emitLine(...lhs, ...args, "; /*float*/"), + (_stringType) => this.emitLine(...lhs, ...args, "; /*string*/"), + (arrayType) => { + this.emitLine(...lhs, " array_map(function ($value) {"); + this.indent(() => { + this.phpFromObjConvert( + className, + arrayType.items, + ["return "], + ["$value"], + ); + // this.emitLine("return $tmp;"); + }); + this.emitLine("}, ", ...args, ");"); + }, + (classType) => + this.emitLine( + ...lhs, + this.nameForNamedType(classType), + "::from(", + ...args, + "); ", + "/*class*/", + ), + (mapType) => { + this.emitBlock(["function from($my): stdClass"], () => { + this.emitLine("$out = new stdClass();"); + this.emitBlock(["foreach ($my as $k => $v)"], () => { + this.phpFromObjConvert( + className, + mapType.values, + ["$out->$k = "], + ["$v"], + ); + }); + this.emitLine("return $out;"); + }); + this.emitLine("return from(", ...args, ");"); + }, + (enumType) => + this.emitLine( + ...lhs, + this.nameForNamedType(enumType), + "::from(", + ...args, + "); ", + "/*enum*/", + ), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + this.emitLine("if (!is_null(", ...args, ")) {"); + this.indent(() => + this.phpFromObjConvert(className, nullable, lhs, args), + ); + this.emitLine("} else {"); + this.indent(() => this.emitLine("return null;")); + this.emitLine("}"); + return; + } + + throw Error("union are not supported"); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + this.emitLine( + "$tmp = ", + "DateTime::createFromFormat(DateTimeInterface::ISO8601, ", + args, + ");", + ); + this.transformDateTime(className, "", ["$tmp"]); + this.emitLine("return $tmp;"); + return; + } + + throw Error('transformedStringType.kind === "unknown"'); + }, + ); + } + + protected phpSampleConvert( + className: Name, + t: Type, + lhs: Sourcelike[], + args: Sourcelike[], + idx: number, + suffix: Sourcelike, + ): void { + matchType( + t, + (_anyType) => + this.emitLine( + ...lhs, + "'AnyType::", + className, + "::", + args, + "::" + idx, + "'", + suffix, + "/*", + "" + idx, + ":", + args, + "*/", + ), + (_nullType) => + this.emitLine( + ...lhs, + "null", + suffix, + " /*", + "" + idx, + ":", + args, + "*/", + ), + (_boolType) => + this.emitLine( + ...lhs, + "true", + suffix, + " /*", + "" + idx, + ":", + args, + "*/", + ), + (_integerType) => + this.emitLine( + ...lhs, + "" + idx, + suffix, + " /*", + "" + idx, + ":", + args, + "*/", + ), + (_doubleType) => + this.emitLine( + ...lhs, + "" + (idx + idx / 1000), + suffix, + " /*", + "" + idx, + ":", + args, + "*/", + ), + (_stringType) => + this.emitLine( + ...lhs, + "'", + className, + "::", + args, + "::" + idx, + "'", + suffix, + " /*", + "" + idx, + ":", + args, + "*/", + ), + (arrayType) => { + this.emitLine(...lhs, " array("); + this.indent(() => { + this.phpSampleConvert( + className, + arrayType.items, + [], + [], + idx, + "", + ); + }); + this.emitLine("); /* ", "" + idx, ":", args, "*/"); + }, + (classType) => + this.emitLine( + ...lhs, + this.nameForNamedType(classType), + "::sample()", + suffix, + " /*", + "" + idx, + ":", + args, + "*/", + ), + (mapType) => { + this.emitBlock(["function sample(): stdClass"], () => { + this.emitLine("$out = new stdClass();"); + this.phpSampleConvert( + className, + mapType.values, + ["$out->{'", className, "'} = "], + args, + idx, + ";", + ); + this.emitLine("return $out;"); + }); + this.emitLine("return sample();"); + }, + (enumType) => + this.emitLine( + ...lhs, + this.nameForNamedType(enumType), + "::sample()", + suffix, + " /*enum*/", + ), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + this.phpSampleConvert( + className, + nullable, + lhs, + args, + idx, + suffix, + ); + return; + } + + throw Error(`union are not supported:${unionType}`); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + const x = _.pad("" + (1 + (idx % 31)), 2, "0"); + this.emitLine( + ...lhs, + "DateTime::createFromFormat(DateTimeInterface::ISO8601, '", + `2020-12-${x}T12:${x}:${x}+00:00`, + "')", + suffix, + ); + // this.emitLine("return sample();"); + return; + } + + throw Error('transformedStringType.kind === "unknown"'); + }, + ); + } + + private phpValidate( + className: Name, + t: Type, + attrName: Sourcelike, + scopeAttrName: string, + ): void { + const is = (isfn: string, myT: Name = className): void => { + this.emitBlock(["if (!", isfn, "(", scopeAttrName, "))"], () => + this.emitLine( + 'throw new Exception("Attribute Error:', + myT, + "::", + attrName, + '");', + ), + ); + }; + + matchType( + t, + (_anyType) => is("defined"), + (_nullType) => is("is_null"), + (_boolType) => is("is_bool"), + (_integerType) => is("is_integer"), + (_doubleType) => is("is_float"), + (_stringType) => is("is_string"), + (arrayType) => { + is("is_array"); + this.emitLine( + "array_walk(", + scopeAttrName, + ", function(", + scopeAttrName, + "_v) {", + ); + this.indent(() => { + this.phpValidate( + className, + arrayType.items, + attrName, + `${scopeAttrName}_v`, + ); + }); + this.emitLine("});"); + }, + (_classType) => { + this.emitLine(scopeAttrName, "->validate();"); + }, + (mapType) => { + this.emitLine("foreach (", scopeAttrName, " as $k => $v) {"); + this.indent(() => { + this.phpValidate(className, mapType.values, attrName, "$v"); + }); + this.emitLine("}"); + }, + (enumType) => { + this.emitLine( + this.phpType(false, enumType), + "::to(", + scopeAttrName, + ");", + ); + }, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + this.emitBlock( + ["if (!is_null(", scopeAttrName, "))"], + () => { + this.phpValidate( + className, + nullable, + attrName, + scopeAttrName, + ); + }, + ); + return; + } + + throw Error("not implemented"); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + this.transformDateTime(className, attrName, [ + scopeAttrName, + ]); + return; + } + + throw Error( + `transformedStringType.kind === ${transformedStringType.kind}`, + ); + }, + ); + } + + protected emitFromMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + _name: Name, + desc?: string[], + ): void { + this.emitLine("/**"); + if (desc !== undefined) { + this.emitLine(" * ", desc); + this.emitLine(" *"); + } + + // this.emitLine(" * @param ", this.phpType(false, p.type, false, "", "|null")); + this.emitLine( + " * @param ", + this.phpConvertType(className, p.type), + " $value", + ); + this.emitLine(" * @throws Exception"); + this.emitLine(" * @return ", this.phpType(false, p.type)); + this.emitLine(" */"); + this.emitBlock( + [ + "public static function ", + names.from, + "(", + this.phpConvertType(className, p.type), + " $value): ", + this.phpType(false, p.type), + ], + () => { + this.phpFromObjConvert( + className, + p.type, + ["return "], + ["$value"], + ); + // this.emitLine("return $ret;"); + }, + ); + } + + protected emitToMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[], + ): void { + this.emitLine("/**"); + if (desc !== undefined) { + this.emitLine(" * ", desc); + this.emitLine(" *"); + } + + this.emitLine(" * @throws Exception"); + this.emitLine(" * @return ", this.phpConvertType(className, p.type)); + this.emitLine(" */"); + this.emitBlock( + [ + "public function ", + names.to, + "(): ", + this.phpConvertType(className, p.type), + ], + () => { + this.emitBlock( + [ + "if (", + className, + "::", + names.validate, + "($this->", + name, + ")) ", + ], + () => { + this.phpToObjConvert( + className, + p.type, + ["return "], + ["$this->", name], + ); + }, + ); + this.emitLine( + "throw new Exception('never get to this ", + className, + "::", + name, + "');", + ); + }, + ); + } + + protected emitValidateMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[], + ): void { + this.emitLine("/**"); + if (desc !== undefined) { + this.emitLine(" * ", desc); + this.emitLine(" *"); + } + + this.emitLine( + " * @param ", + this.phpType(false, p.type, false, "", "|null"), + ); + this.emitLine(" * @return bool"); + this.emitLine(" * @throws Exception"); + this.emitLine(" */"); + this.emitBlock( + [ + "public static function ", + names.validate, + "(", + this.phpType(false, p.type), + " $value): bool", + ], + () => { + this.phpValidate(className, p.type, name, "$value"); + this.emitLine("return true;"); + }, + ); + } + + protected emitGetMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[], + ): void { + if (this._options.withGet) { + this.emitLine("/**"); + if (desc !== undefined) { + this.emitLine(" * ", desc); + this.emitLine(" *"); + } + + if (!this._options.fastGet) { + this.emitLine(" * @throws Exception"); + } + + const rendered = this.phpType(false, p.type); + this.emitLine(" * @return ", rendered); + this.emitLine(" */"); + this.emitBlock( + ["public function ", names.getter, "(): ", rendered], + () => { + if (!this._options.fastGet) { + this.emitBlock( + [ + "if (", + className, + "::", + names.validate, + "($this->", + name, + ")) ", + ], + () => { + this.emitLine("return $this->", name, ";"); + }, + ); + this.emitLine( + "throw new Exception('never get to ", + names.getter, + " ", + className, + "::", + name, + "');", + ); + } else { + this.emitLine("return $this->", name, ";"); + } + }, + ); + } + } + + protected emitSetMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc?: string[], + ): void { + if (this._options.withSet) { + this.emitLine("/**"); + if (desc !== undefined) { + this.emitLine(" * ", desc); + this.emitLine(" *"); + } + + this.emitLine( + " * @param ", + this.phpType(false, p.type, false, "", "|null"), + ); + this.emitLine(" * @throws Exception"); + this.emitLine(" */"); + this.emitBlock( + [ + "public function ", + names.setter, + "(", + this.phpType(false, p.type), + " $value)", + ], + () => { + this.emitBlock( + ["if (", className, "::", names.validate, "($value)) "], + () => { + this.emitLine("$this->", name, " = $value;"); + }, + ); + }, + ); + } + } + + protected emitSampleMethod( + names: FunctionNames, + p: ClassProperty, + className: Name, + name: Name, + desc: string[] | undefined, + idx: number, + ): void { + if (this._options.withGet) { + this.emitLine("/**"); + if (desc !== undefined) { + this.emitLine(" * ", desc); + this.emitLine(" *"); + } + + const rendered = this.phpType(false, p.type); + this.emitLine(" * @return ", rendered); + this.emitLine(" */"); + this.emitBlock( + ["public static function ", names.sample, "(): ", rendered], + () => { + this.phpSampleConvert( + className, + p.type, + ["return "], + [name], + idx, + ";", + ); + }, + ); + } + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + this.emitFileHeader(className, []); + + this.emitBlock(["class ", className], () => { + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + this.emitLine( + "private ", + this.phpType(false, p.type), + " $", + name, + "; // json:", + jsonName, + " ", + p.type.isNullable ? "Optional" : "Required", + ); + }); + + this.ensureBlankLine(); + const comments: Sourcelike[][] = []; + const args: Sourcelike[][] = []; + let prefix = ""; + this.forEachClassProperty(c, "none", (name, __, p) => { + args.push([prefix, this.phpType(false, p.type), " $", name]); + prefix = ", "; + comments.push([ + " * @param ", + this.phpType(false, p.type, false, "", "|null"), + " $", + name, + "\n", + ]); + }); + this.emitBlock( + [ + "/**\n", + ...comments, + " */\n", + "public function __construct(", + ...args, + ")", + ], + () => { + this.forEachClassProperty(c, "none", (name) => { + this.emitLine("$this->", name, " = $", name, ";"); + }); + }, + ); + + let idx = 31; + this.forEachClassProperty( + c, + "leading-and-interposing", + (name, jsonName, p) => { + const desc = this.descriptionForClassProperty(c, jsonName); + const names = defined( + this._gettersAndSettersForPropertyName.get(name), + ); + + this.ensureBlankLine(); + this.emitFromMethod(names, p, className, name, desc); + this.ensureBlankLine(); + this.emitToMethod(names, p, className, name, desc); + this.ensureBlankLine(); + this.emitValidateMethod(names, p, className, name, desc); + this.ensureBlankLine(); + this.emitGetMethod(names, p, className, name, desc); + this.ensureBlankLine(); + this.emitSetMethod(names, p, className, name, desc); + this.ensureBlankLine(); + this.emitSampleMethod( + names, + p, + className, + name, + desc, + idx++, + ); + }, + ); + + this.ensureBlankLine(); + this.emitBlock( + [ + "/**\n", + " * @throws Exception\n", + " * @return bool\n", + " */\n", + "public function validate(): bool", + ], + () => { + const lines: Sourcelike[][] = []; + let p = "return "; + this.forEachClassProperty( + c, + "none", + (name, _jsonName, _p) => { + const names = defined( + this._gettersAndSettersForPropertyName.get( + name, + ), + ); + lines.push([ + p, + className, + "::", + names.validate, + "($this->", + name, + ")", + ]); + p = "|| "; + }, + ); + lines.forEach((line, jdx) => { + this.emitLine( + ...line, + lines.length === jdx + 1 ? ";" : "", + ); + }); + }, + ); + + this.ensureBlankLine(); + this.emitBlock( + [ + "/**\n", + " * @return stdClass\n", + " * @throws Exception\n", + " */\n", + "public function to(): stdClass ", + ], + () => { + this.emitLine("$out = new stdClass();"); + this.forEachClassProperty(c, "none", (name, jsonName) => { + const names = defined( + this._gettersAndSettersForPropertyName.get(name), + ); + this.emitLine( + "$out->{'", + jsonName, + "'} = $this->", + names.to, + "();", + ); + }); + this.emitLine("return $out;"); + }, + ); + + this.ensureBlankLine(); + this.emitBlock( + [ + "/**\n", + " * @param stdClass $obj\n", + " * @return ", + className, + "\n", + " * @throws Exception\n", + " */\n", + "public static function from(stdClass $obj): ", + className, + ], + () => { + if (this._options.fastGet) { + this.forEachClassProperty(c, "none", (name) => { + const names = defined( + this._gettersAndSettersForPropertyName.get( + name, + ), + ); + this.emitLine( + className, + "::", + names.validate, + "($this->", + name, + ", true);", + ); + }); + } + + this.emitLine("return new ", className, "("); + let comma = " "; + this.forEachClassProperty(c, "none", (name, jsonName) => { + const names = defined( + this._gettersAndSettersForPropertyName.get(name), + ); + this.emitLine( + comma, + className, + "::", + names.from, + "($obj->{'", + jsonName, + "'})", + ); + comma = ","; + }); + this.emitLine(");"); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "/**\n", + " * @return ", + className, + "\n", + " */\n", + "public static function sample(): ", + className, + ], + () => { + this.emitLine("return new ", className, "("); + let comma = " "; + this.forEachClassProperty(c, "none", (name) => { + const names = defined( + this._gettersAndSettersForPropertyName.get(name), + ); + this.emitLine( + comma, + className, + "::", + names.sample, + "()", + ); + comma = ","; + }); + this.emitLine(");"); + }, + ); + }); + this.finishFile(); + } + + protected emitUnionAttributes(_u: UnionType, _unionName: Name): void { + // empty + } + + protected emitUnionSerializer(_u: UnionType, _unionName: Name): void { + // empty + } + + protected emitUnionDefinition(_u: UnionType, _unionName: Name): void { + throw Error("emitUnionDefinition not implemented"); + } + + protected emitEnumSerializationAttributes(_e: EnumType): void { + // Empty + } + + protected emitEnumDeserializationAttributes(_e: EnumType): void { + // Empty + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitFileHeader(enumName, []); + this.emitDescription(this.descriptionForType(e)); + const caseNames: Sourcelike[] = []; + caseNames.push(";"); + const enumSerdeType = "string"; + this.emitBlock(["class ", enumName], () => { + this.forEachEnumCase(e, "none", (name, _jsonName) => { + this.emitLine("public static ", enumName, " $", name, ";"); + }); + + this.emitBlock("public static function init()", () => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine( + enumName, + "::$", + name, + " = new ", + enumName, + "('", + jsonName, + "');", + ); + }); + }); + + this.emitLine("private ", enumSerdeType, " $enum;"); + this.emitBlock( + ["public function __construct(", enumSerdeType, " $enum)"], + () => { + this.emitLine("$this->enum = $enum;"); + }, + ); + + this.ensureBlankLine(); + this.emitEnumSerializationAttributes(e); + + this.emitBlock( + [ + "/**\n", + " * @param ", + enumName, + "\n", + " * @return ", + enumSerdeType, + "\n", + " * @throws Exception\n", + " */\n", + "public static function to(", + enumName, + " $obj): ", + enumSerdeType, + ], + () => { + this.emitLine("switch ($obj->enum) {"); + this.indent(() => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + // Todo String or Number + this.emitLine( + "case ", + enumName, + "::$", + name, + "->enum: return '", + stringEscape(jsonName), + "';", + ); + }); + }); + this.emitLine("}"); + this.emitLine( + "throw new Exception('the give value is not an enum-value.');", + ); + }, + ); + this.ensureBlankLine(); + this.emitEnumDeserializationAttributes(e); + + this.emitBlock( + [ + "/**\n", + " * @param mixed\n", + " * @return ", + enumName, + "\n", + " * @throws Exception\n", + " */\n", + "public static function from($obj): ", + enumName, + ], + () => { + this.emitLine("switch ($obj) {"); + this.indent(() => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + // Todo String or Enum + this.emitLine( + "case '", + stringEscape(jsonName), + "': return ", + enumName, + "::$", + name, + ";", + ); + }); + }); + this.emitLine("}"); + this.emitLine( + 'throw new Exception("Cannot deserialize ', + enumName, + '");', + ); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + [ + "/**\n", + " * @return ", + enumName, + "\n", + " */\n", + "public static function sample(): ", + enumName, + ], + () => { + const lines: Sourcelike[] = []; + this.forEachEnumCase(e, "none", (name) => { + lines.push([enumName, "::$", name]); + }); + this.emitLine("return ", lines[0], ";"); + }, + ); + }); + this.emitLine(enumName, "::init();"); + this.finishFile(); + } + + protected emitSourceStructure(givenFilename: string): void { + this.emitLine(" this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n), + ); + if (this._options.withClosing) { + this.emitLine("?>"); + } + + super.finishFile(defined(givenFilename)); + } +} diff --git a/packages/quicktype-core/src/language/Php/index.ts b/packages/quicktype-core/src/language/Php/index.ts new file mode 100644 index 000000000..2e11f2650 --- /dev/null +++ b/packages/quicktype-core/src/language/Php/index.ts @@ -0,0 +1,2 @@ +export { PhpTargetLanguage, phpOptions } from "./language"; +export { PhpRenderer } from "./PhpRenderer"; diff --git a/packages/quicktype-core/src/language/Php/language.ts b/packages/quicktype-core/src/language/Php/language.ts new file mode 100644 index 000000000..0e8aa7f1c --- /dev/null +++ b/packages/quicktype-core/src/language/Php/language.ts @@ -0,0 +1,60 @@ +import type { RenderContext } from "../../Renderer"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { PhpRenderer } from "./PhpRenderer"; + +export const phpOptions = { + withGet: new BooleanOption("with-get", "Create Getter", true), + fastGet: new BooleanOption("fast-get", "getter without validation", false), + withSet: new BooleanOption("with-set", "Create Setter", false), + withClosing: new BooleanOption("with-closing", "PHP Closing Tag", false), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), +}; + +export const phpLanguageConfig = { + displayName: "PHP", + names: ["php"], + extension: "php", +} as const; + +export class PhpTargetLanguage extends TargetLanguage< + typeof phpLanguageConfig +> { + public constructor() { + super(phpLanguageConfig); + } + + public getOptions(): typeof phpOptions { + return phpOptions; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): PhpRenderer { + const options = getOptionValues(phpOptions, untypedOptionValues); + return new PhpRenderer(this, renderContext, options); + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + mapping.set("date", "date"); // TODO is not implemented yet + mapping.set("time", "time"); // TODO is not implemented yet + mapping.set("uuid", "uuid"); // TODO is not implemented yet + mapping.set("date-time", "date-time"); + return mapping; + } +} diff --git a/packages/quicktype-core/src/language/Php/utils.ts b/packages/quicktype-core/src/language/Php/utils.ts new file mode 100644 index 000000000..a235dc908 --- /dev/null +++ b/packages/quicktype-core/src/language/Php/utils.ts @@ -0,0 +1,59 @@ +import * as _ from "lodash"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + isAscii, + isDigit, + isLetter, + splitIntoWords, + standardUnicodeHexEscape, + utf16ConcatMap, + utf16LegalizeCharacters, +} from "../../support/Strings"; + +export const stringEscape = utf16ConcatMap( + escapeNonPrintableMapper(isAscii, standardUnicodeHexEscape), +); + +function isStartCharacter(codePoint: number): boolean { + if (codePoint === 0x5f) return true; // underscore + return isAscii(codePoint) && isLetter(codePoint); +} + +function isPartCharacter(codePoint: number): boolean { + return ( + isStartCharacter(codePoint) || + (isAscii(codePoint) && isDigit(codePoint)) + ); +} + +const legalizeName = utf16LegalizeCharacters(isPartCharacter); + +export function phpNameStyle( + startWithUpper: boolean, + upperUnderscore: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle, +): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upperUnderscore + ? allUpperWordStyle + : startWithUpper + ? firstUpperWordStyle + : allLowerWordStyle, + upperUnderscore ? allUpperWordStyle : firstUpperWordStyle, + upperUnderscore || startWithUpper + ? allUpperWordStyle + : allLowerWordStyle, + acronymsStyle, + upperUnderscore ? "_" : "", + isStartCharacter, + ); +} diff --git a/packages/quicktype-core/src/language/Pike.ts b/packages/quicktype-core/src/language/Pike/PikeRenderer.ts similarity index 53% rename from packages/quicktype-core/src/language/Pike.ts rename to packages/quicktype-core/src/language/Pike/PikeRenderer.ts index 686ca8c53..81fd8dda6 100644 --- a/packages/quicktype-core/src/language/Pike.ts +++ b/packages/quicktype-core/src/language/Pike/PikeRenderer.ts @@ -1,87 +1,37 @@ -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { Option } from "../RendererOptions"; -import { RenderContext } from "../Renderer"; -import { MultiWord, Sourcelike, multiWord, parenIfNeeded, singleWord } from "../Source"; -import { TargetLanguage } from "../TargetLanguage"; -import { Type, ClassType, EnumType, UnionType, ArrayType, MapType, PrimitiveType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { legalizeCharacters, isLetterOrUnderscoreOrDigit, stringEscape, makeNameStyle } from "../support/Strings"; - -export const pikeOptions = {}; - -const keywords = [ - "auto", - "nomask", - "final", - "static", - "extern", - "private", - "local", - "public", - "protected", - "inline", - "optional", - "variant", - "void", - "mixed", - "array", - "__attribute__", - "__deprecated__", - "mapping", - "multiset", - "object", - "function", - "__func__", - "program", - "string", - "float", - "int", - "enum", - "typedef", - "if", - "do", - "for", - "while", - "else", - "foreach", - "catch", - "gauge", - "class", - "break", - "case", - "const", - "constant", - "continue", - "default", - "import", - "inherit", - "lambda", - "predef", - "return", - "sscanf", - "switch", - "typeof", - "global" -]; - -const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); -const enumNamingFunction = funPrefixNamer("enumNamer", makeNameStyle("upper-underscore", legalizeName)); -const namingFunction = funPrefixNamer("genericNamer", makeNameStyle("underscore", legalizeName)); -const namedTypeNamingFunction = funPrefixNamer("typeNamer", makeNameStyle("pascal", legalizeName)); - -export class PikeTargetLanguage extends TargetLanguage { - constructor() { - super("Pike", ["pike", "pikelang"], "pmod"); - } - protected getOptions(): Option[] { - return []; - } - - protected makeRenderer(renderContext: RenderContext): PikeRenderer { - return new PikeRenderer(this, renderContext); - } -} +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import type { Name, Namer } from "../../Naming"; +import { + type MultiWord, + type Sourcelike, + multiWord, + parenIfNeeded, + singleWord, +} from "../../Source"; +import { stringEscape } from "../../support/Strings"; +import { + ArrayType, + type ClassType, + type EnumType, + MapType, + PrimitiveType, + type Type, + type UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import { + enumNamingFunction, + namedTypeNamingFunction, + namingFunction, +} from "./utils"; export class PikeRenderer extends ConvenienceRenderer { protected emitSourceStructure(): void { @@ -95,14 +45,15 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitTopLevelConverter(t, name); this.ensureBlankLine(); }, - t => this.namedTypeToNameForTopLevel(t) === undefined + (t) => this.namedTypeToNameForTopLevel(t) === undefined, ); this.ensureBlankLine(); this.forEachNamedType( "leading-and-interposing", - (c: ClassType, className: Name) => this.emitClassDefinition(c, className), + (c: ClassType, className: Name) => + this.emitClassDefinition(c, className), (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) + (u, n) => this.emitUnion(u, n), ); } @@ -113,6 +64,7 @@ export class PikeRenderer extends ConvenienceRenderer { protected makeEnumCaseNamer(): Namer { return enumNamingFunction; } + protected makeNamedTypeNamer(): Namer { return namedTypeNamingFunction; } @@ -129,48 +81,64 @@ export class PikeRenderer extends ConvenienceRenderer { return [...keywords]; } - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { return { names: [], includeGlobalForbidden: true }; } protected sourceFor(t: Type): MultiWord { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { + if (["class", "object", "enum"].includes(t.kind)) { return singleWord(this.nameForNamedType(t)); } + return matchType( t, - _anyType => singleWord("mixed"), - _nullType => singleWord("mixed"), - _boolType => singleWord("bool"), - _integerType => singleWord("int"), - _doubleType => singleWord("float"), - _stringType => singleWord("string"), - arrayType => singleWord(["array(", this.sourceFor(arrayType.items).source, ")"]), - _classType => singleWord(this.nameForNamedType(_classType)), - mapType => { - let valueSource: Sourcelike; + (_anyType) => singleWord("mixed"), + (_nullType) => singleWord("mixed"), + (_boolType) => singleWord("bool"), + (_integerType) => singleWord("int"), + (_doubleType) => singleWord("float"), + (_stringType) => singleWord("string"), + (arrayType) => + singleWord([ + "array(", + this.sourceFor(arrayType.items).source, + ")", + ]), + (_classType) => singleWord(this.nameForNamedType(_classType)), + (mapType) => { const v = mapType.values; + const valueSource: Sourcelike = this.sourceFor(v).source; - valueSource = this.sourceFor(v).source; return singleWord(["mapping(string:", valueSource, ")"]); }, - _enumType => singleWord("enum"), - unionType => { + (_enumType) => singleWord("enum"), + (unionType) => { if (nullableFromUnion(unionType) !== null) { - const children = Array.from(unionType.getChildren()).map(c => parenIfNeeded(this.sourceFor(c))); + const children = Array.from(unionType.getChildren()).map( + (c) => parenIfNeeded(this.sourceFor(c)), + ); return multiWord("|", ...children); - } else { - return singleWord(this.nameForNamedType(unionType)); } - } + + return singleWord(this.nameForNamedType(unionType)); + }, ); } @@ -187,11 +155,11 @@ export class PikeRenderer extends ConvenienceRenderer { protected emitEnum(e: EnumType, enumName: Name): void { this.emitBlock([e.kind, " ", enumName], () => { - let table: Sourcelike[][] = []; + const table: Sourcelike[][] = []; this.forEachEnumCase(e, "none", (name, jsonName) => { table.push([ [name, ' = "', stringEscape(jsonName), '", '], - ['// json: "', jsonName, '"'] + ['// json: "', jsonName, '"'], ]); }); this.emitTable(table); @@ -209,7 +177,7 @@ export class PikeRenderer extends ConvenienceRenderer { const [, nonNulls] = removeNullFromUnion(u); - let types: Sourcelike[][] = []; + const types: Sourcelike[][] = []; this.forEachUnionMember(u, nonNulls, "none", null, (_name, t) => { const pikeType = this.sourceFor(t).source; types.push([pikeType]); @@ -217,18 +185,28 @@ export class PikeRenderer extends ConvenienceRenderer { this.emitLine([ "typedef ", - types.map(r => r.map(sl => this.sourcelikeToString(sl))).join("|"), + types + .map((r) => r.map((sl) => this.sourcelikeToString(sl))) + .join("|"), " ", unionName, - ";" + ";", ]); this.ensureBlankLine(); - this.emitBlock([unionName, " ", unionName, "_from_JSON(mixed json)"], () => { - this.emitLine(["return json;"]); - }); + this.emitBlock( + [unionName, " ", unionName, "_from_JSON(mixed json)"], + () => { + this.emitLine(["return json;"]); + }, + ); } - private emitBlock(line: Sourcelike, f: () => void, opening: Sourcelike = " {", closing: Sourcelike = "}"): void { + private emitBlock( + line: Sourcelike, + f: () => void, + opening: Sourcelike = " {", + closing: Sourcelike = "}", + ): void { this.emitLine(line, opening); this.indent(f); this.emitLine(closing); @@ -239,20 +217,20 @@ export class PikeRenderer extends ConvenienceRenderer { } private emitClassMembers(c: ClassType): void { - let table: Sourcelike[][] = []; + const table: Sourcelike[][] = []; this.forEachClassProperty(c, "none", (name, jsonName, p) => { const pikeType = this.sourceFor(p.type).source; table.push([ [pikeType, " "], [name, "; "], - ['// json: "', jsonName, '"'] + ['// json: "', jsonName, '"'], ]); }); this.emitTable(table); } - private emitInformationComment() { + private emitInformationComment(): void { this.emitCommentLines( [ "This source has been automatically generated by quicktype.", @@ -267,28 +245,35 @@ export class PikeRenderer extends ConvenienceRenderer { "It will return an instance of .", "Bear in mind that these functions have unexpected behavior,", "and will likely throw an error, if the JSON string does not", - "match the expected interface, even if the JSON itself is valid." + "match the expected interface, even if the JSON itself is valid.", ], - "// " + { lineStart: "// " }, ); } - private emitTopLevelTypedef(t: Type, name: Name) { + private emitTopLevelTypedef(t: Type, name: Name): void { this.emitLine("typedef ", this.sourceFor(t).source, " ", name, ";"); } - private emitTopLevelConverter(t: Type, name: Name) { + private emitTopLevelConverter(t: Type, name: Name): void { this.emitBlock([name, " ", name, "_from_JSON(mixed json)"], () => { if (t instanceof PrimitiveType) { this.emitLine(["return json;"]); } else if (t instanceof ArrayType) { - if (t.items instanceof PrimitiveType) this.emitLine(["return json;"]); - else this.emitLine(["return map(json, ", this.sourceFor(t.items).source, "_from_JSON);"]); + if (t.items instanceof PrimitiveType) + this.emitLine(["return json;"]); + else + this.emitLine([ + "return map(json, ", + this.sourceFor(t.items).source, + "_from_JSON);", + ]); } else if (t instanceof MapType) { const type = this.sourceFor(t.values).source; this.emitLine(["mapping(string:", type, ") retval = ([]);"]); let assignmentRval: Sourcelike; - if (t.values instanceof PrimitiveType) assignmentRval = ["(", type, ") v"]; + if (t.values instanceof PrimitiveType) + assignmentRval = ["(", type, ") v"]; else assignmentRval = [type, "_from_JSON(v)"]; this.emitBlock(["foreach (json; string k; mixed v)"], () => { this.emitLine(["retval[k] = ", assignmentRval, ";"]); @@ -298,11 +283,17 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitEncodingFunction(c: ClassType) { + private emitEncodingFunction(c: ClassType): void { this.emitBlock(["string encode_json()"], () => { this.emitMappingBlock(["mapping(string:mixed) json = "], () => { this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(['"', stringEscape(jsonName), '" : ', name, ","]); + this.emitLine([ + '"', + stringEscape(jsonName), + '" : ', + name, + ",", + ]); }); }); this.ensureBlankLine(); @@ -310,15 +301,24 @@ export class PikeRenderer extends ConvenienceRenderer { }); } - private emitDecodingFunction(className: Name, c: ClassType) { - this.emitBlock([className, " ", className, "_from_JSON(mixed json)"], () => { - this.emitLine([className, " retval = ", className, "();"]); - this.ensureBlankLine(); - this.forEachClassProperty(c, "none", (name, jsonName) => { - this.emitLine(["retval.", name, ' = json["', stringEscape(jsonName), '"];']); - }); - this.ensureBlankLine(); - this.emitLine(["return retval;"]); - }); + private emitDecodingFunction(className: Name, c: ClassType): void { + this.emitBlock( + [className, " ", className, "_from_JSON(mixed json)"], + () => { + this.emitLine([className, " retval = ", className, "();"]); + this.ensureBlankLine(); + this.forEachClassProperty(c, "none", (name, jsonName) => { + this.emitLine([ + "retval.", + name, + ' = json["', + stringEscape(jsonName), + '"];', + ]); + }); + this.ensureBlankLine(); + this.emitLine(["return retval;"]); + }, + ); } } diff --git a/packages/quicktype-core/src/language/Pike/constants.ts b/packages/quicktype-core/src/language/Pike/constants.ts new file mode 100644 index 000000000..c6a8024ca --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/constants.ts @@ -0,0 +1,54 @@ +export const keywords = [ + "auto", + "nomask", + "final", + "static", + "extern", + "private", + "local", + "public", + "protected", + "inline", + "optional", + "variant", + "void", + "mixed", + "array", + "__attribute__", + "__deprecated__", + "mapping", + "multiset", + "object", + "function", + "__func__", + "program", + "string", + "float", + "int", + "enum", + "typedef", + "if", + "do", + "for", + "while", + "else", + "foreach", + "catch", + "gauge", + "class", + "break", + "case", + "const", + "constant", + "continue", + "default", + "import", + "inherit", + "lambda", + "predef", + "return", + "sscanf", + "switch", + "typeof", + "global", +] as const; diff --git a/packages/quicktype-core/src/language/Pike/index.ts b/packages/quicktype-core/src/language/Pike/index.ts new file mode 100644 index 000000000..2b80f3674 --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/index.ts @@ -0,0 +1,2 @@ +export { PikeTargetLanguage, pikeOptions } from "./language"; +export { PikeRenderer } from "./PikeRenderer"; diff --git a/packages/quicktype-core/src/language/Pike/language.ts b/packages/quicktype-core/src/language/Pike/language.ts new file mode 100644 index 000000000..cbce94b71 --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/language.ts @@ -0,0 +1,28 @@ +import type { RenderContext } from "../../Renderer"; +import { TargetLanguage } from "../../TargetLanguage"; + +import { PikeRenderer } from "./PikeRenderer"; + +export const pikeOptions = {}; + +export const pikeLanguageConfig = { + displayName: "Pike", + names: ["pike", "pikelang"], + extension: "pmod", +} as const; + +export class PikeTargetLanguage extends TargetLanguage< + typeof pikeLanguageConfig +> { + public constructor() { + super(pikeLanguageConfig); + } + + public getOptions(): {} { + return {}; + } + + protected makeRenderer(renderContext: RenderContext): PikeRenderer { + return new PikeRenderer(this, renderContext); + } +} diff --git a/packages/quicktype-core/src/language/Pike/utils.ts b/packages/quicktype-core/src/language/Pike/utils.ts new file mode 100644 index 000000000..acd6a06e6 --- /dev/null +++ b/packages/quicktype-core/src/language/Pike/utils.ts @@ -0,0 +1,20 @@ +import { funPrefixNamer } from "../../Naming"; +import { + isLetterOrUnderscoreOrDigit, + legalizeCharacters, + makeNameStyle, +} from "../../support/Strings"; + +const legalizeName = legalizeCharacters(isLetterOrUnderscoreOrDigit); +export const enumNamingFunction = funPrefixNamer( + "enumNamer", + makeNameStyle("upper-underscore", legalizeName), +); +export const namingFunction = funPrefixNamer( + "genericNamer", + makeNameStyle("underscore", legalizeName), +); +export const namedTypeNamingFunction = funPrefixNamer( + "typeNamer", + makeNameStyle("pascal", legalizeName), +); diff --git a/packages/quicktype-core/src/language/Python.ts b/packages/quicktype-core/src/language/Python.ts deleted file mode 100644 index 7da7dc74d..000000000 --- a/packages/quicktype-core/src/language/Python.ts +++ /dev/null @@ -1,1275 +0,0 @@ -import { TargetLanguage } from "../TargetLanguage"; -import { StringTypeMapping } from "../TypeBuilder"; -import { - TransformedStringTypeKind, - PrimitiveStringTypeKind, - Type, - EnumType, - ClassType, - UnionType, - ClassProperty -} from "../Type"; -import { RenderContext } from "../Renderer"; -import { Option, getOptionValues, OptionValues, EnumOption, BooleanOption } from "../RendererOptions"; -import { ConvenienceRenderer, ForbiddenWordsInfo, topLevelNameOrder } from "../ConvenienceRenderer"; -import { Namer, funPrefixNamer, Name, DependencyName } from "../Naming"; -import { - splitIntoWords, - combineWords, - firstUpperWordStyle, - utf16LegalizeCharacters, - allUpperWordStyle, - allLowerWordStyle, - stringEscape, - originalWord -} from "../support/Strings"; -import { assertNever, panic, defined } from "../support/Support"; -import { Sourcelike, MultiWord, multiWord, singleWord, parenIfNeeded, modifySource } from "../Source"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { - followTargetType, - transformationForType, - Transformer, - DecodingChoiceTransformer, - ChoiceTransformer, - DecodingTransformer, - UnionInstantiationTransformer, - ParseStringTransformer, - UnionMemberMatchTransformer, - StringifyTransformer, - EncodingTransformer -} from "../Transformers"; -import { - arrayIntercalate, - setUnionInto, - mapUpdateInto, - iterableSome, - mapSortBy, - iterableFirst -} from "collection-utils"; - -import unicode from "unicode-properties"; - -const forbiddenTypeNames = [ - "Any", - "True", - "False", - "None", - "Enum", - "List", - "Dict", - "Optional", - "Union", - "Iterable", - "Type", - "TypeVar", - "T", - "EnumT" -]; -const forbiddenPropertyNames = [ - "and", - "as", - "assert", - "async", - "await", - "bool", - "break", - "class", - "continue", - "datetime", - "def", - "del", - "dict", - "elif", - "else", - "except", - "finally", - "float", - "for", - "from", - "global", - "if", - "import", - "in", - "int", - "is", - "lambda", - "nonlocal", - "not", - "or", - "pass", - "print", - "raise", - "return", - "self", - "str", - "try", - "while", - "with", - "yield" -]; - -export type PythonFeatures = { - typeHints: boolean; - dataClasses: boolean; -}; - -export const pythonOptions = { - features: new EnumOption( - "python-version", - "Python version", - [ - ["3.5", { typeHints: false, dataClasses: false }], - ["3.6", { typeHints: true, dataClasses: false }], - ["3.7", { typeHints: true, dataClasses: true }] - ], - "3.6" - ), - justTypes: new BooleanOption("just-types", "Classes only", false), - nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be Pythonic", true) -}; - -export class PythonTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return [pythonOptions.features, pythonOptions.justTypes, pythonOptions.nicePropertyNames]; - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - const dateTimeType = "date-time"; - mapping.set("date", dateTimeType); - mapping.set("time", dateTimeType); - mapping.set("date-time", dateTimeType); - mapping.set("uuid", "uuid"); - mapping.set("integer-string", "integer-string"); - mapping.set("bool-string", "bool-string"); - return mapping; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - get supportsOptionalClassProperties(): boolean { - return false; - } - - needsTransformerForType(t: Type): boolean { - if (t instanceof UnionType) { - return iterableSome(t.members, m => this.needsTransformerForType(m)); - } - return t.kind === "integer-string" || t.kind === "bool-string"; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): PythonRenderer { - const options = getOptionValues(pythonOptions, untypedOptionValues); - if (options.justTypes) { - return new PythonRenderer(this, renderContext, options); - } else { - return new JSONPythonRenderer(this, renderContext, options); - } - } -} - -function isNormalizedStartCharacter3(utf16Unit: number): boolean { - // FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers - const category: string = unicode.getCategory(utf16Unit); - return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].indexOf(category) >= 0; -} - -function isNormalizedPartCharacter3(utf16Unit: number): boolean { - // FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers - if (isNormalizedStartCharacter3(utf16Unit)) return true; - const category: string = unicode.getCategory(utf16Unit); - return ["Mn", "Mc", "Nd", "Pc"].indexOf(category) >= 0; -} - -function isStartCharacter3(utf16Unit: number): boolean { - const s = String.fromCharCode(utf16Unit).normalize("NFKC"); - const l = s.length; - if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0))) return false; - for (let i = 1; i < l; i++) { - if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; - } - return true; -} - -function isPartCharacter3(utf16Unit: number): boolean { - const s = String.fromCharCode(utf16Unit).normalize("NFKC"); - const l = s.length; - for (let i = 0; i < l; i++) { - if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; - } - return true; -} - -const legalizeName3 = utf16LegalizeCharacters(isPartCharacter3); - -function classNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName3, - firstUpperWordStyle, - firstUpperWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter3 - ); -} - -function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean) { - if (!forceSnakeNameStyle) { - return originalWord; - } - return uppercase ? allUpperWordStyle : allLowerWordStyle; -} - -function snakeNameStyle(original: string, uppercase: boolean, forceSnakeNameStyle: boolean): string { - const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle); - const separator = forceSnakeNameStyle ? "_" : ""; - const words = splitIntoWords(original); - return combineWords(words, legalizeName3, wordStyle, wordStyle, wordStyle, wordStyle, separator, isStartCharacter3); -} - -export class PythonRenderer extends ConvenienceRenderer { - private readonly imports: Map> = new Map(); - private readonly declaredTypes: Set = new Set(); - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly pyOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return forbiddenTypeNames; - } - - protected forbiddenForObjectProperties(_: ClassType, _classNamed: Name): ForbiddenWordsInfo { - return { names: forbiddenPropertyNames, includeGlobalForbidden: false }; - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("type", classNameStyle); - } - - protected namerForObjectProperty(): Namer { - return funPrefixNamer("property", s => snakeNameStyle(s, false, this.pyOptions.nicePropertyNames)); - } - - protected makeUnionMemberNamer(): null { - return null; - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enum-case", s => snakeNameStyle(s, true, this.pyOptions.nicePropertyNames)); - } - - protected get commentLineStart(): string { - return "# "; - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - if (lines.length === 1) { - const docstring = modifySource(content => { - if (content.endsWith('"')) { - return content.slice(0, -1) + '\\"'; - } - - return content; - }, lines[0]); - this.emitLine('"""', docstring, '"""'); - } else { - this.emitCommentLines(lines, "", undefined, '"""', '"""'); - } - } - - protected get needsTypeDeclarationBeforeUse(): boolean { - return true; - } - - protected canBeForwardDeclared(t: Type): boolean { - const kind = t.kind; - return kind === "class" || kind === "enum"; - } - - protected emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line); - this.indent(f); - } - - protected string(s: string): Sourcelike { - const openQuote = '"'; - return [openQuote, stringEscape(s), '"']; - } - - protected withImport(module: string, name: string): Sourcelike { - if (this.pyOptions.features.typeHints || module !== "typing") { - // FIXME: This is ugly. We should rather not generate that import in the first - // place, but right now we just make the type source and then throw it away. It's - // not a performance issue, so it's fine, I just bemoan this special case, and - // potential others down the road. - mapUpdateInto(this.imports, module, s => (s ? setUnionInto(s, [name]) : new Set([name]))); - } - return name; - } - - protected withTyping(name: string): Sourcelike { - return this.withImport("typing", name); - } - - protected namedType(t: Type): Sourcelike { - const name = this.nameForNamedType(t); - if (this.declaredTypes.has(t)) return name; - return ["'", name, "'"]; - } - - protected pythonType(t: Type, _isRootTypeDef = false): Sourcelike { - const actualType = followTargetType(t); - - return matchType( - actualType, - _anyType => this.withTyping("Any"), - _nullType => "None", - _boolType => "bool", - _integerType => "int", - _doubletype => "float", - _stringType => "str", - arrayType => [this.withTyping("List"), "[", this.pythonType(arrayType.items), "]"], - classType => this.namedType(classType), - mapType => [this.withTyping("Dict"), "[str, ", this.pythonType(mapType.values), "]"], - enumType => this.namedType(enumType), - unionType => { - const [hasNull, nonNulls] = removeNullFromUnion(unionType); - const memberTypes = Array.from(nonNulls).map(m => this.pythonType(m)); - - if (hasNull !== null) { - let rest: string[] = []; - if (!this.getAlphabetizeProperties() && this.pyOptions.features.dataClasses && _isRootTypeDef) { - // Only push "= None" if this is a root level type def - // otherwise we may get type defs like List[Optional[int] = None] - // which are invalid - rest.push(" = None"); - } - - if (nonNulls.size > 1) { - this.withImport("typing", "Union"); - return [ - this.withTyping("Optional"), - "[Union[", - arrayIntercalate(", ", memberTypes), - "]]", - ...rest - ]; - } else { - return [this.withTyping("Optional"), "[", defined(iterableFirst(memberTypes)), "]", ...rest]; - } - } else { - return [this.withTyping("Union"), "[", arrayIntercalate(", ", memberTypes), "]"]; - } - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return this.withImport("datetime", "datetime"); - } - if (transformedStringType.kind === "uuid") { - return this.withImport("uuid", "UUID"); - } - return panic(`Transformed type ${transformedStringType.kind} not supported`); - } - ); - } - - protected declarationLine(t: Type): Sourcelike { - if (t instanceof ClassType) { - return ["class ", this.nameForNamedType(t), ":"]; - } - if (t instanceof EnumType) { - return ["class ", this.nameForNamedType(t), "(", this.withImport("enum", "Enum"), "):"]; - } - return panic(`Can't declare type ${t.kind}`); - } - - protected declareType(t: T, emitter: () => void): void { - this.emitBlock(this.declarationLine(t), () => { - this.emitDescription(this.descriptionForType(t)); - emitter(); - }); - this.declaredTypes.add(t); - } - - protected emitClassMembers(t: ClassType): void { - if (this.pyOptions.features.dataClasses) return; - - const args: Sourcelike[] = []; - this.forEachClassProperty(t, "none", (name, _, cp) => { - args.push([name, this.typeHint(": ", this.pythonType(cp.type))]); - }); - this.emitBlock( - ["def __init__(self, ", arrayIntercalate(", ", args), ")", this.typeHint(" -> None"), ":"], - () => { - if (args.length === 0) { - this.emitLine("pass"); - } else { - this.forEachClassProperty(t, "none", name => { - this.emitLine("self.", name, " = ", name); - }); - } - } - ); - } - - protected typeHint(...sl: Sourcelike[]): Sourcelike { - if (this.pyOptions.features.typeHints) { - return sl; - } - return []; - } - - protected typingDecl(name: Sourcelike, type: string): Sourcelike { - return [name, this.typeHint(": ", this.withTyping(type))]; - } - - protected typingReturn(type: string): Sourcelike { - return this.typeHint(" -> ", this.withTyping(type)); - } - - protected sortClassProperties( - properties: ReadonlyMap, - propertyNames: ReadonlyMap - ): ReadonlyMap { - if (this.pyOptions.features.dataClasses) { - return mapSortBy(properties, (p: ClassProperty) => { - return (p.type instanceof UnionType && nullableFromUnion(p.type) != null) || p.isOptional ? 1 : 0; - }); - } else { - return super.sortClassProperties(properties, propertyNames); - } - } - - protected emitClass(t: ClassType): void { - if (this.pyOptions.features.dataClasses) { - this.emitLine("@", this.withImport("dataclasses", "dataclass")); - } - this.declareType(t, () => { - if (this.pyOptions.features.typeHints) { - if (t.getProperties().size === 0) { - this.emitLine("pass"); - } else { - this.forEachClassProperty(t, "none", (name, jsonName, cp) => { - this.emitDescription(this.descriptionForClassProperty(t, jsonName)); - this.emitLine(name, this.typeHint(": ", this.pythonType(cp.type, true))); - }); - } - this.ensureBlankLine(); - } - this.emitClassMembers(t); - }); - } - - protected emitEnum(t: EnumType): void { - this.declareType(t, () => { - this.forEachEnumCase(t, "none", (name, jsonName) => { - this.emitLine([name, " = ", this.string(jsonName)]); - }); - }); - } - - protected emitImports(): void { - this.imports.forEach((names, module) => { - this.emitLine("from ", module, " import ", Array.from(names).join(", ")); - }); - } - - protected emitSupportCode(): void { - return; - } - - protected emitClosingCode(): void { - return; - } - - protected emitSourceStructure(_givenOutputFilename: string): void { - const declarationLines = this.gatherSource(() => { - this.forEachNamedType( - ["interposing", 2], - (c: ClassType) => this.emitClass(c), - e => this.emitEnum(e), - _u => { - return; - } - ); - }); - - const closingLines = this.gatherSource(() => this.emitClosingCode()); - const supportLines = this.gatherSource(() => this.emitSupportCode()); - - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } - this.ensureBlankLine(); - this.emitImports(); - this.ensureBlankLine(2); - this.emitGatheredSource(supportLines); - this.ensureBlankLine(2); - this.emitGatheredSource(declarationLines); - this.ensureBlankLine(2); - this.emitGatheredSource(closingLines); - } -} - -export type ConverterFunction = - | "none" - | "bool" - | "int" - | "from-float" - | "to-float" - | "str" - | "to-enum" - | "list" - | "to-class" - | "dict" - | "union" - | "from-datetime" - | "from-stringified-bool" - | "is-type"; - -type TopLevelConverterNames = { - fromDict: Name; - toDict: Name; -}; - -// A value or a lambda. All four combinations are valid: -// -// * `value` and `lambda`: a value given by applying `value` to `lambda`, i.e. `lambda(value)` -// * `lambda` only: a lambda given by `lambda` -// * `value` only: a value given by `value` -// * neither: the identity function, i.e. `lambda x: x` -export type ValueOrLambda = { - value: Sourcelike | undefined; - lambda?: MultiWord; -}; - -// Return the result of composing `input` and `f`. `input` can be a -// value or a lambda, but `f` must be a lambda or a TypeScript function -// (i.e. it can't be a value). -// -// * If `input` is a value, the result is `f(input)`. -// * If `input` is a lambda, the result is `lambda x: f(input(x))` -function compose(input: ValueOrLambda, f: (arg: Sourcelike) => Sourcelike): ValueOrLambda; -function compose(input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; -function compose(input: ValueOrLambda, f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike)): ValueOrLambda { - if (typeof f === "function") { - if (input.value !== undefined) { - // `input` is a value, so just apply `f` to its source form. - return { value: f(makeValue(input)) }; - } - if (input.lambda !== undefined) { - // `input` is a lambda, so build `lambda x: f(input(x))`. - return { lambda: multiWord(" ", "lambda x:", f([parenIfNeeded(input.lambda), "(x)"])), value: undefined }; - } - // `input` is the identify function, so the composition is `lambda x: f(x)`. - return { lambda: multiWord(" ", "lambda x:", f("x")), value: undefined }; - } - - if (f.value !== undefined) { - return panic("Cannot compose into a value"); - } - if (f.lambda === undefined) { - // `f` is the identity function, so the result is just `input`. - return input; - } - - if (input.value === undefined) { - // `input` is a lambda - if (input.lambda === undefined) { - // `input` is the identity function, so the result is just `f`. - return f; - } - // `input` is a lambda, so the result is `lambda x: f(input(x))`. - return { - lambda: multiWord("", "lambda x: ", parenIfNeeded(f.lambda), "(", parenIfNeeded(input.lambda), "(x))"), - value: undefined - }; - } - - // `input` is a value, so return `f(input)`. - return { lambda: f.lambda, value: makeValue(input) }; -} - -const identity: ValueOrLambda = { value: undefined }; - -// If `vol` is a lambda, return it in its source form. If it's -// a value, return a `lambda` that returns the value. -function makeLambda(vol: ValueOrLambda): MultiWord { - if (vol.lambda !== undefined) { - if (vol.value === undefined) { - return vol.lambda; - } - return multiWord("", "lambda x: ", parenIfNeeded(vol.lambda), "(", vol.value, ")"); - } else if (vol.value !== undefined) { - return multiWord(" ", "lambda x:", vol.value); - } - return multiWord(" ", "lambda x:", "x"); -} - -// If `vol` is a value, return the value in its source form. -// Calling this with `vol` being a lambda is not allowed. -function makeValue(vol: ValueOrLambda): Sourcelike { - if (vol.value === undefined) { - return panic("Cannot make value from lambda without value"); - } - if (vol.lambda !== undefined) { - return [parenIfNeeded(vol.lambda), "(", vol.value, ")"]; - } - return vol.value; -} - -export class JSONPythonRenderer extends PythonRenderer { - private readonly _deserializerFunctions = new Set(); - private readonly _converterNamer = funPrefixNamer("converter", s => - snakeNameStyle(s, false, this.pyOptions.nicePropertyNames) - ); - private readonly _topLevelConverterNames = new Map(); - private _haveTypeVar = false; - private _haveEnumTypeVar = false; - private _haveDateutil = false; - - protected emitTypeVar(tvar: string, constraints: Sourcelike): void { - if (!this.pyOptions.features.typeHints) { - return; - } - this.emitLine(tvar, " = ", this.withTyping("TypeVar"), "(", this.string(tvar), constraints, ")"); - } - - protected typeVar(): string { - this._haveTypeVar = true; - // FIXME: This is ugly, but the code that requires the type variables, in - // `emitImports` actually runs after imports have been imported. The proper - // solution would be to either allow more complex dependencies, or to - // gather-emit the type variable declarations, too. Unfortunately the - // gather-emit is a bit buggy with blank lines, and I can't be bothered to - // fix it now. - this.withTyping("TypeVar"); - return "T"; - } - - protected enumTypeVar(): string { - this._haveEnumTypeVar = true; - // See the comment above. - this.withTyping("TypeVar"); - this.withImport("enum", "Enum"); - return "EnumT"; - } - - protected cast(type: Sourcelike, v: Sourcelike): Sourcelike { - if (!this.pyOptions.features.typeHints) { - return v; - } - return [this.withTyping("cast"), "(", type, ", ", v, ")"]; - } - - protected emitNoneConverter(): void { - // FIXME: We can't return the None type here because mypy thinks that means - // We're not returning any value, when we're actually returning `None`. - this.emitBlock( - ["def from_none(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> ", this.withTyping("Any")), ":"], - () => { - this.emitLine("assert x is None"); - this.emitLine("return x"); - } - ); - } - - protected emitBoolConverter(): void { - this.emitBlock(["def from_bool(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> bool"), ":"], () => { - this.emitLine("assert isinstance(x, bool)"); - this.emitLine("return x"); - }); - } - - protected emitIntConverter(): void { - this.emitBlock(["def from_int(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> int"), ":"], () => { - this.emitLine("assert isinstance(x, int) and not isinstance(x, bool)"); - this.emitLine("return x"); - }); - } - - protected emitFromFloatConverter(): void { - this.emitBlock(["def from_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => { - this.emitLine("assert isinstance(x, (float, int)) and not isinstance(x, bool)"); - this.emitLine("return float(x)"); - }); - } - - protected emitToFloatConverter(): void { - this.emitBlock(["def to_float(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> float"), ":"], () => { - this.emitLine("assert isinstance(x, float)"); - this.emitLine("return x"); - }); - } - - protected emitStrConverter(): void { - this.emitBlock(["def from_str(", this.typingDecl("x", "Any"), ")", this.typeHint(" -> str"), ":"], () => { - const strType = "str"; - this.emitLine("assert isinstance(x, ", strType, ")"); - this.emitLine("return x"); - }); - } - - protected emitToEnumConverter(): void { - const tvar = this.enumTypeVar(); - this.emitBlock( - [ - "def to_enum(c", - this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"), - ", ", - this.typingDecl("x", "Any"), - ")", - this.typeHint(" -> ", tvar), - ":" - ], - () => { - this.emitLine("assert isinstance(x, c)"); - this.emitLine("return x.value"); - } - ); - } - - protected emitListConverter(): void { - const tvar = this.typeVar(); - this.emitBlock( - [ - "def from_list(f", - this.typeHint(": ", this.withTyping("Callable"), "[[", this.withTyping("Any"), "], ", tvar, "]"), - ", ", - this.typingDecl("x", "Any"), - ")", - this.typeHint(" -> ", this.withTyping("List"), "[", tvar, "]"), - ":" - ], - () => { - this.emitLine("assert isinstance(x, list)"); - this.emitLine("return [f(y) for y in x]"); - } - ); - } - - protected emitToClassConverter(): void { - const tvar = this.typeVar(); - this.emitBlock( - [ - "def to_class(c", - this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"), - ", ", - this.typingDecl("x", "Any"), - ")", - this.typeHint(" -> dict"), - ":" - ], - () => { - this.emitLine("assert isinstance(x, c)"); - this.emitLine("return ", this.cast(this.withTyping("Any"), "x"), ".to_dict()"); - } - ); - } - - protected emitDictConverter(): void { - const tvar = this.typeVar(); - this.emitBlock( - [ - "def from_dict(f", - this.typeHint(": ", this.withTyping("Callable"), "[[", this.withTyping("Any"), "], ", tvar, "]"), - ", ", - this.typingDecl("x", "Any"), - ")", - this.typeHint(" -> ", this.withTyping("Dict"), "[str, ", tvar, "]"), - ":" - ], - () => { - this.emitLine("assert isinstance(x, dict)"); - this.emitLine("return { k: f(v) for (k, v) in x.items() }"); - } - ); - } - - // This is not easily idiomatically typeable in Python. See - // https://stackoverflow.com/questions/51066468/computed-types-in-mypy/51084497 - protected emitUnionConverter(): void { - this.emitMultiline(`def from_union(fs, x): - for f in fs: - try: - return f(x) - except: - pass - assert False`); - } - - protected emitFromDatetimeConverter(): void { - this.emitBlock( - [ - "def from_datetime(", - this.typingDecl("x", "Any"), - ")", - this.typeHint(" -> ", this.withImport("datetime", "datetime")), - ":" - ], - () => { - this._haveDateutil = true; - this.emitLine("return dateutil.parser.parse(x)"); - } - ); - } - - protected emitFromStringifiedBoolConverter(): void { - this.emitBlock( - ["def from_stringified_bool(x", this.typeHint(": str"), ")", this.typeHint(" -> bool"), ":"], - () => { - this.emitBlock('if x == "true":', () => this.emitLine("return True")); - this.emitBlock('if x == "false":', () => this.emitLine("return False")); - this.emitLine("assert False"); - } - ); - } - - protected emitIsTypeConverter(): void { - const tvar = this.typeVar(); - this.emitBlock( - [ - "def is_type(t", - this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"), - ", ", - this.typingDecl("x", "Any"), - ")", - this.typeHint(" -> ", tvar), - ":" - ], - () => { - this.emitLine("assert isinstance(x, t)"); - this.emitLine("return x"); - } - ); - } - - protected emitConverter(cf: ConverterFunction): void { - switch (cf) { - case "none": - return this.emitNoneConverter(); - case "bool": - return this.emitBoolConverter(); - case "int": - return this.emitIntConverter(); - case "from-float": - return this.emitFromFloatConverter(); - case "to-float": - return this.emitToFloatConverter(); - case "str": - return this.emitStrConverter(); - case "to-enum": - return this.emitToEnumConverter(); - case "list": - return this.emitListConverter(); - case "to-class": - return this.emitToClassConverter(); - case "dict": - return this.emitDictConverter(); - case "union": - return this.emitUnionConverter(); - case "from-datetime": - return this.emitFromDatetimeConverter(); - case "from-stringified-bool": - return this.emitFromStringifiedBoolConverter(); - case "is-type": - return this.emitIsTypeConverter(); - default: - return assertNever(cf); - } - } - - // Return the name of the Python converter function `cf`. - protected conv(cf: ConverterFunction): Sourcelike { - this._deserializerFunctions.add(cf); - const name = cf.replace(/-/g, "_"); - if (cf.startsWith("from-") || cf.startsWith("to-") || cf.startsWith("is-")) return name; - return ["from_", name]; - } - - // Applies the converter function to `arg` - protected convFn(cf: ConverterFunction, arg: ValueOrLambda): ValueOrLambda { - return compose(arg, { lambda: singleWord(this.conv(cf)), value: undefined }); - } - - protected typeObject(t: Type): Sourcelike { - const s = matchType( - t, - _anyType => undefined, - _nullType => "type(None)", - _boolType => "bool", - _integerType => "int", - _doubleType => "float", - _stringType => "str", - _arrayType => "List", - classType => this.nameForNamedType(classType), - _mapType => "dict", - enumType => this.nameForNamedType(enumType), - _unionType => undefined, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return this.withImport("datetime", "datetime"); - } - if (transformedStringType.kind === "uuid") { - return this.withImport("uuid", "UUID"); - } - return undefined; - } - ); - if (s === undefined) { - return panic(`No type object for ${t.kind}`); - } - return s; - } - - protected transformer(inputTransformer: ValueOrLambda, xfer: Transformer, targetType: Type): ValueOrLambda { - const consume = (consumer: Transformer | undefined, vol: ValueOrLambda) => { - if (consumer === undefined) { - return vol; - } - return this.transformer(vol, consumer, targetType); - }; - - const isType = (t: Type, valueToCheck: ValueOrLambda): ValueOrLambda => { - return compose(valueToCheck, v => [this.conv("is-type"), "(", this.typeObject(t), ", ", v, ")"]); - }; - - if (xfer instanceof DecodingChoiceTransformer || xfer instanceof ChoiceTransformer) { - const lambdas = xfer.transformers.map(x => makeLambda(this.transformer(identity, x, targetType)).source); - return compose(inputTransformer, v => [ - this.conv("union"), - "([", - arrayIntercalate(", ", lambdas), - "], ", - v, - ")" - ]); - } else if (xfer instanceof DecodingTransformer) { - const consumer = xfer.consumer; - const vol = this.deserializer(inputTransformer, xfer.sourceType); - return consume(consumer, vol); - } else if (xfer instanceof EncodingTransformer) { - return this.serializer(inputTransformer, xfer.sourceType); - } else if (xfer instanceof UnionInstantiationTransformer) { - return inputTransformer; - } else if (xfer instanceof UnionMemberMatchTransformer) { - const consumer = xfer.transformer; - const vol = isType(xfer.memberType, inputTransformer); - return consume(consumer, vol); - } else if (xfer instanceof ParseStringTransformer) { - const consumer = xfer.consumer; - const immediateTargetType = consumer === undefined ? targetType : consumer.sourceType; - let vol: ValueOrLambda; - switch (immediateTargetType.kind) { - case "integer": - vol = compose(inputTransformer, v => ["int(", v, ")"]); - break; - case "bool": - vol = this.convFn("from-stringified-bool", inputTransformer); - break; - case "enum": - vol = this.deserializer(inputTransformer, immediateTargetType); - break; - case "date-time": - vol = this.convFn("from-datetime", inputTransformer); - break; - case "uuid": - vol = compose(inputTransformer, v => [this.withImport("uuid", "UUID"), "(", v, ")"]); - break; - default: - return panic(`Parsing of ${immediateTargetType.kind} in a transformer is not supported`); - } - return consume(consumer, vol); - } else if (xfer instanceof StringifyTransformer) { - const consumer = xfer.consumer; - let vol: ValueOrLambda; - switch (xfer.sourceType.kind) { - case "integer": - vol = compose(inputTransformer, v => ["str(", v, ")"]); - break; - case "bool": - vol = compose(inputTransformer, v => ["str(", v, ").lower()"]); - break; - case "enum": - vol = this.serializer(inputTransformer, xfer.sourceType); - break; - case "date-time": - vol = compose(inputTransformer, v => [v, ".isoformat()"]); - break; - case "uuid": - vol = compose(inputTransformer, v => ["str(", v, ")"]); - break; - default: - return panic(`Parsing of ${xfer.sourceType.kind} in a transformer is not supported`); - } - return consume(consumer, vol); - } else { - return panic(`Transformer ${xfer.kind} is not supported`); - } - } - - // Returns the code to deserialize `value` as type `t`. If `t` has - // an associated transformer, the code for that transformer is - // returned. - protected deserializer(value: ValueOrLambda, t: Type): ValueOrLambda { - const xf = transformationForType(t); - if (xf !== undefined) { - return this.transformer(value, xf.transformer, xf.targetType); - } - return matchType( - t, - _anyType => value, - _nullType => this.convFn("none", value), - _boolType => this.convFn("bool", value), - _integerType => this.convFn("int", value), - _doubleType => this.convFn("from-float", value), - _stringType => this.convFn("str", value), - arrayType => - compose(value, v => [ - this.conv("list"), - "(", - makeLambda(this.deserializer(identity, arrayType.items)).source, - ", ", - v, - ")" - ]), - classType => - compose(value, { - lambda: singleWord(this.nameForNamedType(classType), ".from_dict"), - value: undefined - }), - mapType => - compose(value, v => [ - this.conv("dict"), - "(", - makeLambda(this.deserializer(identity, mapType.values)).source, - ", ", - v, - ")" - ]), - enumType => compose(value, { lambda: singleWord(this.nameForNamedType(enumType)), value: undefined }), - unionType => { - // FIXME: handle via transformers - const deserializers = Array.from(unionType.members).map( - m => makeLambda(this.deserializer(identity, m)).source - ); - return compose(value, v => [ - this.conv("union"), - "([", - arrayIntercalate(", ", deserializers), - "], ", - v, - ")" - ]); - }, - transformedStringType => { - // FIXME: handle via transformers - if (transformedStringType.kind === "date-time") { - return this.convFn("from-datetime", value); - } - if (transformedStringType.kind === "uuid") { - return compose(value, v => [this.withImport("uuid", "UUID"), "(", v, ")"]); - } - return panic(`Transformed type ${transformedStringType.kind} not supported`); - } - ); - } - - protected serializer(value: ValueOrLambda, t: Type): ValueOrLambda { - const xf = transformationForType(t); - if (xf !== undefined) { - const reverse = xf.reverse; - return this.transformer(value, reverse.transformer, reverse.targetType); - } - return matchType( - t, - _anyType => value, - _nullType => this.convFn("none", value), - _boolType => this.convFn("bool", value), - _integerType => this.convFn("int", value), - _doubleType => this.convFn("to-float", value), - _stringType => this.convFn("str", value), - arrayType => - compose(value, v => [ - this.conv("list"), - "(", - makeLambda(this.serializer(identity, arrayType.items)).source, - ", ", - v, - ")" - ]), - classType => - compose(value, v => [this.conv("to-class"), "(", this.nameForNamedType(classType), ", ", v, ")"]), - mapType => - compose(value, v => [ - this.conv("dict"), - "(", - makeLambda(this.serializer(identity, mapType.values)).source, - ", ", - v, - ")" - ]), - enumType => compose(value, v => [this.conv("to-enum"), "(", this.nameForNamedType(enumType), ", ", v, ")"]), - unionType => { - const serializers = Array.from(unionType.members).map( - m => makeLambda(this.serializer(identity, m)).source - ); - return compose(value, v => [ - this.conv("union"), - "([", - arrayIntercalate(", ", serializers), - "], ", - v, - ")" - ]); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return compose(value, v => [v, ".isoformat()"]); - } - if (transformedStringType.kind === "uuid") { - return compose(value, v => ["str(", v, ")"]); - } - return panic(`Transformed type ${transformedStringType.kind} not supported`); - } - ); - } - - protected emitClassMembers(t: ClassType): void { - super.emitClassMembers(t); - this.ensureBlankLine(); - - const className = this.nameForNamedType(t); - - this.emitLine("@staticmethod"); - this.emitBlock( - ["def from_dict(", this.typingDecl("obj", "Any"), ")", this.typeHint(" -> ", this.namedType(t)), ":"], - () => { - const args: Sourcelike[] = []; - this.emitLine("assert isinstance(obj, dict)"); - this.forEachClassProperty(t, "none", (name, jsonName, cp) => { - const property = { value: ["obj.get(", this.string(jsonName), ")"] }; - this.emitLine(name, " = ", makeValue(this.deserializer(property, cp.type))); - args.push(name); - }); - this.emitLine("return ", className, "(", arrayIntercalate(", ", args), ")"); - } - ); - this.ensureBlankLine(); - - this.emitBlock(["def to_dict(self)", this.typeHint(" -> dict"), ":"], () => { - this.emitLine("result", this.typeHint(": dict"), " = {}"); - this.forEachClassProperty(t, "none", (name, jsonName, cp) => { - const property = { value: ["self.", name] }; - if (cp.isOptional) { - this.emitBlock(["if self.", name, " is not None:"], () => { - this.emitLine( - "result[", - this.string(jsonName), - "] = ", - makeValue(this.serializer(property, cp.type)) - ); - }); - } else { - this.emitLine( - "result[", - this.string(jsonName), - "] = ", - makeValue(this.serializer(property, cp.type)) - ); - } - }); - this.emitLine("return result"); - }); - } - - protected emitImports(): void { - super.emitImports(); - if (this._haveDateutil) { - this.emitLine("import dateutil.parser"); - } - - if (!this._haveTypeVar && !this._haveEnumTypeVar) return; - - this.ensureBlankLine(2); - if (this._haveTypeVar) { - this.emitTypeVar(this.typeVar(), []); - } - if (this._haveEnumTypeVar) { - this.emitTypeVar(this.enumTypeVar(), [", bound=", this.withImport("enum", "Enum")]); - } - } - - protected emitSupportCode(): void { - const map = Array.from(this._deserializerFunctions).map(f => [f, f] as [ConverterFunction, ConverterFunction]); - this.forEachWithBlankLines(map, ["interposing", 2], cf => { - this.emitConverter(cf); - }); - } - - protected makeTopLevelDependencyNames(_t: Type, topLevelName: Name): DependencyName[] { - const fromDict = new DependencyName( - this._converterNamer, - topLevelNameOrder, - l => `${l(topLevelName)}_from_dict` - ); - const toDict = new DependencyName(this._converterNamer, topLevelNameOrder, l => `${l(topLevelName)}_to_dict`); - this._topLevelConverterNames.set(topLevelName, { fromDict, toDict }); - return [fromDict, toDict]; - } - - protected emitDefaultLeadingComments(): void { - this.ensureBlankLine(); - if (this._haveDateutil) { - this.emitCommentLines([ - "This code parses date/times, so please", - "", - " pip install python-dateutil", - "" - ]); - } - this.emitCommentLines([ - "To use this code, make sure you", - "", - " import json", - "", - "and then, to convert JSON from a string, do", - "" - ]); - this.forEachTopLevel("none", (_, name) => { - const { fromDict } = defined(this._topLevelConverterNames.get(name)); - this.emitLine(this.commentLineStart, " result = ", fromDict, "(json.loads(json_string))"); - }); - } - - protected emitClosingCode(): void { - this.forEachTopLevel(["interposing", 2], (t, name) => { - const { fromDict, toDict } = defined(this._topLevelConverterNames.get(name)); - const pythonType = this.pythonType(t); - this.emitBlock( - ["def ", fromDict, "(", this.typingDecl("s", "Any"), ")", this.typeHint(" -> ", pythonType), ":"], - () => { - this.emitLine("return ", makeValue(this.deserializer({ value: "s" }, t))); - } - ); - this.ensureBlankLine(2); - this.emitBlock( - ["def ", toDict, "(x", this.typeHint(": ", pythonType), ")", this.typingReturn("Any"), ":"], - () => { - this.emitLine("return ", makeValue(this.serializer({ value: "x" }, t))); - } - ); - }); - } -} diff --git a/packages/quicktype-core/src/language/Python/JSONPythonRenderer.ts b/packages/quicktype-core/src/language/Python/JSONPythonRenderer.ts new file mode 100644 index 000000000..b06965694 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/JSONPythonRenderer.ts @@ -0,0 +1,1153 @@ +import { arrayIntercalate } from "collection-utils"; + +import { topLevelNameOrder } from "../../ConvenienceRenderer"; +import { DependencyName, type Name, funPrefixNamer } from "../../Naming"; +import { + type MultiWord, + type Sourcelike, + multiWord, + parenIfNeeded, + singleWord, +} from "../../Source"; +import { assertNever, defined, panic } from "../../support/Support"; +import { + ChoiceTransformer, + DecodingChoiceTransformer, + DecodingTransformer, + EncodingTransformer, + ParseStringTransformer, + StringifyTransformer, + type Transformer, + UnionInstantiationTransformer, + UnionMemberMatchTransformer, + transformationForType, +} from "../../Transformers"; +import type { ClassType, Type } from "../../Type"; +import { matchType } from "../../Type/TypeUtils"; + +import { PythonRenderer } from "./PythonRenderer"; +import { snakeNameStyle } from "./utils"; + +export type ConverterFunction = + | "none" + | "bool" + | "int" + | "from-float" + | "to-float" + | "str" + | "to-enum" + | "list" + | "to-class" + | "dict" + | "union" + | "from-datetime" + | "from-stringified-bool" + | "is-type"; + +interface TopLevelConverterNames { + fromDict: Name; + toDict: Name; +} + +// A value or a lambda. All four combinations are valid: +// +// * `value` and `lambda`: a value given by applying `value` to `lambda`, i.e. `lambda(value)` +// * `lambda` only: a lambda given by `lambda` +// * `value` only: a value given by `value` +// * neither: the identity function, i.e. `lambda x: x` +export interface ValueOrLambda { + lambda?: MultiWord; + value: Sourcelike | undefined; +} + +// Return the result of composing `input` and `f`. `input` can be a +// value or a lambda, but `f` must be a lambda or a TypeScript function +// (i.e. it can't be a value). +// +// * If `input` is a value, the result is `f(input)`. +// * If `input` is a lambda, the result is `lambda x: f(input(x))` +function compose( + input: ValueOrLambda, + f: (arg: Sourcelike) => Sourcelike, +): ValueOrLambda; +// FIXME: refactor this +// eslint-disable-next-line @typescript-eslint/unified-signatures +function compose(input: ValueOrLambda, f: ValueOrLambda): ValueOrLambda; +function compose( + input: ValueOrLambda, + f: ValueOrLambda | ((arg: Sourcelike) => Sourcelike), +): ValueOrLambda { + if (typeof f === "function") { + if (input.value !== undefined) { + // `input` is a value, so just apply `f` to its source form. + return { value: f(makeValue(input)) }; + } + + if (input.lambda !== undefined) { + // `input` is a lambda, so build `lambda x: f(input(x))`. + return { + lambda: multiWord( + " ", + "lambda x:", + f([parenIfNeeded(input.lambda), "(x)"]), + ), + value: undefined, + }; + } + + // `input` is the identify function, so the composition is `lambda x: f(x)`. + return { + lambda: multiWord(" ", "lambda x:", f("x")), + value: undefined, + }; + } + + if (f.value !== undefined) { + return panic("Cannot compose into a value"); + } + + if (f.lambda === undefined) { + // `f` is the identity function, so the result is just `input`. + return input; + } + + if (input.value === undefined) { + // `input` is a lambda + if (input.lambda === undefined) { + // `input` is the identity function, so the result is just `f`. + return f; + } + + // `input` is a lambda, so the result is `lambda x: f(input(x))`. + return { + lambda: multiWord( + "", + "lambda x: ", + parenIfNeeded(f.lambda), + "(", + parenIfNeeded(input.lambda), + "(x))", + ), + value: undefined, + }; + } + + // `input` is a value, so return `f(input)`. + return { lambda: f.lambda, value: makeValue(input) }; +} + +const identity: ValueOrLambda = { value: undefined }; + +// If `vol` is a lambda, return it in its source form. If it's +// a value, return a `lambda` that returns the value. +function makeLambda(vol: ValueOrLambda): MultiWord { + if (vol.lambda !== undefined) { + if (vol.value === undefined) { + return vol.lambda; + } + + return multiWord( + "", + "lambda x: ", + parenIfNeeded(vol.lambda), + "(", + vol.value, + ")", + ); + } + if (vol.value !== undefined) { + return multiWord(" ", "lambda x:", vol.value); + } + + return multiWord(" ", "lambda x:", "x"); +} + +// If `vol` is a value, return the value in its source form. +// Calling this with `vol` being a lambda is not allowed. +function makeValue(vol: ValueOrLambda): Sourcelike { + if (vol.value === undefined) { + return panic("Cannot make value from lambda without value"); + } + + if (vol.lambda !== undefined) { + return [parenIfNeeded(vol.lambda), "(", vol.value, ")"]; + } + + return vol.value; +} + +export class JSONPythonRenderer extends PythonRenderer { + private readonly _deserializerFunctions = new Set(); + + private readonly _converterNamer = funPrefixNamer("converter", (s) => + snakeNameStyle(s, false, this.pyOptions.nicePropertyNames), + ); + + private readonly _topLevelConverterNames = new Map< + Name, + TopLevelConverterNames + >(); + + private _haveTypeVar = false; + + private _haveEnumTypeVar = false; + + private _haveDateutil = false; + + protected emitTypeVar(tvar: string, constraints: Sourcelike): void { + if (!this.pyOptions.features.typeHints) { + return; + } + + this.emitLine( + tvar, + " = ", + this.withTyping("TypeVar"), + "(", + this.string(tvar), + constraints, + ")", + ); + } + + protected typeVar(): string { + this._haveTypeVar = true; + // FIXME: This is ugly, but the code that requires the type variables, in + // `emitImports` actually runs after imports have been imported. The proper + // solution would be to either allow more complex dependencies, or to + // gather-emit the type variable declarations, too. Unfortunately the + // gather-emit is a bit buggy with blank lines, and I can't be bothered to + // fix it now. + this.withTyping("TypeVar"); + return "T"; + } + + protected enumTypeVar(): string { + this._haveEnumTypeVar = true; + // See the comment above. + this.withTyping("TypeVar"); + this.withImport("enum", "Enum"); + return "EnumT"; + } + + protected cast(type: Sourcelike, v: Sourcelike): Sourcelike { + if (!this.pyOptions.features.typeHints) { + return v; + } + + return [this.withTyping("cast"), "(", type, ", ", v, ")"]; + } + + protected emitNoneConverter(): void { + // FIXME: We can't return the None type here because mypy thinks that means + // We're not returning any value, when we're actually returning `None`. + this.emitBlock( + [ + "def from_none(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> ", this.withTyping("Any")), + ":", + ], + () => { + this.emitLine("assert x is None"); + this.emitLine("return x"); + }, + ); + } + + protected emitBoolConverter(): void { + this.emitBlock( + [ + "def from_bool(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> bool"), + ":", + ], + () => { + this.emitLine("assert isinstance(x, bool)"); + this.emitLine("return x"); + }, + ); + } + + protected emitIntConverter(): void { + this.emitBlock( + [ + "def from_int(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> int"), + ":", + ], + () => { + this.emitLine( + "assert isinstance(x, int) and not isinstance(x, bool)", + ); + this.emitLine("return x"); + }, + ); + } + + protected emitFromFloatConverter(): void { + this.emitBlock( + [ + "def from_float(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> float"), + ":", + ], + () => { + this.emitLine( + "assert isinstance(x, (float, int)) and not isinstance(x, bool)", + ); + this.emitLine("return float(x)"); + }, + ); + } + + protected emitToFloatConverter(): void { + this.emitBlock( + [ + "def to_float(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> float"), + ":", + ], + () => { + this.emitLine("assert isinstance(x, (int, float))"); + this.emitLine("return x"); + }, + ); + } + + protected emitStrConverter(): void { + this.emitBlock( + [ + "def from_str(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> str"), + ":", + ], + () => { + const strType = "str"; + this.emitLine("assert isinstance(x, ", strType, ")"); + this.emitLine("return x"); + }, + ); + } + + protected emitToEnumConverter(): void { + const tvar = this.enumTypeVar(); + this.emitBlock( + [ + "def to_enum(c", + this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"), + ", ", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> ", tvar), + ":", + ], + () => { + this.emitLine("assert isinstance(x, c)"); + this.emitLine("return x.value"); + }, + ); + } + + protected emitListConverter(): void { + const tvar = this.typeVar(); + this.emitBlock( + [ + "def from_list(f", + this.typeHint( + ": ", + this.withTyping("Callable"), + "[[", + this.withTyping("Any"), + "], ", + tvar, + "]", + ), + ", ", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> ", this.withTyping("List"), "[", tvar, "]"), + ":", + ], + () => { + this.emitLine("assert isinstance(x, list)"); + this.emitLine("return [f(y) for y in x]"); + }, + ); + } + + protected emitToClassConverter(): void { + const tvar = this.typeVar(); + this.emitBlock( + [ + "def to_class(c", + this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"), + ", ", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> dict"), + ":", + ], + () => { + this.emitLine("assert isinstance(x, c)"); + this.emitLine( + "return ", + this.cast(this.withTyping("Any"), "x"), + ".to_dict()", + ); + }, + ); + } + + protected emitDictConverter(): void { + const tvar = this.typeVar(); + this.emitBlock( + [ + "def from_dict(f", + this.typeHint( + ": ", + this.withTyping("Callable"), + "[[", + this.withTyping("Any"), + "], ", + tvar, + "]", + ), + ", ", + this.typingDecl("x", "Any"), + ")", + this.typeHint( + " -> ", + this.withTyping("Dict"), + "[str, ", + tvar, + "]", + ), + ":", + ], + () => { + this.emitLine("assert isinstance(x, dict)"); + this.emitLine("return { k: f(v) for (k, v) in x.items() }"); + }, + ); + } + + // This is not easily idiomatically typeable in Python. See + // https://stackoverflow.com/questions/51066468/computed-types-in-mypy/51084497 + protected emitUnionConverter(): void { + this.emitMultiline(`def from_union(fs, x): + for f in fs: + try: + return f(x) + except: + pass + assert False`); + } + + protected emitFromDatetimeConverter(): void { + this.emitBlock( + [ + "def from_datetime(", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> ", this.withImport("datetime", "datetime")), + ":", + ], + () => { + this._haveDateutil = true; + this.emitLine("return dateutil.parser.parse(x)"); + }, + ); + } + + protected emitFromStringifiedBoolConverter(): void { + this.emitBlock( + [ + "def from_stringified_bool(x", + this.typeHint(": str"), + ")", + this.typeHint(" -> bool"), + ":", + ], + () => { + this.emitBlock('if x == "true":', () => + this.emitLine("return True"), + ); + this.emitBlock('if x == "false":', () => + this.emitLine("return False"), + ); + this.emitLine("assert False"); + }, + ); + } + + protected emitIsTypeConverter(): void { + const tvar = this.typeVar(); + this.emitBlock( + [ + "def is_type(t", + this.typeHint(": ", this.withTyping("Type"), "[", tvar, "]"), + ", ", + this.typingDecl("x", "Any"), + ")", + this.typeHint(" -> ", tvar), + ":", + ], + () => { + this.emitLine("assert isinstance(x, t)"); + this.emitLine("return x"); + }, + ); + } + + protected emitConverter(cf: ConverterFunction): void { + switch (cf) { + case "none": { + this.emitNoneConverter(); + return; + } + + case "bool": { + this.emitBoolConverter(); + return; + } + + case "int": { + this.emitIntConverter(); + return; + } + + case "from-float": { + this.emitFromFloatConverter(); + return; + } + + case "to-float": { + this.emitToFloatConverter(); + return; + } + + case "str": { + this.emitStrConverter(); + return; + } + + case "to-enum": { + this.emitToEnumConverter(); + return; + } + + case "list": { + this.emitListConverter(); + return; + } + + case "to-class": { + this.emitToClassConverter(); + return; + } + + case "dict": { + this.emitDictConverter(); + return; + } + + case "union": { + this.emitUnionConverter(); + return; + } + + case "from-datetime": { + this.emitFromDatetimeConverter(); + return; + } + + case "from-stringified-bool": { + this.emitFromStringifiedBoolConverter(); + return; + } + + case "is-type": { + this.emitIsTypeConverter(); + return; + } + + default: + assertNever(cf); + } + } + + // Return the name of the Python converter function `cf`. + protected conv(cf: ConverterFunction): Sourcelike { + this._deserializerFunctions.add(cf); + const name = cf.replace(/-/g, "_"); + if ( + cf.startsWith("from-") || + cf.startsWith("to-") || + cf.startsWith("is-") + ) + return name; + return ["from_", name]; + } + + // Applies the converter function to `arg` + protected convFn(cf: ConverterFunction, arg: ValueOrLambda): ValueOrLambda { + return compose(arg, { + lambda: singleWord(this.conv(cf)), + value: undefined, + }); + } + + protected typeObject(t: Type): Sourcelike { + const s = matchType( + t, + (_anyType) => undefined, + (_nullType) => "type(None)", + (_boolType) => "bool", + (_integerType) => "int", + (_doubleType) => "float", + (_stringType) => "str", + (_arrayType) => "List", + (classType) => this.nameForNamedType(classType), + (_mapType) => "dict", + (enumType) => this.nameForNamedType(enumType), + (_unionType) => undefined, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return this.withImport("datetime", "datetime"); + } + + if (transformedStringType.kind === "uuid") { + return this.withImport("uuid", "UUID"); + } + + return undefined; + }, + ); + if (s === undefined) { + return panic(`No type object for ${t.kind}`); + } + + return s; + } + + protected transformer( + inputTransformer: ValueOrLambda, + xfer: Transformer, + targetType: Type, + ): ValueOrLambda { + const consume = ( + consumer: Transformer | undefined, + vol: ValueOrLambda, + ): ValueOrLambda => { + if (consumer === undefined) { + return vol; + } + + return this.transformer(vol, consumer, targetType); + }; + + const isType = ( + t: Type, + valueToCheck: ValueOrLambda, + ): ValueOrLambda => { + return compose(valueToCheck, (v) => [ + this.conv("is-type"), + "(", + this.typeObject(t), + ", ", + v, + ")", + ]); + }; + + if ( + xfer instanceof DecodingChoiceTransformer || + xfer instanceof ChoiceTransformer + ) { + const lambdas = xfer.transformers.map( + (x) => + makeLambda(this.transformer(identity, x, targetType)) + .source, + ); + return compose(inputTransformer, (v) => [ + this.conv("union"), + "([", + arrayIntercalate(", ", lambdas), + "], ", + v, + ")", + ]); + } + if (xfer instanceof DecodingTransformer) { + const consumer = xfer.consumer; + const vol = this.deserializer(inputTransformer, xfer.sourceType); + return consume(consumer, vol); + } + if (xfer instanceof EncodingTransformer) { + return this.serializer(inputTransformer, xfer.sourceType); + } + if (xfer instanceof UnionInstantiationTransformer) { + return inputTransformer; + } + if (xfer instanceof UnionMemberMatchTransformer) { + const consumer = xfer.transformer; + const vol = isType(xfer.memberType, inputTransformer); + return consume(consumer, vol); + } + if (xfer instanceof ParseStringTransformer) { + const consumer = xfer.consumer; + const immediateTargetType = + consumer === undefined ? targetType : consumer.sourceType; + let vol: ValueOrLambda; + switch (immediateTargetType.kind) { + case "integer": + vol = compose(inputTransformer, (v) => ["int(", v, ")"]); + break; + case "bool": + vol = this.convFn( + "from-stringified-bool", + inputTransformer, + ); + break; + case "enum": + vol = this.deserializer( + inputTransformer, + immediateTargetType, + ); + break; + case "date-time": + vol = this.convFn("from-datetime", inputTransformer); + break; + case "uuid": + vol = compose(inputTransformer, (v) => [ + this.withImport("uuid", "UUID"), + "(", + v, + ")", + ]); + break; + default: + return panic( + `Parsing of ${immediateTargetType.kind} in a transformer is not supported`, + ); + } + + return consume(consumer, vol); + } + if (xfer instanceof StringifyTransformer) { + const consumer = xfer.consumer; + let vol: ValueOrLambda; + switch (xfer.sourceType.kind) { + case "integer": + vol = compose(inputTransformer, (v) => ["str(", v, ")"]); + break; + case "bool": + vol = compose(inputTransformer, (v) => [ + "str(", + v, + ").lower()", + ]); + break; + case "enum": + vol = this.serializer(inputTransformer, xfer.sourceType); + break; + case "date-time": + vol = compose(inputTransformer, (v) => [v, ".isoformat()"]); + break; + case "uuid": + vol = compose(inputTransformer, (v) => ["str(", v, ")"]); + break; + default: + return panic( + `Parsing of ${xfer.sourceType.kind} in a transformer is not supported`, + ); + } + + return consume(consumer, vol); + } + + return panic(`Transformer ${xfer.kind} is not supported`); + } + + // Returns the code to deserialize `value` as type `t`. If `t` has + // an associated transformer, the code for that transformer is + // returned. + protected deserializer(value: ValueOrLambda, t: Type): ValueOrLambda { + const xf = transformationForType(t); + if (xf !== undefined) { + return this.transformer(value, xf.transformer, xf.targetType); + } + + return matchType( + t, + (_anyType) => value, + (_nullType) => this.convFn("none", value), + (_boolType) => this.convFn("bool", value), + (_integerType) => this.convFn("int", value), + (_doubleType) => this.convFn("from-float", value), + (_stringType) => this.convFn("str", value), + (arrayType) => + compose(value, (v) => [ + this.conv("list"), + "(", + makeLambda(this.deserializer(identity, arrayType.items)) + .source, + ", ", + v, + ")", + ]), + (classType) => + compose(value, { + lambda: singleWord( + this.nameForNamedType(classType), + ".from_dict", + ), + value: undefined, + }), + (mapType) => + compose(value, (v) => [ + this.conv("dict"), + "(", + makeLambda(this.deserializer(identity, mapType.values)) + .source, + ", ", + v, + ")", + ]), + (enumType) => + compose(value, { + lambda: singleWord(this.nameForNamedType(enumType)), + value: undefined, + }), + (unionType) => { + // FIXME: handle via transformers + const deserializers = Array.from(unionType.members).map( + (m) => makeLambda(this.deserializer(identity, m)).source, + ); + return compose(value, (v) => [ + this.conv("union"), + "([", + arrayIntercalate(", ", deserializers), + "], ", + v, + ")", + ]); + }, + (transformedStringType) => { + // FIXME: handle via transformers + if (transformedStringType.kind === "date-time") { + return this.convFn("from-datetime", value); + } + + if (transformedStringType.kind === "uuid") { + return compose(value, (v) => [ + this.withImport("uuid", "UUID"), + "(", + v, + ")", + ]); + } + + return panic( + `Transformed type ${transformedStringType.kind} not supported`, + ); + }, + ); + } + + protected serializer(value: ValueOrLambda, t: Type): ValueOrLambda { + const xf = transformationForType(t); + if (xf !== undefined) { + const reverse = xf.reverse; + return this.transformer( + value, + reverse.transformer, + reverse.targetType, + ); + } + + return matchType( + t, + (_anyType) => value, + (_nullType) => this.convFn("none", value), + (_boolType) => this.convFn("bool", value), + (_integerType) => this.convFn("int", value), + (_doubleType) => this.convFn("to-float", value), + (_stringType) => this.convFn("str", value), + (arrayType) => + compose(value, (v) => [ + this.conv("list"), + "(", + makeLambda(this.serializer(identity, arrayType.items)) + .source, + ", ", + v, + ")", + ]), + (classType) => + compose(value, (v) => [ + this.conv("to-class"), + "(", + this.nameForNamedType(classType), + ", ", + v, + ")", + ]), + (mapType) => + compose(value, (v) => [ + this.conv("dict"), + "(", + makeLambda(this.serializer(identity, mapType.values)) + .source, + ", ", + v, + ")", + ]), + (enumType) => + compose(value, (v) => [ + this.conv("to-enum"), + "(", + this.nameForNamedType(enumType), + ", ", + v, + ")", + ]), + (unionType) => { + const serializers = Array.from(unionType.members).map( + (m) => makeLambda(this.serializer(identity, m)).source, + ); + return compose(value, (v) => [ + this.conv("union"), + "([", + arrayIntercalate(", ", serializers), + "], ", + v, + ")", + ]); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return compose(value, (v) => [v, ".isoformat()"]); + } + + if (transformedStringType.kind === "uuid") { + return compose(value, (v) => ["str(", v, ")"]); + } + + return panic( + `Transformed type ${transformedStringType.kind} not supported`, + ); + }, + ); + } + + protected emitClassMembers(t: ClassType): void { + super.emitClassMembers(t); + this.ensureBlankLine(); + + const className = this.nameForNamedType(t); + + this.emitLine("@staticmethod"); + this.emitBlock( + [ + "def from_dict(", + this.typingDecl("obj", "Any"), + ")", + this.typeHint(" -> ", this.namedType(t)), + ":", + ], + () => { + const args: Sourcelike[] = []; + this.emitLine("assert isinstance(obj, dict)"); + this.forEachClassProperty(t, "none", (name, jsonName, cp) => { + const property = { + value: ["obj.get(", this.string(jsonName), ")"], + }; + this.emitLine( + name, + " = ", + makeValue(this.deserializer(property, cp.type)), + ); + args.push(name); + }); + this.emitLine( + "return ", + className, + "(", + arrayIntercalate(", ", args), + ")", + ); + }, + ); + this.ensureBlankLine(); + + this.emitBlock( + ["def to_dict(self)", this.typeHint(" -> dict"), ":"], + () => { + this.emitLine("result", this.typeHint(": dict"), " = {}"); + this.forEachClassProperty(t, "none", (name, jsonName, cp) => { + const property = { value: ["self.", name] }; + if (cp.isOptional) { + this.emitBlock( + ["if self.", name, " is not None:"], + () => { + this.emitLine( + "result[", + this.string(jsonName), + "] = ", + makeValue( + this.serializer(property, cp.type), + ), + ); + }, + ); + } else { + this.emitLine( + "result[", + this.string(jsonName), + "] = ", + makeValue(this.serializer(property, cp.type)), + ); + } + }); + this.emitLine("return result"); + }, + ); + } + + protected emitImports(): void { + super.emitImports(); + if (this._haveDateutil) { + this.emitLine("import dateutil.parser"); + } + + if (!this._haveTypeVar && !this._haveEnumTypeVar) return; + + this.ensureBlankLine(2); + if (this._haveTypeVar) { + this.emitTypeVar(this.typeVar(), []); + } + + if (this._haveEnumTypeVar) { + this.emitTypeVar(this.enumTypeVar(), [ + ", bound=", + this.withImport("enum", "Enum"), + ]); + } + } + + protected emitSupportCode(): void { + const map = Array.from(this._deserializerFunctions).map( + (f) => [f, f] as [ConverterFunction, ConverterFunction], + ); + this.forEachWithBlankLines(map, ["interposing", 2], (cf) => { + this.emitConverter(cf); + }); + } + + protected makeTopLevelDependencyNames( + _t: Type, + topLevelName: Name, + ): DependencyName[] { + const fromDict = new DependencyName( + this._converterNamer, + topLevelNameOrder, + (l) => `${l(topLevelName)}_from_dict`, + ); + const toDict = new DependencyName( + this._converterNamer, + topLevelNameOrder, + (l) => `${l(topLevelName)}_to_dict`, + ); + this._topLevelConverterNames.set(topLevelName, { fromDict, toDict }); + return [fromDict, toDict]; + } + + protected emitDefaultLeadingComments(): void { + this.ensureBlankLine(); + if (this._haveDateutil) { + this.emitCommentLines([ + "This code parses date/times, so please", + "", + " pip install python-dateutil", + "", + ]); + } + + this.emitCommentLines([ + "To use this code, make sure you", + "", + " import json", + "", + "and then, to convert JSON from a string, do", + "", + ]); + this.forEachTopLevel("none", (_, name) => { + const { fromDict } = defined( + this._topLevelConverterNames.get(name), + ); + this.emitLine( + this.commentLineStart, + " result = ", + fromDict, + "(json.loads(json_string))", + ); + }); + } + + protected emitClosingCode(): void { + this.forEachTopLevel(["interposing", 2], (t, name) => { + const { fromDict, toDict } = defined( + this._topLevelConverterNames.get(name), + ); + const pythonType = this.pythonType(t); + this.emitBlock( + [ + "def ", + fromDict, + "(", + this.typingDecl("s", "Any"), + ")", + this.typeHint(" -> ", pythonType), + ":", + ], + () => { + this.emitLine( + "return ", + makeValue(this.deserializer({ value: "s" }, t)), + ); + }, + ); + this.ensureBlankLine(2); + this.emitBlock( + [ + "def ", + toDict, + "(x", + this.typeHint(": ", pythonType), + ")", + this.typingReturn("Any"), + ":", + ], + () => { + this.emitLine( + "return ", + makeValue(this.serializer({ value: "x" }, t)), + ); + }, + ); + }); + } +} diff --git a/packages/quicktype-core/src/language/Python/PythonRenderer.ts b/packages/quicktype-core/src/language/Python/PythonRenderer.ts new file mode 100644 index 000000000..fd7bb84e8 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/PythonRenderer.ts @@ -0,0 +1,436 @@ +import { + arrayIntercalate, + iterableFirst, + mapSortBy, + mapUpdateInto, + setUnionInto, +} from "collection-utils"; + +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { stringEscape } from "../../support/Strings"; +import { defined, panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { followTargetType } from "../../Transformers"; +import { + type ClassProperty, + ClassType, + EnumType, + type Type, + UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { forbiddenPropertyNames, forbiddenTypeNames } from "./constants"; +import type { pythonOptions } from "./language"; +import { classNameStyle, snakeNameStyle } from "./utils"; + +export class PythonRenderer extends ConvenienceRenderer { + private readonly imports: Map> = new Map(); + + private readonly declaredTypes: Set = new Set(); + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly pyOptions: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return forbiddenTypeNames; + } + + protected forbiddenForObjectProperties( + _: ClassType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { + names: forbiddenPropertyNames as unknown as string[], + includeGlobalForbidden: false, + }; + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("type", classNameStyle); + } + + protected namerForObjectProperty(): Namer { + return funPrefixNamer("property", (s) => + snakeNameStyle(s, false, this.pyOptions.nicePropertyNames), + ); + } + + protected makeUnionMemberNamer(): null { + return null; + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("enum-case", (s) => + snakeNameStyle(s, true, this.pyOptions.nicePropertyNames), + ); + } + + protected get commentLineStart(): string { + return "# "; + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + if (lines.length === 1) { + const docstring = modifySource((content) => { + if (content.endsWith('"')) { + return content.slice(0, -1) + '\\"'; + } + + return content; + }, lines[0]); + this.emitComments([ + { customLines: [docstring], lineStart: '"""', lineEnd: '"""' }, + ]); + } else { + this.emitCommentLines(lines, { + firstLineStart: '"""', + lineStart: "", + afterComment: '"""', + }); + } + } + + protected get needsTypeDeclarationBeforeUse(): boolean { + return true; + } + + protected canBeForwardDeclared(t: Type): boolean { + const kind = t.kind; + return kind === "class" || kind === "enum"; + } + + protected emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line); + this.indent(f); + } + + protected string(s: string): Sourcelike { + const openQuote = '"'; + return [openQuote, stringEscape(s), '"']; + } + + protected withImport(module: string, name: string): Sourcelike { + if (this.pyOptions.features.typeHints || module !== "typing") { + // FIXME: This is ugly. We should rather not generate that import in the first + // place, but right now we just make the type source and then throw it away. It's + // not a performance issue, so it's fine, I just bemoan this special case, and + // potential others down the road. + mapUpdateInto(this.imports, module, (s) => + s ? setUnionInto(s, [name]) : new Set([name]), + ); + } + + return name; + } + + protected withTyping(name: string): Sourcelike { + return this.withImport("typing", name); + } + + protected namedType(t: Type): Sourcelike { + const name = this.nameForNamedType(t); + if (this.declaredTypes.has(t)) return name; + return ["'", name, "'"]; + } + + protected pythonType(t: Type, _isRootTypeDef = false): Sourcelike { + const actualType = followTargetType(t); + + return matchType( + actualType, + (_anyType) => this.withTyping("Any"), + (_nullType) => "None", + (_boolType) => "bool", + (_integerType) => "int", + (_doubletype) => "float", + (_stringType) => "str", + (arrayType) => [ + this.withTyping("List"), + "[", + this.pythonType(arrayType.items), + "]", + ], + (classType) => this.namedType(classType), + (mapType) => [ + this.withTyping("Dict"), + "[str, ", + this.pythonType(mapType.values), + "]", + ], + (enumType) => this.namedType(enumType), + (unionType) => { + const [hasNull, nonNulls] = removeNullFromUnion(unionType); + const memberTypes = Array.from(nonNulls).map((m) => + this.pythonType(m), + ); + + if (hasNull !== null) { + const rest: string[] = []; + if ( + !this.getAlphabetizeProperties() && + (this.pyOptions.features.dataClasses || + this.pyOptions.pydanticBaseModel) && + _isRootTypeDef + ) { + // Only push "= None" if this is a root level type def + // otherwise we may get type defs like List[Optional[int] = None] + // which are invalid + rest.push(" = None"); + } + + if (nonNulls.size > 1) { + this.withImport("typing", "Union"); + return [ + this.withTyping("Optional"), + "[Union[", + arrayIntercalate(", ", memberTypes), + "]]", + ...rest, + ]; + } + + return [ + this.withTyping("Optional"), + "[", + defined(iterableFirst(memberTypes)), + "]", + ...rest, + ]; + } + + return [ + this.withTyping("Union"), + "[", + arrayIntercalate(", ", memberTypes), + "]", + ]; + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return this.withImport("datetime", "datetime"); + } + + if (transformedStringType.kind === "uuid") { + return this.withImport("uuid", "UUID"); + } + + return panic( + `Transformed type ${transformedStringType.kind} not supported`, + ); + }, + ); + } + + protected declarationLine(t: Type): Sourcelike { + if (t instanceof ClassType) { + if (this.pyOptions.pydanticBaseModel) { + return [ + "class ", + this.nameForNamedType(t), + "(", + this.withImport("pydantic", "BaseModel"), + "):", + ]; + } + return ["class ", this.nameForNamedType(t), ":"]; + } + + if (t instanceof EnumType) { + return [ + "class ", + this.nameForNamedType(t), + "(", + this.withImport("enum", "Enum"), + "):", + ]; + } + + return panic(`Can't declare type ${t.kind}`); + } + + protected declareType(t: T, emitter: () => void): void { + this.emitBlock(this.declarationLine(t), () => { + this.emitDescription(this.descriptionForType(t)); + emitter(); + }); + this.declaredTypes.add(t); + } + + protected emitClassMembers(t: ClassType): void { + if ( + this.pyOptions.features.dataClasses || + this.pyOptions.pydanticBaseModel + ) + return; + + const args: Sourcelike[] = []; + this.forEachClassProperty(t, "none", (name, _, cp) => { + args.push([name, this.typeHint(": ", this.pythonType(cp.type))]); + }); + this.emitBlock( + [ + "def __init__(self, ", + arrayIntercalate(", ", args), + ")", + this.typeHint(" -> None"), + ":", + ], + () => { + if (args.length === 0) { + this.emitLine("pass"); + } else { + this.forEachClassProperty(t, "none", (name) => { + this.emitLine("self.", name, " = ", name); + }); + } + }, + ); + } + + protected typeHint(...sl: Sourcelike[]): Sourcelike { + if (this.pyOptions.features.typeHints) { + return sl; + } + + return []; + } + + protected typingDecl(name: Sourcelike, type: string): Sourcelike { + return [name, this.typeHint(": ", this.withTyping(type))]; + } + + protected typingReturn(type: string): Sourcelike { + return this.typeHint(" -> ", this.withTyping(type)); + } + + protected sortClassProperties( + properties: ReadonlyMap, + propertyNames: ReadonlyMap, + ): ReadonlyMap { + if ( + this.pyOptions.features.dataClasses || + this.pyOptions.pydanticBaseModel + ) { + return mapSortBy(properties, (p: ClassProperty) => { + return (p.type instanceof UnionType && + nullableFromUnion(p.type) != null) || + p.isOptional + ? 1 + : 0; + }); + } + + return super.sortClassProperties(properties, propertyNames); + } + + protected emitClass(t: ClassType): void { + if ( + this.pyOptions.features.dataClasses && + !this.pyOptions.pydanticBaseModel + ) { + this.emitLine("@", this.withImport("dataclasses", "dataclass")); + } + + this.declareType(t, () => { + if (this.pyOptions.features.typeHints) { + if (t.getProperties().size === 0) { + this.emitLine("pass"); + } else { + this.forEachClassProperty( + t, + "none", + (name, jsonName, cp) => { + this.emitLine( + name, + this.typeHint( + ": ", + this.pythonType(cp.type, true), + ), + ); + this.emitDescription( + this.descriptionForClassProperty(t, jsonName), + ); + }, + ); + } + + this.ensureBlankLine(); + } + + this.emitClassMembers(t); + }); + } + + protected emitEnum(t: EnumType): void { + this.declareType(t, () => { + this.forEachEnumCase(t, "none", (name, jsonName) => { + this.emitLine([name, " = ", this.string(jsonName)]); + }); + }); + } + + protected emitImports(): void { + this.imports.forEach((names, module) => { + this.emitLine( + "from ", + module, + " import ", + Array.from(names).join(", "), + ); + }); + } + + protected emitSupportCode(): void { + return; + } + + protected emitClosingCode(): void { + return; + } + + protected emitSourceStructure(_givenOutputFilename: string): void { + const declarationLines = this.gatherSource(() => { + this.forEachNamedType( + ["interposing", 2], + (c: ClassType) => this.emitClass(c), + (e) => this.emitEnum(e), + (_u) => { + return; + }, + ); + }); + + const closingLines = this.gatherSource(() => this.emitClosingCode()); + const supportLines = this.gatherSource(() => this.emitSupportCode()); + + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } + + this.ensureBlankLine(); + this.emitImports(); + this.ensureBlankLine(2); + this.emitGatheredSource(supportLines); + this.ensureBlankLine(2); + this.emitGatheredSource(declarationLines); + this.ensureBlankLine(2); + this.emitGatheredSource(closingLines); + } +} diff --git a/packages/quicktype-core/src/language/Python/constants.ts b/packages/quicktype-core/src/language/Python/constants.ts new file mode 100644 index 000000000..d32c10923 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/constants.ts @@ -0,0 +1,59 @@ +export const forbiddenTypeNames = [ + "Any", + "True", + "False", + "None", + "Enum", + "List", + "Dict", + "Optional", + "Union", + "Iterable", + "Type", + "TypeVar", + "T", + "EnumT", +] as const; + +export const forbiddenPropertyNames = [ + "and", + "as", + "assert", + "async", + "await", + "bool", + "break", + "class", + "continue", + "datetime", + "def", + "del", + "dict", + "elif", + "else", + "except", + "finally", + "float", + "for", + "from", + "global", + "if", + "import", + "in", + "int", + "is", + "lambda", + "nonlocal", + "not", + "or", + "pass", + "print", + "raise", + "return", + "self", + "str", + "try", + "while", + "with", + "yield", +] as const; diff --git a/packages/quicktype-core/src/language/Python/index.ts b/packages/quicktype-core/src/language/Python/index.ts new file mode 100644 index 000000000..7c7b92ba3 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/index.ts @@ -0,0 +1,3 @@ +export { PythonTargetLanguage, pythonOptions } from "./language"; +export { PythonRenderer } from "./PythonRenderer"; +export { JSONPythonRenderer } from "./JSONPythonRenderer"; diff --git a/packages/quicktype-core/src/language/Python/language.ts b/packages/quicktype-core/src/language/Python/language.ts new file mode 100644 index 000000000..c6a35b0db --- /dev/null +++ b/packages/quicktype-core/src/language/Python/language.ts @@ -0,0 +1,110 @@ +import { iterableSome } from "collection-utils"; + +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import { + type PrimitiveStringTypeKind, + type TransformedStringTypeKind, + type Type, + UnionType, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { JSONPythonRenderer } from "./JSONPythonRenderer"; +import { PythonRenderer } from "./PythonRenderer"; + +export interface PythonFeatures { + dataClasses: boolean; + typeHints: boolean; +} + +export const pythonOptions = { + features: new EnumOption( + "python-version", + "Python version", + { + "3.5": { typeHints: false, dataClasses: false }, + "3.6": { typeHints: true, dataClasses: false }, + "3.7": { typeHints: true, dataClasses: true }, + }, + "3.6", + ), + justTypes: new BooleanOption("just-types", "Classes only", false), + nicePropertyNames: new BooleanOption( + "nice-property-names", + "Transform property names to be Pythonic", + true, + ), + pydanticBaseModel: new BooleanOption( + "pydantic-base-model", + "Uses pydantic BaseModel", + false, + ), +}; + +export const pythonLanguageConfig = { + displayName: "Python", + names: ["python", "py"], + extension: "py", +} as const; + +export class PythonTargetLanguage extends TargetLanguage< + typeof pythonLanguageConfig +> { + public constructor() { + super(pythonLanguageConfig); + } + + public getOptions(): typeof pythonOptions { + return pythonOptions; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("time", dateTimeType); + mapping.set("date-time", dateTimeType); + mapping.set("uuid", "uuid"); + mapping.set("integer-string", "integer-string"); + mapping.set("bool-string", "bool-string"); + return mapping; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + public get supportsOptionalClassProperties(): boolean { + return false; + } + + public needsTransformerForType(t: Type): boolean { + if (t instanceof UnionType) { + return iterableSome(t.members, (m) => + this.needsTransformerForType(m), + ); + } + + return t.kind === "integer-string" || t.kind === "bool-string"; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): PythonRenderer { + const options = getOptionValues(pythonOptions, untypedOptionValues); + if (options.justTypes) { + return new PythonRenderer(this, renderContext, options); + } + + return new JSONPythonRenderer(this, renderContext, options); + } +} diff --git a/packages/quicktype-core/src/language/Python/utils.ts b/packages/quicktype-core/src/language/Python/utils.ts new file mode 100644 index 000000000..e39a9c7e1 --- /dev/null +++ b/packages/quicktype-core/src/language/Python/utils.ts @@ -0,0 +1,89 @@ +import unicode from "unicode-properties"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + originalWord, + splitIntoWords, + utf16LegalizeCharacters, +} from "../../support/Strings"; + +function isNormalizedStartCharacter3(utf16Unit: number): boolean { + // FIXME: add Other_ID_Start - https://docs.python.org/3/reference/lexical_analysis.html#identifiers + const category: string = unicode.getCategory(utf16Unit); + return ["Lu", "Ll", "Lt", "Lm", "Lo", "Nl"].includes(category); +} + +function isNormalizedPartCharacter3(utf16Unit: number): boolean { + // FIXME: add Other_ID_Continue - https://docs.python.org/3/reference/lexical_analysis.html#identifiers + if (isNormalizedStartCharacter3(utf16Unit)) return true; + const category: string = unicode.getCategory(utf16Unit); + return ["Mn", "Mc", "Nd", "Pc"].includes(category); +} + +function isStartCharacter3(utf16Unit: number): boolean { + const s = String.fromCharCode(utf16Unit).normalize("NFKC"); + const l = s.length; + if (l === 0 || !isNormalizedStartCharacter3(s.charCodeAt(0))) return false; + for (let i = 1; i < l; i++) { + if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; + } + + return true; +} + +function isPartCharacter3(utf16Unit: number): boolean { + const s = String.fromCharCode(utf16Unit).normalize("NFKC"); + const l = s.length; + for (let i = 0; i < l; i++) { + if (!isNormalizedPartCharacter3(s.charCodeAt(i))) return false; + } + + return true; +} + +const legalizeName3 = utf16LegalizeCharacters(isPartCharacter3); + +export function classNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName3, + firstUpperWordStyle, + firstUpperWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter3, + ); +} + +function getWordStyle(uppercase: boolean, forceSnakeNameStyle: boolean) { + if (!forceSnakeNameStyle) { + return originalWord; + } + + return uppercase ? allUpperWordStyle : allLowerWordStyle; +} + +export function snakeNameStyle( + original: string, + uppercase: boolean, + forceSnakeNameStyle: boolean, +): string { + const wordStyle = getWordStyle(uppercase, forceSnakeNameStyle); + const separator = forceSnakeNameStyle ? "_" : ""; + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName3, + wordStyle, + wordStyle, + wordStyle, + wordStyle, + separator, + isStartCharacter3, + ); +} diff --git a/packages/quicktype-core/src/language/Ruby/RubyRenderer.ts b/packages/quicktype-core/src/language/Ruby/RubyRenderer.ts new file mode 100644 index 000000000..af5af4b6f --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/RubyRenderer.ts @@ -0,0 +1,921 @@ +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, modifySource } from "../../Source"; +import { snakeCase } from "../../support/Strings"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + type EnumType, + MapType, + type Type, + type UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { globals } from "./constants"; +import type { rubyOptions } from "./language"; +import { + Strictness, + forbiddenForObjectProperties, + memberNameStyle, + simpleNameStyle, + stringEscape, +} from "./utils"; + +export class RubyRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected get commentLineStart(): string { + return "# "; + } + + protected get needsTypeDeclarationBeforeUse(): boolean { + return true; + } + + protected canBeForwardDeclared(t: Type): boolean { + return "class" === t.kind; + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return [ + ...globals, + "Types", + "JSON", + "Dry", + "Constructor", + "Self", + ] as const; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { + names: forbiddenForObjectProperties, + includeGlobalForbidden: true, + }; + } + + protected makeNamedTypeNamer(): Namer { + return new Namer("types", (n) => simpleNameStyle(n, true), []); + } + + protected namerForObjectProperty(): Namer { + return new Namer("properties", memberNameStyle, []); + } + + protected makeUnionMemberNamer(): Namer { + return new Namer("properties", memberNameStyle, []); + } + + protected makeEnumCaseNamer(): Namer { + return new Namer("enum-cases", (n) => simpleNameStyle(n, true), []); + } + + private dryType(t: Type, isOptional = false): Sourcelike { + const optional = isOptional ? ".optional" : ""; + return matchType( + t, + (_anyType) => ["Types::Any", optional], + (_nullType) => ["Types::Nil", optional], + (_boolType) => ["Types::Bool", optional], + (_integerType) => ["Types::Integer", optional], + (_doubleType) => ["Types::Double", optional], + (_stringType) => ["Types::String", optional], + (arrayType) => [ + "Types.Array(", + this.dryType(arrayType.items), + ")", + optional, + ], + (classType) => [this.nameForNamedType(classType), optional], + (mapType) => [ + "Types::Hash.meta(of: ", + this.dryType(mapType.values), + ")", + optional, + ], + (enumType) => [ + "Types::", + this.nameForNamedType(enumType), + optional, + ], + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return [this.dryType(nullable), ".optional"]; + } + + return [ + "Types.Instance(", + this.nameForNamedType(unionType), + ")", + optional, + ]; + }, + ); + } + + private exampleUse( + t: Type, + exp: Sourcelike, + depth = 6, + optional = false, + ): Sourcelike { + if (depth-- <= 0) { + return exp; + } + + const safeNav = optional ? "&" : ""; + + return matchType( + t, + (_anyType) => exp, + (_nullType) => [exp, ".nil?"], + (_boolType) => exp, + (_integerType) => [exp, ".even?"], + (_doubleType) => exp, + (_stringType) => exp, + (arrayType) => + this.exampleUse( + arrayType.items, + [exp, safeNav, ".first"], + depth, + ), + (classType) => { + let info: { name: Name; prop: ClassProperty } | undefined; + this.forEachClassProperty( + classType, + "none", + (name, _json, prop) => { + if ( + ["class", "map", "array"].includes(prop.type.kind) + ) { + info = { name, prop }; + } else if (info === undefined) { + info = { name, prop }; + } + }, + ); + if (info !== undefined) { + return this.exampleUse( + info.prop.type, + [exp, safeNav, ".", info.name], + depth, + info.prop.isOptional, + ); + } + + return exp; + }, + (mapType) => + this.exampleUse(mapType.values, [exp, safeNav, '["…"]'], depth), + (enumType) => { + let name: Name | undefined; + // FIXME: This is a terrible way to get the first enum case name. + this.forEachEnumCase(enumType, "none", (theName) => { + if (name === undefined) { + name = theName; + } + }); + if (name !== undefined) { + return [ + exp, + " == ", + this.nameForNamedType(enumType), + "::", + name, + ]; + } + + return exp; + }, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (["class", "map", "array"].includes(nullable.kind)) { + return this.exampleUse(nullable, exp, depth, true); + } + + return [exp, ".nil?"]; + } + + return exp; + }, + ); + } + + private jsonSample(t: Type): Sourcelike { + function inner(): string { + if (t instanceof ArrayType) { + return "[…]"; + } + if (t instanceof MapType) { + return "{…}"; + } + if (t instanceof ClassType) { + return "{…}"; + } + + return "…"; + } + + return `"${inner()}"`; + } + + private fromDynamic( + t: Type, + e: Sourcelike, + optional = false, + castPrimitives = false, + ): Sourcelike { + const primitiveCast = [this.dryType(t, optional), "[", e, "]"]; + const primitive = castPrimitives ? primitiveCast : e; + const safeAccess = optional ? "&" : ""; + return matchType( + t, + (_anyType) => primitive, + (_nullType) => primitive, + (_boolType) => primitive, + (_integerType) => primitive, + (_doubleType) => primitive, + (_stringType) => primitive, + (arrayType) => [ + e, + safeAccess, + ".map { |x| ", + this.fromDynamic(arrayType.items, "x", false, true), + " }", + ], + (classType) => { + const expression = [ + this.nameForNamedType(classType), + ".from_dynamic!(", + e, + ")", + ]; + return optional ? [e, " ? ", expression, " : nil"] : expression; + }, + (mapType) => [ + ["Types::Hash", optional ? ".optional" : "", "[", e, "]"], + safeAccess, + ".map { |k, v| [k, ", + this.fromDynamic(mapType.values, "v", false, true), + "] }", + safeAccess, + ".to_h", + ], + (enumType) => { + const expression = [ + "Types::", + this.nameForNamedType(enumType), + "[", + e, + "]", + ]; + return optional + ? [e, ".nil? ? nil : ", expression] + : expression; + }, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return this.fromDynamic(nullable, e, true); + } + + const expression = [ + this.nameForNamedType(unionType), + ".from_dynamic!(", + e, + ")", + ]; + return optional ? [e, " ? ", expression, " : nil"] : expression; + }, + ); + } + + private toDynamic(t: Type, e: Sourcelike, optional = false): Sourcelike { + if (this.marshalsImplicitlyToDynamic(t)) { + return e; + } + + return matchType( + t, + (_anyType) => e, + (_nullType) => e, + (_boolType) => e, + (_integerType) => e, + (_doubleType) => e, + (_stringType) => e, + (arrayType) => [ + e, + optional ? "&" : "", + ".map { |x| ", + this.toDynamic(arrayType.items, "x"), + " }", + ], + (_classType) => [e, optional ? "&" : "", ".to_dynamic"], + (mapType) => [ + e, + optional ? "&" : "", + ".map { |k, v| [k, ", + this.toDynamic(mapType.values, "v"), + "] }.to_h", + ], + (_enumType) => e, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return this.toDynamic(nullable, e, true); + } + + if (this.marshalsImplicitlyToDynamic(unionType)) { + return e; + } + + return [e, optional ? "&" : "", ".to_dynamic"]; + }, + ); + } + + private marshalsImplicitlyToDynamic(t: Type): boolean { + return matchType( + t, + (_anyType) => true, + (_nullType) => true, + (_boolType) => true, + (_integerType) => true, + (_doubleType) => true, + (_stringType) => true, + (arrayType) => this.marshalsImplicitlyToDynamic(arrayType.items), + (_classType) => false, + (mapType) => this.marshalsImplicitlyToDynamic(mapType.values), + (_enumType) => true, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return this.marshalsImplicitlyToDynamic(nullable); + } + + return false; + }, + ); + } + + // This is only to be used to allow class properties to possibly + // marshal implicitly. They are allowed to do this because they will + // be checked in Dry::Struct.new + private propertyTypeMarshalsImplicitlyFromDynamic(t: Type): boolean { + return matchType( + t, + (_anyType) => true, + (_nullType) => true, + (_boolType) => true, + (_integerType) => true, + (_doubleType) => true, + (_stringType) => true, + (arrayType) => + this.propertyTypeMarshalsImplicitlyFromDynamic(arrayType.items), + (_classType) => false, + // Map properties must be checked because Dry:Types doesn't have a generic Map + (_mapType) => false, + (_enumType) => true, + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return this.propertyTypeMarshalsImplicitlyFromDynamic( + nullable, + ); + } + + return false; + }, + ); + } + + private emitBlock(source: Sourcelike, emit: () => void): void { + this.emitLine(source); + this.indent(emit); + this.emitLine("end"); + } + + private emitModule(emit: () => void): void { + const emitModuleInner = (moduleName: string): void => { + const [firstModule, ...subModules] = moduleName.split("::"); + if (subModules.length > 0) { + this.emitBlock(["module ", firstModule], () => { + emitModuleInner(subModules.join("::")); + }); + } else { + this.emitBlock(["module ", moduleName], emit); + } + }; + + if ( + this._options.namespace !== undefined && + this._options.namespace !== "" + ) { + emitModuleInner(this._options.namespace); + } else { + emit(); + } + } + + private emitClass(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitBlock(["class ", className, " < Dry::Struct"], () => { + let table: Sourcelike[][] = []; + let count = c.getProperties().size; + this.forEachClassProperty(c, "none", (name, jsonName, p) => { + const last = --count === 0; + const description = this.descriptionForClassProperty( + c, + jsonName, + ); + const attribute = [ + ["attribute :", name, ","], + [ + " ", + this.dryType(p.type), + p.isOptional ? ".optional" : "", + ], + ]; + if (description !== undefined) { + if (table.length > 0) { + this.emitTable(table); + table = []; + } + + this.ensureBlankLine(); + this.emitDescriptionBlock(description); + this.emitLine(attribute); + if (!last) { + this.ensureBlankLine(); + } + } else { + table.push(attribute); + } + }); + if (table.length > 0) { + this.emitTable(table); + } + + if (this._options.justTypes) { + return; + } + + this.ensureBlankLine(); + this.emitBlock(["def self.from_dynamic!(d)"], () => { + this.emitLine("d = Types::Hash[d]"); + this.emitLine("new("); + this.indent(() => { + const inits: Sourcelike[][] = []; + this.forEachClassProperty( + c, + "none", + (name, jsonName, p) => { + const dynamic = p.isOptional + ? // If key is not found in hash, this will be nil + `d["${stringEscape(jsonName)}"]` + : // This will raise a runtime error if the key is not found in the hash + `d.fetch("${stringEscape(jsonName)}")`; + + if ( + this.propertyTypeMarshalsImplicitlyFromDynamic( + p.type, + ) + ) { + inits.push([ + [name, ": "], + [dynamic, ","], + ]); + } else { + const expression = this.fromDynamic( + p.type, + dynamic, + p.isOptional, + ); + inits.push([ + [name, ": "], + [expression, ","], + ]); + } + }, + ); + this.emitTable(inits); + }); + this.emitLine(")"); + }); + + this.ensureBlankLine(); + this.emitBlock("def self.from_json!(json)", () => { + this.emitLine("from_dynamic!(JSON.parse(json))"); + }); + + this.ensureBlankLine(); + this.emitBlock(["def to_dynamic"], () => { + this.emitLine("{"); + this.indent(() => { + const inits: Sourcelike[][] = []; + this.forEachClassProperty( + c, + "none", + (name, jsonName, p) => { + const expression = this.toDynamic( + p.type, + name, + p.isOptional, + ); + inits.push([ + [`"${stringEscape(jsonName)}"`], + [" => ", expression, ","], + ]); + }, + ); + this.emitTable(inits); + }); + this.emitLine("}"); + }); + this.ensureBlankLine(); + this.emitBlock("def to_json(options = nil)", () => { + this.emitLine("JSON.generate(to_dynamic, options)"); + }); + }); + } + + private emitEnum(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + this.emitBlock(["module ", enumName], () => { + const table: Sourcelike[][] = []; + this.forEachEnumCase(e, "none", (name, json) => { + table.push([[name], [` = "${stringEscape(json)}"`]]); + }); + this.emitTable(table); + }); + } + + private emitUnion(u: UnionType, unionName: Name): void { + this.emitDescription(this.descriptionForType(u)); + this.emitBlock(["class ", unionName, " < Dry::Struct"], () => { + const table: Sourcelike[][] = []; + this.forEachUnionMember( + u, + u.getChildren(), + "none", + null, + (name, t) => { + table.push([ + ["attribute :", name, ", "], + [this.dryType(t, true)], + ]); + }, + ); + this.emitTable(table); + + if (this._options.justTypes) { + return; + } + + this.ensureBlankLine(); + const [maybeNull, nonNulls] = removeNullFromUnion(u, false); + this.emitBlock("def self.from_dynamic!(d)", () => { + const memberNames = Array.from(u.getChildren()).map((member) => + this.nameForUnionMember(u, member), + ); + this.forEachUnionMember( + u, + u.getChildren(), + "none", + null, + (name, t) => { + const nilMembers = memberNames + .filter((n) => n !== name) + .map((memberName) => [", ", memberName, ": nil"]); + if (this.propertyTypeMarshalsImplicitlyFromDynamic(t)) { + this.emitBlock( + ["if schema[:", name, "].right.valid? d"], + () => { + this.emitLine( + "return new(", + name, + ": d", + nilMembers, + ")", + ); + }, + ); + } else { + this.emitLine("begin"); + this.indent(() => { + this.emitLine( + "value = ", + this.fromDynamic(t, "d"), + ); + this.emitBlock( + [ + "if schema[:", + name, + "].right.valid? value", + ], + () => { + this.emitLine( + "return new(", + name, + ": value", + nilMembers, + ")", + ); + }, + ); + }); + this.emitLine("rescue"); + this.emitLine("end"); + } + }, + ); + this.emitLine('raise "Invalid union"'); + }); + + this.ensureBlankLine(); + this.emitBlock("def self.from_json!(json)", () => { + this.emitLine("from_dynamic!(JSON.parse(json))"); + }); + + this.ensureBlankLine(); + this.emitBlock("def to_dynamic", () => { + let first = true; + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (name, t) => { + this.emitLine( + first ? "if" : "elsif", + " ", + name, + " != nil", + ); + this.indent(() => { + this.emitLine(this.toDynamic(t, name)); + }); + first = false; + }, + ); + if (maybeNull !== null) { + this.emitLine("else"); + this.indent(() => { + this.emitLine("nil"); + }); + } + + this.emitLine("end"); + }); + + this.ensureBlankLine(); + this.emitBlock("def to_json(options = nil)", () => { + this.emitLine("JSON.generate(to_dynamic, options)"); + }); + }); + } + + private emitTypesModule(): void { + this.emitBlock(["module Types"], () => { + this.emitLine("include Dry.Types(default: :nominal)"); + + const declarations: Sourcelike[][] = []; + + if (this._options.strictness !== Strictness.None) { + let has = { + int: false, + nil: false, + bool: false, + hash: false, + string: false, + double: false, + }; + this.forEachType((t) => { + has = { + int: has.int || t.kind === "integer", + nil: has.nil || t.kind === "null", + bool: has.bool || t.kind === "bool", + hash: + has.hash || t.kind === "map" || t.kind === "class", + string: + has.string || + t.kind === "string" || + t.kind === "enum", + double: has.double || t.kind === "double", + }; + }); + if (has.int) + declarations.push([ + ["Integer"], + [` = ${this._options.strictness}Integer`], + ]); + if (this._options.strictness === Strictness.Strict) { + if (has.nil) + declarations.push([ + ["Nil"], + [` = ${this._options.strictness}Nil`], + ]); + } + + if (has.bool) + declarations.push([ + ["Bool"], + [` = ${this._options.strictness}Bool`], + ]); + if (has.hash) + declarations.push([ + ["Hash"], + [` = ${this._options.strictness}Hash`], + ]); + if (has.string) + declarations.push([ + ["String"], + [` = ${this._options.strictness}String`], + ]); + if (has.double) + declarations.push([ + ["Double"], + [ + ` = ${this._options.strictness}Float | ${this._options.strictness}Integer`, + ], + ]); + } + + this.forEachEnum("none", (enumType, enumName) => { + const cases: Sourcelike[][] = []; + this.forEachEnumCase(enumType, "none", (_name, json) => { + cases.push([ + cases.length === 0 ? "" : ", ", + `"${stringEscape(json)}"`, + ]); + }); + declarations.push([ + [enumName], + [ + " = ", + this._options.strictness, + "String.enum(", + ...cases, + ")", + ], + ]); + }); + + if (declarations.length > 0) { + this.ensureBlankLine(); + this.emitTable(declarations); + } + }); + } + + protected emitSourceStructure(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else if (!this._options.justTypes) { + this.emitLine( + "# This code may look unusually verbose for Ruby (and it is), but", + ); + this.emitLine( + "# it performs some subtle and complex validation of JSON data.", + ); + this.emitLine("#"); + this.emitLine( + "# To parse this JSON, add 'dry-struct' and 'dry-types' gems, then do:", + ); + this.emitLine("#"); + this.forEachTopLevel("none", (topLevel, name) => { + const variable = modifySource(snakeCase, name); + this.emitLine( + "# ", + variable, + " = ", + name, + ".from_json! ", + this.jsonSample(topLevel), + ); + this.emitLine("# puts ", this.exampleUse(topLevel, variable)); + this.emitLine("#"); + }); + this.emitLine( + "# If from_json! succeeds, the value returned matches the schema.", + ); + } + + this.ensureBlankLine(); + + this.emitLine("require 'json'"); + this.emitLine("require 'dry-types'"); + this.emitLine("require 'dry-struct'"); + + this.ensureBlankLine(); + + this.emitModule(() => { + this.emitTypesModule(); + + this.forEachDeclaration("leading-and-interposing", (decl) => { + if (decl.kind === "forward") { + this.emitCommentLines(["(forward declaration)"]); + this.emitModule(() => { + this.emitLine( + "class ", + this.nameForNamedType(decl.type), + " < Dry::Struct; end", + ); + }); + } + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClass(c, n), + (e, n) => this.emitEnum(e, n), + (u, n) => this.emitUnion(u, n), + ); + + if (!this._options.justTypes) { + this.forEachTopLevel( + "leading-and-interposing", + (topLevel, name) => { + const self = modifySource(snakeCase, name); + + // The json gem defines to_json on maps and primitives, so we only need to supply + // it for arrays. + const needsToJsonDefined = "array" === topLevel.kind; + + const classDeclaration = (): void => { + this.emitBlock(["class ", name], () => { + this.emitBlock( + ["def self.from_json!(json)"], + () => { + if (needsToJsonDefined) { + this.emitLine( + self, + " = ", + this.fromDynamic( + topLevel, + "JSON.parse(json, quirks_mode: true)", + ), + ); + this.emitBlock( + [ + self, + ".define_singleton_method(:to_json) do", + ], + () => { + this.emitLine( + "JSON.generate(", + this.toDynamic( + topLevel, + "self", + ), + ")", + ); + }, + ); + this.emitLine(self); + } else { + this.emitLine( + this.fromDynamic( + topLevel, + "JSON.parse(json, quirks_mode: true)", + ), + ); + } + }, + ); + }); + }; + + this.emitModule(() => { + classDeclaration(); + }); + }, + (t) => this.namedTypeToNameForTopLevel(t) === undefined, + ); + } + }); + } +} diff --git a/packages/quicktype-core/src/language/ruby/keywords.ts b/packages/quicktype-core/src/language/Ruby/constants.ts similarity index 97% rename from packages/quicktype-core/src/language/ruby/keywords.ts rename to packages/quicktype-core/src/language/Ruby/constants.ts index e01c14b5f..ae9f5bf7b 100644 --- a/packages/quicktype-core/src/language/ruby/keywords.ts +++ b/packages/quicktype-core/src/language/Ruby/constants.ts @@ -39,8 +39,8 @@ export const keywords = [ "until", "when", "while", - "yield" -]; + "yield", +] as const; const globalClasses = [ "ArgumentError", @@ -133,8 +133,8 @@ const globalClasses = [ "Undefined", "UnicodeNormalize", "Warning", - "ZeroDivisionError" -]; + "ZeroDivisionError", +] as const; const kernel = [ "__callee__", @@ -286,10 +286,10 @@ const kernel = [ "untrace_var", "untrust", "untrusted?", - "warn" -]; + "warn", +] as const; -export const globals = kernel.concat(globalClasses); +export const globals = [...kernel, ...globalClasses] as const; export const reservedProperties = [ "__id__", @@ -355,5 +355,5 @@ export const reservedProperties = [ "undef", "untrust", "while", - "with" -]; + "with", +] as const; diff --git a/packages/quicktype-core/src/language/Ruby/index.ts b/packages/quicktype-core/src/language/Ruby/index.ts new file mode 100644 index 000000000..13ba45f36 --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/index.ts @@ -0,0 +1,2 @@ +export { RubyTargetLanguage, rubyOptions } from "./language"; +export { RubyRenderer } from "./RubyRenderer"; diff --git a/packages/quicktype-core/src/language/Ruby/language.ts b/packages/quicktype-core/src/language/Ruby/language.ts new file mode 100644 index 000000000..e7b021305 --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/language.ts @@ -0,0 +1,70 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { RubyRenderer } from "./RubyRenderer"; +import { Strictness } from "./utils"; + +export const rubyOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + strictness: new EnumOption( + "strictness", + "Type strictness", + { + strict: Strictness.Strict, + coercible: Strictness.Coercible, + none: Strictness.None, + } as const, + "strict", + ), + namespace: new StringOption( + "namespace", + "Specify a wrapping Namespace", + "NAME", + "", + "secondary", + ), +}; + +export const rubyLanguageConfig = { + displayName: "Ruby", + names: ["ruby"], + extension: "rb", +} as const; + +export class RubyTargetLanguage extends TargetLanguage< + typeof rubyLanguageConfig +> { + public constructor() { + super(rubyLanguageConfig); + } + + public getOptions(): typeof rubyOptions { + return rubyOptions; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected get defaultIndentation(): string { + return " "; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): RubyRenderer { + return new RubyRenderer( + this, + renderContext, + getOptionValues(rubyOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/Ruby/utils.ts b/packages/quicktype-core/src/language/Ruby/utils.ts new file mode 100644 index 000000000..61c12f8c2 --- /dev/null +++ b/packages/quicktype-core/src/language/Ruby/utils.ts @@ -0,0 +1,78 @@ +import unicode from "unicode-properties"; + +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isLetterOrUnderscore, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap, +} from "../../support/Strings"; + +import * as keywords from "./constants"; + +export enum Strictness { + Strict = "Strict::", + Coercible = "Coercible::", + None = "Types::", +} + +export const forbiddenForObjectProperties = Array.from( + new Set([...keywords.keywords, ...keywords.reservedProperties]), +); +function unicodeEscape(codePoint: number): string { + return "\\u{" + intToHex(codePoint, 0) + "}"; +} + +export const stringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, unicodeEscape), +); + +const isStartCharacter = isLetterOrUnderscore; + +function isPartCharacter(utf16Unit: number): boolean { + const category: string = unicode.getCategory(utf16Unit); + return ( + ["Nd", "Pc", "Mn", "Mc"].includes(category) || + isStartCharacter(utf16Unit) + ); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function simpleNameStyle(original: string, uppercase: boolean): string { + if (/^[0-9]+$/.test(original)) { + original = original + "N"; + } + + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + uppercase ? firstUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + allUpperWordStyle, + "", + isStartCharacter, + ); +} + +export function memberNameStyle(original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + allLowerWordStyle, + "_", + isStartCharacter, + ); +} diff --git a/packages/quicktype-core/src/language/Rust.ts b/packages/quicktype-core/src/language/Rust.ts deleted file mode 100644 index 93b0a1b33..000000000 --- a/packages/quicktype-core/src/language/Rust.ts +++ /dev/null @@ -1,560 +0,0 @@ -import { mapFirst } from "collection-utils"; - -import { TargetLanguage } from "../TargetLanguage"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { - legalizeCharacters, - splitIntoWords, - isLetterOrUnderscoreOrDigit, - combineWords, - allLowerWordStyle, - firstUpperWordStyle, - intToHex, - utf32ConcatMap, - escapeNonPrintableMapper, - isPrintable, - isAscii, - isLetterOrUnderscore -} from "../support/Strings"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { UnionType, Type, ClassType, EnumType } from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Sourcelike, maybeAnnotated } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { BooleanOption, EnumOption, Option, getOptionValues, OptionValues } from "../RendererOptions"; -import { defined } from "../support/Support"; -import { RenderContext } from "../Renderer"; - -export enum Density { - Normal, - Dense -} - -export enum Visibility { - Private, - Crate, - Public -} - -export const rustOptions = { - density: new EnumOption("density", "Density", [ - ["normal", Density.Normal], - ["dense", Density.Dense] - ]), - visibility: new EnumOption("visibility", "Field visibility", [ - ["private", Visibility.Private], - ["crate", Visibility.Crate], - ["public", Visibility.Public] - ]), - deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), - deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), - derivePartialEq: new BooleanOption("derive-partial-eq", "Derive PartialEq impl", false), - edition2018: new BooleanOption("edition-2018", "Edition 2018", true), - leadingComments: new BooleanOption("leading-comments", "Leading Comments", true) -}; - -type NameToParts = (name: string) => string[]; -type PartsToName = (parts: string[]) => string; -type NamingStyle = { - regex: RegExp; - toParts: NameToParts; - fromParts: PartsToName; -}; - -const namingStyles: Record = { - snake_case: { - regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/, - toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("_") - }, - SCREAMING_SNAKE_CASE: { - regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/, - toParts: (name: string): string[] => name.split("_"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("_") - }, - camelCase: { - regex: /^[a-z]+([A-Z0-9][a-z]*)*$/, - toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), - fromParts: (parts: string[]): string => - parts - .map((p, i) => - i === 0 ? p.toLowerCase() : p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase() - ) - .join("") - }, - PascalCase: { - regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/, - toParts: (name: string): string[] => namingStyles.snake_case.toParts(name.replace(/(.)([A-Z])/g, "$1_$2")), - fromParts: (parts: string[]): string => - parts.map(p => p.substring(0, 1).toUpperCase() + p.substring(1).toLowerCase()).join("") - }, - "kebab-case": { - regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, - toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("-") - }, - "SCREAMING-KEBAB-CASE": { - regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/, - toParts: (name: string): string[] => name.split("-"), - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("-") - }, - lowercase: { - regex: /^[a-z][a-z0-9]*$/, - toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toLowerCase()).join("") - }, - UPPERCASE: { - regex: /^[A-Z][A-Z0-9]*$/, - toParts: (name: string): string[] => [name], - fromParts: (parts: string[]): string => parts.map(p => p.toUpperCase()).join("") - } -}; - -export class RustTargetLanguage extends TargetLanguage { - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RustRenderer { - return new RustRenderer(this, renderContext, getOptionValues(rustOptions, untypedOptionValues)); - } - - constructor() { - super("Rust", ["rust", "rs", "rustlang"], "rs"); - } - - protected getOptions(): Option[] { - return [ - rustOptions.density, - rustOptions.visibility, - rustOptions.deriveDebug, - rustOptions.deriveClone, - rustOptions.derivePartialEq, - rustOptions.edition2018, - rustOptions.leadingComments - ]; - } -} - -const keywords = [ - "Serialize", - "Deserialize", - - // Special reserved identifiers used internally for elided lifetimes, - // unnamed method parameters, crate root module, error recovery etc. - "{{root}}", - "$crate", - - // Keywords used in the language. - "as", - "async", - "box", - "break", - "const", - "continue", - "crate", - "else", - "enum", - "extern", - "false", - "fn", - "for", - "if", - "impl", - "in", - "let", - "loop", - "match", - "mod", - "move", - "mut", - "pub", - "ref", - "return", - "self", - "Self", - "static", - "struct", - "super", - "trait", - "true", - "type", - "unsafe", - "use", - "where", - "while", - - // Keywords reserved for future use. - "abstract", - "alignof", - "become", - "do", - "final", - "macro", - "offsetof", - "override", - "priv", - "proc", - "pure", - "sizeof", - "typeof", - "unsized", - "virtual", - "yield", - - // Weak keywords, have special meaning only in specific contexts. - "catch", - "default", - "dyn", - "'static", - "union" -]; - -const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => { - if (!isAscii(codePoint)) { - return false; - } - - return isLetterOrUnderscoreOrDigit(codePoint); -}; - -const isAsciiLetterOrUnderscore = (codePoint: number): boolean => { - if (!isAscii(codePoint)) { - return false; - } - - return isLetterOrUnderscore(codePoint); -}; - -const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); - -function rustStyle(original: string, isSnakeCase: boolean): string { - const words = splitIntoWords(original); - - const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; - - const combined = combineWords( - words, - legalizeName, - wordStyle, - wordStyle, - wordStyle, - wordStyle, - isSnakeCase ? "_" : "", - isAsciiLetterOrUnderscore - ); - - return combined === "_" ? "_underscore" : combined; -} - -const snakeNamingFunction = funPrefixNamer("default", (original: string) => rustStyle(original, true)); -const camelNamingFunction = funPrefixNamer("camel", (original: string) => rustStyle(original, false)); - -const standardUnicodeRustEscape = (codePoint: number): string => { - if (codePoint <= 0xffff) { - return "\\u{" + intToHex(codePoint, 4) + "}"; - } else { - return "\\u{" + intToHex(codePoint, 6) + "}"; - } -}; - -const rustStringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape)); - -export class RustRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected makeNamedTypeNamer(): Namer { - return camelNamingFunction; - } - - protected namerForObjectProperty(): Namer | null { - return snakeNamingFunction; - } - - protected makeUnionMemberNamer(): Namer | null { - return camelNamingFunction; - } - - protected makeEnumCaseNamer(): Namer | null { - return camelNamingFunction; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_c: ClassType, _className: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected get commentLineStart(): string { - return "/// "; - } - - private nullableRustType(t: Type, withIssues: boolean): Sourcelike { - return ["Option<", this.breakCycle(t, withIssues), ">"]; - } - - protected isImplicitCycleBreaker(t: Type): boolean { - const kind = t.kind; - return kind === "array" || kind === "map"; - } - - private rustType(t: Type, withIssues = false): Sourcelike { - return matchType( - t, - _anyType => maybeAnnotated(withIssues, anyTypeIssueAnnotation, "Option"), - _nullType => maybeAnnotated(withIssues, nullTypeIssueAnnotation, "Option"), - _boolType => "bool", - _integerType => "i64", - _doubleType => "f64", - _stringType => "String", - arrayType => ["Vec<", this.rustType(arrayType.items, withIssues), ">"], - classType => this.nameForNamedType(classType), - mapType => ["HashMap"], - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - - if (nullable !== null) return this.nullableRustType(nullable, withIssues); - - const [hasNull] = removeNullFromUnion(unionType); - - const isCycleBreaker = this.isCycleBreakerType(unionType); - - const name = isCycleBreaker - ? ["Box<", this.nameForNamedType(unionType), ">"] - : this.nameForNamedType(unionType); - - return hasNull !== null ? (["Option<", name, ">"] as Sourcelike) : name; - } - ); - } - - private breakCycle(t: Type, withIssues: boolean): any { - const rustType = this.rustType(t, withIssues); - const isCycleBreaker = this.isCycleBreakerType(t); - - return isCycleBreaker ? ["Box<", rustType, ">"] : rustType; - } - - private emitRenameAttribute( - propName: Name, - jsonName: string, - defaultNamingStyle: string, - preferedNamingStyle: string - ) { - const escapedName = rustStringEscape(jsonName); - const name = namingStyles[defaultNamingStyle].fromParts(this.sourcelikeToString(propName).split(" ")); - const styledName = nameToNamingStyle(name, preferedNamingStyle); - const namesDiffer = escapedName !== styledName; - if (namesDiffer) { - this.emitLine('#[serde(rename = "', escapedName, '")]'); - } - } - - private get visibility(): string { - if (this._options.visibility === Visibility.Crate) { - return "pub(crate) "; - } else if (this._options.visibility === Visibility.Public) { - return "pub "; - } - return ""; - } - - protected emitStructDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitLine( - "#[derive(", - this._options.deriveDebug ? "Debug, " : "", - this._options.deriveClone ? "Clone, " : "", - this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]" - ); - - // List the possible naming styles for every class property - const propertiesNamingStyles: { [key: string]: string[] } = {}; - this.forEachClassProperty(c, "none", (_name, jsonName, _prop) => { - propertiesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName); - }); - - // Set the default naming style on the struct - const defaultStyle = "snake_case"; - const preferedNamingStyle = getPreferedNamingStyle(Object.values(propertiesNamingStyles).flat(), defaultStyle); - if (preferedNamingStyle !== defaultStyle) { - this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`); - } - - const blankLines = this._options.density === Density.Dense ? "none" : "interposing"; - const structBody = () => - this.forEachClassProperty(c, blankLines, (name, jsonName, prop) => { - this.emitDescription(this.descriptionForClassProperty(c, jsonName)); - this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle); - this.emitLine(this.visibility, name, ": ", this.breakCycle(prop.type, true), ","); - }); - - this.emitBlock(["pub struct ", className], structBody); - } - - protected emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line, " {"); - this.indent(f); - this.emitLine("}"); - } - - protected emitUnion(u: UnionType, unionName: Name): void { - const isMaybeWithSingleType = nullableFromUnion(u); - - if (isMaybeWithSingleType !== null) { - return; - } - - this.emitDescription(this.descriptionForType(u)); - this.emitLine( - "#[derive(", - this._options.deriveDebug ? "Debug, " : "", - this._options.deriveClone ? "Clone, " : "", - this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]" - ); - this.emitLine("#[serde(untagged)]"); - - const [, nonNulls] = removeNullFromUnion(u); - - const blankLines = this._options.density === Density.Dense ? "none" : "interposing"; - this.emitBlock(["pub enum ", unionName], () => - this.forEachUnionMember(u, nonNulls, blankLines, null, (fieldName, t) => { - const rustType = this.breakCycle(t, true); - this.emitLine([fieldName, "(", rustType, "),"]); - }) - ); - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - this.emitLine( - "#[derive(", - this._options.deriveDebug ? "Debug, " : "", - this._options.deriveClone ? "Clone, " : "", - this._options.derivePartialEq ? "PartialEq, " : "", - "Serialize, Deserialize)]" - ); - - // List the possible naming styles for every enum case - const enumCasesNamingStyles: { [key: string]: string[] } = {}; - this.forEachEnumCase(e, "none", (_name, jsonName) => { - enumCasesNamingStyles[jsonName] = listMatchingNamingStyles(jsonName); - }); - - // Set the default naming style on the enum - const defaultStyle = "PascalCase"; - const preferedNamingStyle = getPreferedNamingStyle(Object.values(enumCasesNamingStyles).flat(), defaultStyle); - if (preferedNamingStyle !== defaultStyle) { - this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`); - } - - const blankLines = this._options.density === Density.Dense ? "none" : "interposing"; - this.emitBlock(["pub enum ", enumName], () => - this.forEachEnumCase(e, blankLines, (name, jsonName) => { - this.emitRenameAttribute(name, jsonName, defaultStyle, preferedNamingStyle); - this.emitLine([name, ","]); - }) - ); - } - - protected emitTopLevelAlias(t: Type, name: Name): void { - this.emitLine("pub type ", name, " = ", this.rustType(t), ";"); - } - - protected emitLeadingComments(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - return; - } - - const topLevelName = defined(mapFirst(this.topLevels)).getCombinedName(); - this.emitMultiline( - `// Example code that deserializes and serializes the model. -// extern crate serde; -// #[macro_use] -// extern crate serde_derive; -// extern crate serde_json; -// -// use generated_module::${topLevelName}; -// -// fn main() { -// let json = r#"{"answer": 42}"#; -// let model: ${topLevelName} = serde_json::from_str(&json).unwrap(); -// }` - ); - } - - protected emitSourceStructure(): void { - if (this._options.leadingComments) { - this.emitLeadingComments(); - } - this.ensureBlankLine(); - if (this._options.edition2018) { - this.emitLine("use serde::{Serialize, Deserialize};"); - } else { - this.emitLine("extern crate serde_derive;"); - } - - if (this.haveMaps) { - this.emitLine("use std::collections::HashMap;"); - } - - this.forEachTopLevel( - "leading", - (t, name) => this.emitTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined - ); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, name: Name) => this.emitStructDefinition(c, name), - (e, name) => this.emitEnumDefinition(e, name), - (u, name) => this.emitUnion(u, name) - ); - } -} - -function getPreferedNamingStyle(namingStyleOccurences: string[], defaultStyle: string): string { - const occurrences = Object.fromEntries(Object.keys(namingStyles).map(key => [key, 0])); - namingStyleOccurences.forEach(style => ++occurrences[style]); - const max = Math.max(...Object.values(occurrences)); - const preferedStyles = Object.entries(occurrences) - .filter(([_style, num]) => num === max) - .map(([style, _num]) => style); - if (preferedStyles.includes(defaultStyle)) { - return defaultStyle; - } - return preferedStyles[0]; -} - -function listMatchingNamingStyles(name: string): string[] { - return Object.entries(namingStyles) - .filter(([_, { regex }]) => regex.test(name)) - .map(([namingStyle, _]) => namingStyle); -} - -function nameToNamingStyle(name: string, style: string): string { - if (namingStyles[style].regex.test(name)) { - return name; - } - const fromStyle = listMatchingNamingStyles(name)[0]; - if (fromStyle === undefined) { - return name; - } - return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name)); -} diff --git a/packages/quicktype-core/src/language/Rust/RustRenderer.ts b/packages/quicktype-core/src/language/Rust/RustRenderer.ts new file mode 100644 index 000000000..22e81babc --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/RustRenderer.ts @@ -0,0 +1,402 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { mapFirst } from "collection-utils"; + +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import type { Name, Namer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import { defined } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + type ClassType, + type EnumType, + type Type, + UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { rustOptions } from "./language"; +import { + Density, + type NamingStyleKey, + Visibility, + camelNamingFunction, + getPreferredNamingStyle, + listMatchingNamingStyles, + nameWithNamingStyle, + namingStyles, + rustStringEscape, + snakeNamingFunction, +} from "./utils"; + +export class RustRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected makeNamedTypeNamer(): Namer { + return camelNamingFunction; + } + + protected namerForObjectProperty(): Namer | null { + return snakeNamingFunction; + } + + protected makeUnionMemberNamer(): Namer | null { + return camelNamingFunction; + } + + protected makeEnumCaseNamer(): Namer | null { + return camelNamingFunction; + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _className: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected get commentLineStart(): string { + return "/// "; + } + + private nullableRustType(t: Type, withIssues: boolean): Sourcelike { + return ["Option<", this.breakCycle(t, withIssues), ">"]; + } + + protected isImplicitCycleBreaker(t: Type): boolean { + const kind = t.kind; + return kind === "array" || kind === "map"; + } + + private rustType(t: Type, withIssues = false): Sourcelike { + return matchType( + t, + (_anyType) => + maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + "Option", + ), + (_nullType) => + maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + "Option", + ), + (_boolType) => "bool", + (_integerType) => "i64", + (_doubleType) => "f64", + (_stringType) => "String", + (arrayType) => [ + "Vec<", + this.rustType(arrayType.items, withIssues), + ">", + ], + (classType) => this.nameForNamedType(classType), + (mapType) => [ + "HashMap", + ], + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + + if (nullable !== null) + return this.nullableRustType(nullable, withIssues); + + const [hasNull] = removeNullFromUnion(unionType); + + const isCycleBreaker = this.isCycleBreakerType(unionType); + + const name = isCycleBreaker + ? ["Box<", this.nameForNamedType(unionType), ">"] + : this.nameForNamedType(unionType); + + return hasNull !== null + ? (["Option<", name, ">"] as Sourcelike) + : name; + }, + ); + } + + private breakCycle(t: Type, withIssues: boolean): Sourcelike { + const rustType = this.rustType(t, withIssues); + const isCycleBreaker = this.isCycleBreakerType(t); + + return isCycleBreaker ? ["Box<", rustType, ">"] : rustType; + } + + private emitRenameAttribute( + propName: Name, + jsonName: string, + defaultNamingStyle: NamingStyleKey, + preferedNamingStyle: NamingStyleKey, + ): void { + const escapedName = rustStringEscape(jsonName); + const name = namingStyles[defaultNamingStyle].fromParts( + this.sourcelikeToString(propName).split(" "), + ); + const styledName = nameWithNamingStyle(name, preferedNamingStyle); + const namesDiffer = escapedName !== styledName; + if (namesDiffer) { + this.emitLine('#[serde(rename = "', escapedName, '")]'); + } + } + + private emitSkipSerializeNone(t: Type): void { + if (t instanceof UnionType) { + const nullable = nullableFromUnion(t); + if (nullable !== null) + this.emitLine( + '#[serde(skip_serializing_if = "Option::is_none")]', + ); + } + } + + private get visibility(): string { + if (this._options.visibility === Visibility.Crate) { + return "pub(crate) "; + } + if (this._options.visibility === Visibility.Public) { + return "pub "; + } + + return ""; + } + + protected emitStructDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitLine( + "#[derive(", + this._options.deriveDebug ? "Debug, " : "", + this._options.deriveClone ? "Clone, " : "", + this._options.derivePartialEq ? "PartialEq, " : "", + "Serialize, Deserialize)]", + ); + + // List the possible naming styles for every class property + const propertiesNamingStyles: { [key: string]: string[] } = {}; + this.forEachClassProperty(c, "none", (_name, jsonName, _prop) => { + propertiesNamingStyles[jsonName] = + listMatchingNamingStyles(jsonName); + }); + + // Set the default naming style on the struct + const defaultStyle = "snake_case"; + const preferedNamingStyle = getPreferredNamingStyle( + Object.values(propertiesNamingStyles).flat(), + defaultStyle, + ); + if (preferedNamingStyle !== defaultStyle) { + this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`); + } + + const blankLines = + this._options.density === Density.Dense ? "none" : "interposing"; + const structBody = (): void => + this.forEachClassProperty(c, blankLines, (name, jsonName, prop) => { + this.emitDescription( + this.descriptionForClassProperty(c, jsonName), + ); + this.emitRenameAttribute( + name, + jsonName, + defaultStyle, + preferedNamingStyle, + ); + if (this._options.skipSerializingNone) { + this.emitSkipSerializeNone(prop.type); + } + + this.emitLine( + this.visibility, + name, + ": ", + this.breakCycle(prop.type, true), + ",", + ); + }); + + this.emitBlock(["pub struct ", className], structBody); + } + + protected emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + protected emitUnion(u: UnionType, unionName: Name): void { + const isMaybeWithSingleType = nullableFromUnion(u); + + if (isMaybeWithSingleType !== null) { + return; + } + + this.emitDescription(this.descriptionForType(u)); + this.emitLine( + "#[derive(", + this._options.deriveDebug ? "Debug, " : "", + this._options.deriveClone ? "Clone, " : "", + this._options.derivePartialEq ? "PartialEq, " : "", + "Serialize, Deserialize)]", + ); + this.emitLine("#[serde(untagged)]"); + + const [, nonNulls] = removeNullFromUnion(u); + + const blankLines = + this._options.density === Density.Dense ? "none" : "interposing"; + this.emitBlock(["pub enum ", unionName], () => + this.forEachUnionMember( + u, + nonNulls, + blankLines, + null, + (fieldName, t) => { + const rustType = this.breakCycle(t, true); + this.emitLine([fieldName, "(", rustType, "),"]); + }, + ), + ); + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + this.emitLine( + "#[derive(", + this._options.deriveDebug ? "Debug, " : "", + this._options.deriveClone ? "Clone, " : "", + this._options.derivePartialEq ? "PartialEq, " : "", + "Serialize, Deserialize)]", + ); + + // List the possible naming styles for every enum case + const enumCasesNamingStyles: { [key: string]: string[] } = {}; + this.forEachEnumCase(e, "none", (_name, jsonName) => { + enumCasesNamingStyles[jsonName] = + listMatchingNamingStyles(jsonName); + }); + + // Set the default naming style on the enum + const defaultStyle = "PascalCase"; + const preferedNamingStyle = getPreferredNamingStyle( + Object.values(enumCasesNamingStyles).flat(), + defaultStyle, + ); + if (preferedNamingStyle !== defaultStyle) { + this.emitLine(`#[serde(rename_all = "${preferedNamingStyle}")]`); + } + + const blankLines = + this._options.density === Density.Dense ? "none" : "interposing"; + this.emitBlock(["pub enum ", enumName], () => + this.forEachEnumCase(e, blankLines, (name, jsonName) => { + this.emitRenameAttribute( + name, + jsonName, + defaultStyle, + preferedNamingStyle, + ); + this.emitLine([name, ","]); + }), + ); + } + + protected emitTopLevelAlias(t: Type, name: Name): void { + this.emitLine("pub type ", name, " = ", this.rustType(t), ";"); + } + + protected emitLeadingComments(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + return; + } + + const topLevelName = defined( + mapFirst(this.topLevels), + ).getCombinedName(); + this.emitMultiline( + `// Example code that deserializes and serializes the model. +// extern crate serde; +// #[macro_use] +// extern crate serde_derive; +// extern crate serde_json; +// +// use generated_module::${topLevelName}; +// +// fn main() { +// let json = r#"{"answer": 42}"#; +// let model: ${topLevelName} = serde_json::from_str(&json).unwrap(); +// }`, + ); + } + + protected emitSourceStructure(): void { + if (this._options.leadingComments) { + this.emitLeadingComments(); + } + + this.ensureBlankLine(); + if (this._options.edition2018) { + this.emitLine("use serde::{Serialize, Deserialize};"); + } else { + this.emitLine("extern crate serde_derive;"); + } + + if (this.haveMaps) { + this.emitLine("use std::collections::HashMap;"); + } + + this.forEachTopLevel( + "leading", + (t, name) => this.emitTopLevelAlias(t, name), + (t) => this.namedTypeToNameForTopLevel(t) === undefined, + ); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, name: Name) => this.emitStructDefinition(c, name), + (e, name) => this.emitEnumDefinition(e, name), + (u, name) => this.emitUnion(u, name), + ); + } +} diff --git a/packages/quicktype-core/src/language/Rust/constants.ts b/packages/quicktype-core/src/language/Rust/constants.ts new file mode 100644 index 000000000..7b56747ff --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/constants.ts @@ -0,0 +1,76 @@ +export const keywords = [ + "Serialize", + "Deserialize", + + // Special reserved identifiers used internally for elided lifetimes, + // unnamed method parameters, crate root module, error recovery etc. + "{{root}}", + "$crate", + + // Keywords used in the language. + "as", + "async", + "box", + "break", + "const", + "continue", + "crate", + "else", + "enum", + "extern", + "false", + "fn", + "for", + "if", + "impl", + "in", + "let", + "loop", + "match", + "mod", + "move", + "mut", + "pub", + "ref", + "return", + "self", + "Self", + "static", + "struct", + "super", + "trait", + "true", + "type", + "unsafe", + "use", + "where", + "while", + + // Keywords reserved for future use. + "abstract", + "alignof", + "become", + "do", + "final", + "macro", + "offsetof", + "override", + "priv", + "proc", + "pure", + "sizeof", + "typeof", + "unsized", + "virtual", + "yield", + + // Weak keywords, have special meaning only in specific contexts. + "catch", + "default", + "dyn", + "'static", + "union", + + // Conflict between `std::Option` and potentially generated Option + "option", +] as const; diff --git a/packages/quicktype-core/src/language/Rust/index.ts b/packages/quicktype-core/src/language/Rust/index.ts new file mode 100644 index 000000000..456ae1274 --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/index.ts @@ -0,0 +1,2 @@ +export { RustTargetLanguage, rustOptions } from "./language"; +export { RustRenderer } from "./RustRenderer"; diff --git a/packages/quicktype-core/src/language/Rust/language.ts b/packages/quicktype-core/src/language/Rust/language.ts new file mode 100644 index 000000000..4981d6a6f --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/language.ts @@ -0,0 +1,80 @@ +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + getOptionValues, +} from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { RustRenderer } from "./RustRenderer"; +import { Density, Visibility } from "./utils"; + +export const rustOptions = { + density: new EnumOption( + "density", + "Density", + { + normal: Density.Normal, + dense: Density.Dense, + } as const, + "normal", + ), + visibility: new EnumOption( + "visibility", + "Field visibility", + { + private: Visibility.Private, + crate: Visibility.Crate, + public: Visibility.Public, + } as const, + "private", + ), + deriveDebug: new BooleanOption("derive-debug", "Derive Debug impl", false), + deriveClone: new BooleanOption("derive-clone", "Derive Clone impl", false), + derivePartialEq: new BooleanOption( + "derive-partial-eq", + "Derive PartialEq impl", + false, + ), + skipSerializingNone: new BooleanOption( + "skip-serializing-none", + "Skip serializing empty Option fields", + false, + ), + edition2018: new BooleanOption("edition-2018", "Edition 2018", true), + leadingComments: new BooleanOption( + "leading-comments", + "Leading Comments", + true, + ), +} as const; + +export const rustLanguageConfig = { + displayName: "Rust", + names: ["rust", "rs", "rustlang"], + extension: "rs", +} as const; + +export class RustTargetLanguage extends TargetLanguage< + typeof rustLanguageConfig +> { + public constructor() { + super(rustLanguageConfig); + } + + public getOptions(): typeof rustOptions { + return rustOptions; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): RustRenderer { + return new RustRenderer( + this, + renderContext, + getOptionValues(rustOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/Rust/utils.ts b/packages/quicktype-core/src/language/Rust/utils.ts new file mode 100644 index 000000000..52e8b509a --- /dev/null +++ b/packages/quicktype-core/src/language/Rust/utils.ts @@ -0,0 +1,207 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isAscii, + isLetterOrUnderscore, + isLetterOrUnderscoreOrDigit, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap, +} from "../../support/Strings"; + +export enum Density { + Normal = "Normal", + Dense = "Dense", +} + +export enum Visibility { + Private = "Private", + Crate = "Crate", + Public = "Public", +} + +type NameToParts = (name: string) => string[]; +type PartsToName = (parts: string[]) => string; +interface NamingStyle { + fromParts: PartsToName; + regex: RegExp; + toParts: NameToParts; +} + +export const namingStyles = { + snake_case: { + regex: /^[a-z][a-z0-9]*(_[a-z0-9]+)*$/, + toParts: (name: string): string[] => name.split("_"), + fromParts: (parts: string[]): string => + parts.map((p) => p.toLowerCase()).join("_"), + }, + SCREAMING_SNAKE_CASE: { + regex: /^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$/, + toParts: (name: string): string[] => name.split("_"), + fromParts: (parts: string[]): string => + parts.map((p) => p.toUpperCase()).join("_"), + }, + camelCase: { + regex: /^[a-z]+([A-Z0-9][a-z]*)*$/, + toParts: (name: string): string[] => + namingStyles.snake_case.toParts( + name.replace(/(.)([A-Z])/g, "$1_$2"), + ), + fromParts: (parts: string[]): string => + parts + .map((p, i) => + i === 0 + ? p.toLowerCase() + : p.substring(0, 1).toUpperCase() + + p.substring(1).toLowerCase(), + ) + .join(""), + }, + PascalCase: { + regex: /^[A-Z][a-z]*([A-Z0-9][a-z]*)*$/, + toParts: (name: string): string[] => + namingStyles.snake_case.toParts( + name.replace(/(.)([A-Z])/g, "$1_$2"), + ), + fromParts: (parts: string[]): string => + parts + .map( + (p) => + p.substring(0, 1).toUpperCase() + + p.substring(1).toLowerCase(), + ) + .join(""), + }, + "kebab-case": { + regex: /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/, + toParts: (name: string): string[] => name.split("-"), + fromParts: (parts: string[]): string => + parts.map((p) => p.toLowerCase()).join("-"), + }, + "SCREAMING-KEBAB-CASE": { + regex: /^[A-Z][A-Z0-9]*(-[A-Z0-9]+)*$/, + toParts: (name: string): string[] => name.split("-"), + fromParts: (parts: string[]): string => + parts.map((p) => p.toUpperCase()).join("-"), + }, + lowercase: { + regex: /^[a-z][a-z0-9]*$/, + toParts: (name: string): string[] => [name], + fromParts: (parts: string[]): string => + parts.map((p) => p.toLowerCase()).join(""), + }, + UPPERCASE: { + regex: /^[A-Z][A-Z0-9]*$/, + toParts: (name: string): string[] => [name], + fromParts: (parts: string[]): string => + parts.map((p) => p.toUpperCase()).join(""), + }, +} as const; + +namingStyles satisfies Record; + +export type NamingStyleKey = keyof typeof namingStyles; + +const isAsciiLetterOrUnderscoreOrDigit = (codePoint: number): boolean => { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscoreOrDigit(codePoint); +}; + +const isAsciiLetterOrUnderscore = (codePoint: number): boolean => { + if (!isAscii(codePoint)) { + return false; + } + + return isLetterOrUnderscore(codePoint); +}; + +const legalizeName = legalizeCharacters(isAsciiLetterOrUnderscoreOrDigit); + +function rustStyle(original: string, isSnakeCase: boolean): string { + const words = splitIntoWords(original); + + const wordStyle = isSnakeCase ? allLowerWordStyle : firstUpperWordStyle; + + const combined = combineWords( + words, + legalizeName, + wordStyle, + wordStyle, + wordStyle, + wordStyle, + isSnakeCase ? "_" : "", + isAsciiLetterOrUnderscore, + ); + + return combined === "_" ? "_underscore" : combined; +} + +export const snakeNamingFunction = funPrefixNamer( + "default", + (original: string) => rustStyle(original, true), +); +export const camelNamingFunction = funPrefixNamer("camel", (original: string) => + rustStyle(original, false), +); + +const standardUnicodeRustEscape = (codePoint: number): string => { + if (codePoint <= 0xffff) { + return "\\u{" + intToHex(codePoint, 4) + "}"; + } else { + return "\\u{" + intToHex(codePoint, 6) + "}"; + } +}; + +export const rustStringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, standardUnicodeRustEscape), +); + +export function getPreferredNamingStyle( + namingStyleOccurences: string[], + defaultStyle: NamingStyleKey, +): NamingStyleKey { + const occurrences = Object.fromEntries( + Object.keys(namingStyles).map((key) => [key, 0]), + ); + namingStyleOccurences.forEach((style) => ++occurrences[style]); + const max = Math.max(...Object.values(occurrences)); + const preferedStyles = Object.entries(occurrences).flatMap( + ([style, num]) => (num === max ? [style] : []), + ) as NamingStyleKey[]; + if (preferedStyles.includes(defaultStyle)) { + return defaultStyle; + } + + return preferedStyles[0]; +} + +export function listMatchingNamingStyles(name: string): NamingStyleKey[] { + return Object.entries(namingStyles).flatMap( + ([namingStyleKey, { regex }]) => + regex.test(name) ? [namingStyleKey] : [], + ) as NamingStyleKey[]; +} + +export function nameWithNamingStyle( + name: string, + style: NamingStyleKey, +): string { + if (namingStyles[style].regex.test(name)) { + return name; + } + + const fromStyle = listMatchingNamingStyles(name)[0]; + if (fromStyle === undefined) { + return name; + } + + return namingStyles[style].fromParts(namingStyles[fromStyle].toParts(name)); +} diff --git a/packages/quicktype-core/src/language/Scala3.ts b/packages/quicktype-core/src/language/Scala3.ts deleted file mode 100644 index 489749cea..000000000 --- a/packages/quicktype-core/src/language/Scala3.ts +++ /dev/null @@ -1,744 +0,0 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - isDigit, - isLetterOrUnderscore, - isNumeric, - legalizeCharacters, - splitIntoWords - -} from "../support/Strings"; -import { assertNever } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayType, - ClassProperty, - ClassType, - EnumType, - MapType, - ObjectType, - Type, - UnionType -} from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { RenderContext } from "../Renderer"; - -export enum Framework { - None, - Upickle, - Circe -} - -export const scala3Options = { - framework: new EnumOption("framework", "Serialization framework", - [ - ["just-types", Framework.None], - ["circe", Framework.Circe], - ["upickle", Framework.Upickle], - ] - , undefined), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") -}; - -// Use backticks for param names with symbols -const invalidSymbols = [ - ":", - "-", - "+", - "!", - "@", - "#", - "$", - "%", - "^", - "&", - "*", - "(", - ")", - ">", - "<", - "/", - ";", - "'", - '"', - "{", - "}", - ":", - "~", - "`", - "." -]; - -const keywords = [ - "abstract", - "case", - "catch", - "class", - "def", - "do", - "else", - "enum", - "extends", - "export", - "false", - "final", - "finally", - "for", - "forSome", - "if", - "implicit", - "import", - "lazy", - "match", - "new", - "null", - "object", - "override", - "package", - "private", - "protected", - "return", - "sealed", - "super", - "this", - "then", - "throw", - "trait", - "try", - "true", - "type", - "val", - "var", - "while", - "with", - "yield", - "Any", - "Boolean", - "Double", - "Float", - "Long", - "Int", - "Short", - "System", - "Byte", - "String", - "Array", - "List", - "Map", - "Enum" -]; - - -/** - * Check if given parameter name should be wrapped in a backtick - * @param paramName - */ -const shouldAddBacktick = (paramName: string): boolean => { - return keywords.some(s => paramName === s) || invalidSymbols.some(s => paramName.includes(s)) || !isNaN(+parseFloat(paramName)) || !isNaN(parseInt(paramName.charAt(0))); -}; - -const wrapOption = (s: string, optional: boolean): string => { - if (optional) { - return "Option[" + s + "]"; - } else { - return s; - } -}; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function scalaNameStyle(isUpper: boolean, original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -/* function unicodeEscape(codePoint: number): string { - return "\\u" + intToHex(codePoint, 4); -} */ - -//const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -/* function stringEscape(s: string): string { - // "$this" is a template string in Kotlin so we have to escape $ - return _stringEscape(s).replace(/\$/g, "\\$"); -} */ - -const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s)); -const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); - -export class Scala3Renderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: false }; - } - - protected topLevelNameStyle(rawName: string): string { - return scalaNameStyle(true, rawName); - } - - protected makeNamedTypeNamer(): Namer { - return upperNamingFunction; - } - - protected namerForObjectProperty(): Namer { - return lowerNamingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); - } - - protected emitBlock( - line: Sourcelike, - f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly" - ): void { - const [open, close] = - delimiter === "curly" - ? ["{", "}"] - : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; - this.emitLine(line, " ", open); - this.indent(f); - this.emitLine(close); - } - - protected anySourceType(optional: boolean): Sourcelike { - return [wrapOption("Any", optional)]; - } - - // (asarazan): I've broken out the following two functions - // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, withIssues = false): Sourcelike { - return ["Seq[", this.scalaType(arrayType.items, withIssues), "]"]; - } - - protected mapType(mapType: MapType, withIssues = false): Sourcelike { - return ["Map[String, ", this.scalaType(mapType.values, withIssues), "]"]; - } - - protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { - return matchType( - t, - _anyType => { - return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(!noOptional)); - }, - _nullType => { - //return "None.type" - return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(!noOptional)); - }, - _boolType => "Boolean", - _integerType => "Long", - _doubleType => "Double", - _stringType => "String", - arrayType => this.arrayType(arrayType, withIssues), - classType => this.nameForNamedType(classType), - mapType => this.mapType(mapType, withIssues), - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - if (noOptional) { - return [this.scalaType(nullable, withIssues)]; - } else { - return ["Option[", this.scalaType(nullable, withIssues), "]"]; - } - } - return this.nameForNamedType(unionType); - } - ); - } - protected emitUsageHeader(): void { - // To be overridden - } - - protected emitHeader(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else { - this.emitUsageHeader(); - } - - this.ensureBlankLine(); - this.emitLine("package ", this._scalaOptions.packageName); - this.ensureBlankLine(); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.scalaType(t.items); - this.emitLine(["type ", name, " = List[", elementType, "]"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.scalaType(t.values); - this.emitLine(["type ", name, " = Map[String, ", elementType, "]"]); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitLine("case class ", className, "()"); - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - if (c.getProperties().size === 0) { - this.emitEmptyClassDefinition(c, className); - return; - } - - const scalaType = (p: ClassProperty) => { - if (p.isOptional) { - return ["Option[", this.scalaType(p.type, true, true), "]"]; - } else { - return this.scalaType(p.type, true); - } - }; - - this.emitDescription(this.descriptionForType(c)); - this.emitLine("case class ", className, " ("); - this.indent(() => { - let count = c.getProperties().size; - let first = true; - this.forEachClassProperty(c, "none", (_, jsonName, p) => { - const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; - const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; - const last = --count === 0; - const meta: Array<() => void> = []; - - const description = this.descriptionForClassProperty(c, jsonName); - if (description !== undefined) { - meta.push(() => this.emitDescription(description)); - } - - if (meta.length > 0 && !first) { - this.ensureBlankLine(); - } - - for (const emit of meta) { - emit(); - } - const nameNeedsBackticks = jsonName.endsWith("_") || shouldAddBacktick(jsonName); - const nameWithBackticks = nameNeedsBackticks ? "`" + jsonName + "`" : jsonName; - this.emitLine( - "val ", - nameWithBackticks, - " : ", - scalaType(p), - p.isOptional ? " = None" : nullableOrOptional ? " = None" : "", - last ? "" : "," - ); - - if (meta.length > 0 && !last) { - this.ensureBlankLine(); - } - - first = false; - }); - }); - - this.emitClassDefinitionMethods(); - } - - protected emitClassDefinitionMethods() { - this.emitLine(")"); - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.emitBlock( - ["enum ", enumName, " : "], - () => { - let count = e.cases.size; - if (count > 0) { this.emitItem("\t case ") }; - this.forEachEnumCase(e, "none", (name, jsonName) => { - if (!(jsonName == "")) { - const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))) - if (backticks) { this.emitItem("`") } - this.emitItemOnce([name]); - if (backticks) { this.emitItem("`") } - if (--count > 0) this.emitItem([","]); - } else { - --count - } - }); - }, - "none" - ); - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Array = [] - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - theTypes.push(this.scalaType(t)); - }); - if (maybeNull !== null) { - theTypes.push(this.nameForUnionMember(u, maybeNull)); - } - - this.emitItem(["type ", unionName, " = "]); - theTypes.forEach((t, i) => { - this.emitItem(i === 0 ? t : [" | ", t]); - }); - this.ensureBlankLine(); - } - - protected emitSourceStructure(): void { - this.emitHeader(); - - // Top-level arrays, maps - this.forEachTopLevel("leading", (t, name) => { - if (t instanceof ArrayType) { - this.emitTopLevelArray(t, name); - } else if (t instanceof MapType) { - this.emitTopLevelMap(t, name); - } - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - } -} - -export class UpickleRenderer extends Scala3Renderer { - - protected emitClassDefinitionMethods() { - this.emitLine(") derives ReadWriter "); - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import upickle.default.*"); - this.ensureBlankLine(); - } - -} - -export class Smithy4sRenderer extends Scala3Renderer { - - protected emitHeader(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else { - this.emitUsageHeader(); - } - - this.ensureBlankLine(); - this.emitLine("namespace ", this._scalaOptions.packageName); - this.ensureBlankLine(); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.scalaType(t.items); - this.emitLine(["list ", name, " { member : ", elementType, "}"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.scalaType(t.values); - this.emitLine(["map ", name, " { map[ key : String , value : ", elementType, "}"]); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitLine("structure ", className, "{}"); - } - - - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.ensureBlankLine(); - this.emitItem(["enum ", enumName, " { "]); - let count = e.cases.size; - this.forEachEnumCase(e, "none", (name, jsonName) => { - // if (!(jsonName == "")) { - /* const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))) - if (backticks) {this.emitItem("`")} else */ - this.emitLine(); - this.emitItem([name, " = \"", jsonName, "\""]); - // if (backticks) {this.emitItem("`")} - if (--count > 0) this.emitItem([","]); - //} else { - //--count - //} - }); - this.ensureBlankLine(); - this.emitItem(["}"]); - - } - -} - - -export class CirceRenderer extends Scala3Renderer { - - seenUnionTypes: Array = []; - - protected circeEncoderForType(t: Type, _ = false, noOptional = false, paramName: string = ""): Sourcelike { - return matchType( - t, - _anyType => ["Encoder.encodeJson(", paramName, ")"], - _nullType => ["Encoder.encodeNone(", paramName, ")"], - _boolType => ["Encoder.encodeBoolean(", paramName, ")"], - _integerType => ["Encoder.encodeLong(", paramName, ")"], - _doubleType => ["Encoder.encodeDouble(", paramName, ")"], - _stringType => ["Encoder.encodeString(", paramName, ")"], - arrayType => ["Encoder.encodeSeq[", this.scalaType(arrayType.items), "].apply(", paramName, ")"], - classType => ["Encoder.AsObject[", this.scalaType(classType), "].apply(", paramName, ")"], - mapType => ["Encoder.encodeMap[String,", this.scalaType(mapType.values), "].apply(", paramName, ")"], - _ => ["Encoder.encodeString(", paramName, ")"], - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - if (noOptional) { - return ["Encoder.AsObject[", this.nameForNamedType(nullable), "]"]; - } else { - return ["Encoder.AsObject[Option[", this.nameForNamedType(nullable), "]]"]; - } - } - return ["Encoder.AsObject[", this.nameForNamedType(unionType), "]"]; - } - ); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.ensureBlankLine(); - this.emitLine("case class ", className, "() derives Encoder.AsObject, Decoder"); - } - - protected anySourceType(optional: boolean): Sourcelike { - return [wrapOption("Json", optional)]; - } - - protected emitClassDefinitionMethods() { - this.emitLine(") derives Encoder.AsObject, Decoder"); - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.ensureBlankLine(); - this.emitItem(["type ", enumName, " = "]); - let count = e.cases.size; - this.forEachEnumCase(e, "none", (_, jsonName) => { - // if (!(jsonName == "")) { - /* const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))) - if (backticks) {this.emitItem("`")} else */ - this.emitItem(["\"", jsonName, "\""]); - // if (backticks) {this.emitItem("`")} - if (--count > 0) this.emitItem([" | "]); - //} else { - //--count - //} - }); - this.ensureBlankLine(); - - } - - protected emitHeader(): void { - super.emitHeader(); - - this.emitLine("import scala.util.Try"); - this.emitLine("import io.circe.syntax._"); - this.emitLine("import io.circe._"); - this.emitLine("import cats.syntax.functor._"); - this.ensureBlankLine(); - - this.emitLine("// For serialising string unions") - this.emitLine("given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) "); - this.emitLine("given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) "); - this.ensureBlankLine(); - this.emitLine("// If a union has a null in, then we'll need this too... ") - this.emitLine("type NullValue = None.type"); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - super.emitTopLevelArray(t, name); - const elementType = this.scalaType(t.items); - this.emitLine(["given (using ev : ", elementType, "): Encoder[Map[String,", elementType, "]] = Encoder.encodeMap[String, ", elementType, "]"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - super.emitTopLevelMap(t, name); - const elementType = this.scalaType(t.values); - this.ensureBlankLine(); - this.emitLine(["given (using ev : ", elementType, "): Encoder[Map[String, ", elementType, "]] = Encoder.encodeMap[String, ", elementType, "]"]); - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Array = [] - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - theTypes.push(this.scalaType(t)); - }); - if (maybeNull !== null) { - theTypes.push(this.nameForUnionMember(u, maybeNull)); - } - - this.emitItem(["type ", unionName, " = "]); - theTypes.forEach((t, i) => { - this.emitItem(i === 0 ? t : [" | ", t]); - }); - const thisUnionType = theTypes.map(x => this.sourcelikeToString(x)).join(" | "); - - this.ensureBlankLine(); - if (!this.seenUnionTypes.some(y => y === thisUnionType)) { - this.seenUnionTypes.push(thisUnionType); - const sourceLikeTypes: Array<[Sourcelike, Type]> = [] - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - sourceLikeTypes.push([this.scalaType(t), t]); - - }); - if (maybeNull !== null) { - sourceLikeTypes.push([this.nameForUnionMember(u, maybeNull), maybeNull]); - } - - this.emitLine(["given Decoder[", unionName, "] = {"]) - this.indent(() => { - this.emitLine(["List[Decoder[", unionName, "]]("]) - this.indent(() => { - sourceLikeTypes.forEach((t) => { - this.emitLine(["Decoder[", t[0], "].widen,"]); - }); - }) - this.emitLine(").reduceLeft(_ or _)") - } - ) - this.emitLine(["}"]) - - this.ensureBlankLine(); - - this.emitLine(["given Encoder[", unionName, "] = Encoder.instance {"]) - this.indent(() => { - sourceLikeTypes.forEach((t, i) => { - const paramTemp = `enc${i.toString()}`; - this.emitLine(["case ", paramTemp, " : ", t[0], " => ", this.circeEncoderForType(t[1], false, false, paramTemp)]); - }); - }) - this.emitLine("}") - } - } -} - -export class Scala3TargetLanguage extends TargetLanguage { - constructor() { - super("Scala3", ["scala3"], "scala"); - } - - protected getOptions(): Option[] { - return [scala3Options.framework, scala3Options.packageName]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { - const options = getOptionValues(scala3Options, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new Scala3Renderer(this, renderContext, options); - case Framework.Upickle: - return new UpickleRenderer(this, renderContext, options); - case Framework.Circe: - return new CirceRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } - } -} - diff --git a/packages/quicktype-core/src/language/Scala3/CirceRenderer.ts b/packages/quicktype-core/src/language/Scala3/CirceRenderer.ts new file mode 100644 index 000000000..348b585ad --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/CirceRenderer.ts @@ -0,0 +1,254 @@ +import type { Name } from "../../Naming"; +import type { Sourcelike } from "../../Source"; +import type { + ArrayType, + ClassType, + EnumType, + MapType, + Type, + UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { Scala3Renderer } from "./Scala3Renderer"; +import { wrapOption } from "./utils"; + +export class CirceRenderer extends Scala3Renderer { + private seenUnionTypes: string[] = []; + + protected circeEncoderForType( + t: Type, + __ = false, + noOptional = false, + paramName = "", + ): Sourcelike { + return matchType( + t, + (_anyType) => ["Encoder.encodeJson(", paramName, ")"], + (_nullType) => ["Encoder.encodeNone(", paramName, ")"], + (_boolType) => ["Encoder.encodeBoolean(", paramName, ")"], + (_integerType) => ["Encoder.encodeLong(", paramName, ")"], + (_doubleType) => ["Encoder.encodeDouble(", paramName, ")"], + (_stringType) => ["Encoder.encodeString(", paramName, ")"], + (arrayType) => [ + "Encoder.encodeSeq[", + this.scalaType(arrayType.items), + "].apply(", + paramName, + ")", + ], + (classType) => [ + "Encoder.AsObject[", + this.scalaType(classType), + "].apply(", + paramName, + ")", + ], + (mapType) => [ + "Encoder.encodeMap[String,", + this.scalaType(mapType.values), + "].apply(", + paramName, + ")", + ], + (_) => ["Encoder.encodeString(", paramName, ")"], + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (noOptional) { + return [ + "Encoder.AsObject[", + this.nameForNamedType(nullable), + "]", + ]; + } + + return [ + "Encoder.AsObject[Option[", + this.nameForNamedType(nullable), + "]]", + ]; + } + + return [ + "Encoder.AsObject[", + this.nameForNamedType(unionType), + "]", + ]; + }, + ); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.ensureBlankLine(); + this.emitLine( + "case class ", + className, + "() derives Encoder.AsObject, Decoder", + ); + } + + protected anySourceType(optional: boolean): Sourcelike { + return [wrapOption("Json", optional)]; + } + + protected emitClassDefinitionMethods(): void { + this.emitLine(") derives Encoder.AsObject, Decoder"); + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.ensureBlankLine(); + this.emitItem(["type ", enumName, " = "]); + let count = e.cases.size; + this.forEachEnumCase(e, "none", (_, jsonName) => { + // if (!(jsonName == "")) { + /* const backticks = + shouldAddBacktick(jsonName) || + jsonName.includes(" ") || + !isNaN(parseInt(jsonName.charAt(0))) + if (backticks) {this.emitItem("`")} else */ + this.emitItem(['"', jsonName, '"']); + // if (backticks) {this.emitItem("`")} + if (--count > 0) this.emitItem([" | "]); + // } else { + // --count + // } + }); + this.ensureBlankLine(); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import scala.util.Try"); + this.emitLine("import io.circe.syntax._"); + this.emitLine("import io.circe._"); + this.emitLine("import cats.syntax.functor._"); + this.ensureBlankLine(); + + this.emitLine("// For serialising string unions"); + this.emitLine( + "given [A <: Singleton](using A <:< String): Decoder[A] = Decoder.decodeString.emapTry(x => Try(x.asInstanceOf[A])) ", + ); + this.emitLine( + "given [A <: Singleton](using ev: A <:< String): Encoder[A] = Encoder.encodeString.contramap(ev) ", + ); + this.ensureBlankLine(); + this.emitLine( + "// If a union has a null in, then we'll need this too... ", + ); + this.emitLine("type NullValue = None.type"); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + super.emitTopLevelArray(t, name); + const elementType = this.scalaType(t.items); + this.emitLine([ + "given (using ev : ", + elementType, + "): Encoder[Map[String,", + elementType, + "]] = Encoder.encodeMap[String, ", + elementType, + "]", + ]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + super.emitTopLevelMap(t, name); + const elementType = this.scalaType(t.values); + this.ensureBlankLine(); + this.emitLine([ + "given (using ev : ", + elementType, + "): Encoder[Map[String, ", + elementType, + "]] = Encoder.encodeMap[String, ", + elementType, + "]", + ]); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return "_" + kind; + } + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + const theTypes: Sourcelike[] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + theTypes.push(this.scalaType(t)); + }); + if (maybeNull !== null) { + theTypes.push(this.nameForUnionMember(u, maybeNull)); + } + + this.emitItem(["type ", unionName, " = "]); + theTypes.forEach((t, i) => { + this.emitItem(i === 0 ? t : [" | ", t]); + }); + const thisUnionType = theTypes + .map((x) => this.sourcelikeToString(x)) + .join(" | "); + + this.ensureBlankLine(); + if (!this.seenUnionTypes.some((y) => y === thisUnionType)) { + this.seenUnionTypes.push(thisUnionType); + const sourceLikeTypes: Array<[Sourcelike, Type]> = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + sourceLikeTypes.push([this.scalaType(t), t]); + }); + if (maybeNull !== null) { + sourceLikeTypes.push([ + this.nameForUnionMember(u, maybeNull), + maybeNull, + ]); + } + + this.emitLine(["given Decoder[", unionName, "] = {"]); + this.indent(() => { + this.emitLine(["List[Decoder[", unionName, "]]("]); + this.indent(() => { + sourceLikeTypes.forEach((t) => { + this.emitLine(["Decoder[", t[0], "].widen,"]); + }); + }); + this.emitLine(").reduceLeft(_ or _)"); + }); + this.emitLine(["}"]); + + this.ensureBlankLine(); + + this.emitLine([ + "given Encoder[", + unionName, + "] = Encoder.instance {", + ]); + this.indent(() => { + sourceLikeTypes.forEach((t, i) => { + const paramTemp = `enc${i.toString()}`; + this.emitLine([ + "case ", + paramTemp, + " : ", + t[0], + " => ", + this.circeEncoderForType(t[1], false, false, paramTemp), + ]); + }); + }); + this.emitLine("}"); + } + } +} diff --git a/packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts b/packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts new file mode 100644 index 000000000..913fd6149 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/Scala3Renderer.ts @@ -0,0 +1,378 @@ +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type Type, + type UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { scala3Options } from "./language"; +import { + lowerNamingFunction, + scalaNameStyle, + shouldAddBacktick, + upperNamingFunction, + wrapOption, +} from "./utils"; + +export class Scala3Renderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _scalaOptions: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties( + _: ObjectType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases( + _: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: false }; + } + + protected topLevelNameStyle(rawName: string): string { + return scalaNameStyle(true, rawName); + } + + protected makeNamedTypeNamer(): Namer { + return upperNamingFunction; + } + + protected namerForObjectProperty(): Namer { + return lowerNamingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer( + "upper", + (s) => `${scalaNameStyle(true, s)}Value`, + ); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("upper", (s) => s.replace(" ", "")); // TODO - add backticks where appropriate + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); + } + + protected emitBlock( + line: Sourcelike, + f: () => void, + delimiter: "curly" | "paren" | "lambda" | "none" = "curly", + ): void { + const [open, close] = + delimiter === "curly" + ? ["{", "}"] + : delimiter === "paren" + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; + this.emitLine(line, " ", open); + this.indent(f); + this.emitLine(close); + } + + protected anySourceType(optional: boolean): Sourcelike { + return [wrapOption("Any", optional)]; + } + + // (asarazan): I've broken out the following two functions + // because some renderers, such as kotlinx, can cope with `any`, while some get mad. + protected arrayType(arrayType: ArrayType, withIssues = false): Sourcelike { + return ["Seq[", this.scalaType(arrayType.items, withIssues), "]"]; + } + + protected mapType(mapType: MapType, withIssues = false): Sourcelike { + return [ + "Map[String, ", + this.scalaType(mapType.values, withIssues), + "]", + ]; + } + + protected scalaType( + t: Type, + withIssues = false, + noOptional = false, + ): Sourcelike { + return matchType( + t, + (_anyType) => { + return maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + this.anySourceType(!noOptional), + ); + }, + (_nullType) => { + // return "None.type" + return maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + this.anySourceType(!noOptional), + ); + }, + (_boolType) => "Boolean", + (_integerType) => "Long", + (_doubleType) => "Double", + (_stringType) => "String", + (arrayType) => this.arrayType(arrayType, withIssues), + (classType) => this.nameForNamedType(classType), + (mapType) => this.mapType(mapType, withIssues), + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + if (noOptional) { + return [this.scalaType(nullable, withIssues)]; + } + + return [ + "Option[", + this.scalaType(nullable, withIssues), + "]", + ]; + } + + return this.nameForNamedType(unionType); + }, + ); + } + + protected emitUsageHeader(): void { + // To be overridden + } + + protected emitHeader(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitUsageHeader(); + } + + this.ensureBlankLine(); + this.emitLine("package ", this._scalaOptions.packageName); + this.ensureBlankLine(); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.scalaType(t.items); + this.emitLine(["type ", name, " = List[", elementType, "]"]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.scalaType(t.values); + this.emitLine(["type ", name, " = Map[String, ", elementType, "]"]); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitLine("case class ", className, "()"); + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + if (c.getProperties().size === 0) { + this.emitEmptyClassDefinition(c, className); + return; + } + + const scalaType = (p: ClassProperty): Sourcelike => { + if (p.isOptional) { + return ["Option[", this.scalaType(p.type, true, true), "]"]; + } + + return this.scalaType(p.type, true); + }; + + this.emitDescription(this.descriptionForType(c)); + this.emitLine("case class ", className, " ("); + this.indent(() => { + let count = c.getProperties().size; + let first = true; + this.forEachClassProperty(c, "none", (_, jsonName, p) => { + const nullable = + p.type.kind === "union" && + nullableFromUnion(p.type as UnionType) !== null; + const nullableOrOptional = + p.isOptional || p.type.kind === "null" || nullable; + const last = --count === 0; + const meta: Array<() => void> = []; + + const description = this.descriptionForClassProperty( + c, + jsonName, + ); + if (description !== undefined) { + meta.push(() => this.emitDescription(description)); + } + + if (meta.length > 0 && !first) { + this.ensureBlankLine(); + } + + for (const emit of meta) { + emit(); + } + + const nameNeedsBackticks = + jsonName.endsWith("_") || shouldAddBacktick(jsonName); + const nameWithBackticks = nameNeedsBackticks + ? "`" + jsonName + "`" + : jsonName; + this.emitLine( + "val ", + nameWithBackticks, + " : ", + scalaType(p), + p.isOptional + ? " = None" + : nullableOrOptional + ? " = None" + : "", + last ? "" : ",", + ); + + if (meta.length > 0 && !last) { + this.ensureBlankLine(); + } + + first = false; + }); + }); + + this.emitClassDefinitionMethods(); + } + + protected emitClassDefinitionMethods(): void { + this.emitLine(")"); + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.emitBlock( + ["enum ", enumName, " : "], + () => { + let count = e.cases.size; + if (count > 0) { + this.emitItem("\t case "); + } + + this.forEachEnumCase(e, "none", (name, jsonName) => { + if (!(jsonName === "")) { + const backticks = + shouldAddBacktick(jsonName) || + jsonName.includes(" ") || + !Number.isNaN(Number.parseInt(jsonName.charAt(0))); + if (backticks) { + this.emitItem("`"); + } + + this.emitItemOnce([name]); + if (backticks) { + this.emitItem("`"); + } + + if (--count > 0) this.emitItem([","]); + } else { + --count; + } + }); + }, + "none", + ); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return `_${kind}`; + } + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + const theTypes: Sourcelike[] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + theTypes.push(this.scalaType(t)); + }); + if (maybeNull !== null) { + theTypes.push(this.nameForUnionMember(u, maybeNull)); + } + + this.emitItem(["type ", unionName, " = "]); + theTypes.forEach((t, i) => { + this.emitItem(i === 0 ? t : [" | ", t]); + }); + this.ensureBlankLine(); + } + + protected emitSourceStructure(): void { + this.emitHeader(); + + // Top-level arrays, maps + this.forEachTopLevel("leading", (t, name) => { + if (t instanceof ArrayType) { + this.emitTopLevelArray(t, name); + } else if (t instanceof MapType) { + this.emitTopLevelMap(t, name); + } + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n), + ); + } +} diff --git a/packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts b/packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts new file mode 100644 index 000000000..0eb5ce354 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/UpickleRenderer.ts @@ -0,0 +1,14 @@ +import { Scala3Renderer } from "./Scala3Renderer"; + +export class UpickleRenderer extends Scala3Renderer { + protected emitClassDefinitionMethods(): void { + this.emitLine(") derives ReadWriter "); + } + + protected emitHeader(): void { + super.emitHeader(); + + this.emitLine("import upickle.default.*"); + this.ensureBlankLine(); + } +} diff --git a/packages/quicktype-core/src/language/Scala3/constants.ts b/packages/quicktype-core/src/language/Scala3/constants.ts new file mode 100644 index 000000000..918172d7f --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/constants.ts @@ -0,0 +1,87 @@ +// Use backticks for param names with symbols +export const invalidSymbols = [ + ":", + "-", + "+", + "!", + "@", + "#", + "$", + "%", + "^", + "&", + "*", + "(", + ")", + ">", + "<", + "/", + ";", + "'", + '"', + "{", + "}", + ":", + "~", + "`", + ".", +] as const; + +export const keywords = [ + "abstract", + "case", + "catch", + "class", + "def", + "do", + "else", + "enum", + "extends", + "export", + "false", + "final", + "finally", + "for", + "forSome", + "if", + "implicit", + "import", + "lazy", + "match", + "new", + "null", + "object", + "override", + "package", + "private", + "protected", + "return", + "sealed", + "super", + "this", + "then", + "throw", + "trait", + "try", + "true", + "type", + "val", + "var", + "while", + "with", + "yield", + "Any", + "Boolean", + "Double", + "Float", + "Long", + "Int", + "Short", + "System", + "Byte", + "String", + "Array", + "List", + "Map", + "Enum", +] as const; diff --git a/packages/quicktype-core/src/language/Scala3/index.ts b/packages/quicktype-core/src/language/Scala3/index.ts new file mode 100644 index 000000000..33c5960ae --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/index.ts @@ -0,0 +1,4 @@ +export { Scala3TargetLanguage, scala3Options } from "./language"; +export { Scala3Renderer } from "./Scala3Renderer"; +export { CirceRenderer } from "./CirceRenderer"; +export { UpickleRenderer } from "./UpickleRenderer"; diff --git a/packages/quicktype-core/src/language/Scala3/language.ts b/packages/quicktype-core/src/language/Scala3/language.ts new file mode 100644 index 000000000..235a202a2 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/language.ts @@ -0,0 +1,72 @@ +import type { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import type { RenderContext } from "../../Renderer"; +import { + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { CirceRenderer } from "./CirceRenderer"; +import { Scala3Renderer } from "./Scala3Renderer"; +import { UpickleRenderer } from "./UpickleRenderer"; + +export const scala3Options = { + framework: new EnumOption( + "framework", + "Serialization framework", + { + "just-types": "None", + circe: "Circe", + upickle: "Upickle", + } as const, + "just-types", + ), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), +}; + +export const scala3LanguageConfig = { + displayName: "Scala3", + names: ["scala3"], + extension: "scala", +} as const; + +export class Scala3TargetLanguage extends TargetLanguage< + typeof scala3LanguageConfig +> { + public constructor() { + super(scala3LanguageConfig); + } + + public getOptions(): typeof scala3Options { + return scala3Options; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ConvenienceRenderer { + const options = getOptionValues(scala3Options, untypedOptionValues); + + switch (options.framework) { + case "None": + return new Scala3Renderer(this, renderContext, options); + case "Upickle": + return new UpickleRenderer(this, renderContext, options); + case "Circe": + return new CirceRenderer(this, renderContext, options); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/Scala3/utils.ts b/packages/quicktype-core/src/language/Scala3/utils.ts new file mode 100644 index 000000000..54b9ed008 --- /dev/null +++ b/packages/quicktype-core/src/language/Scala3/utils.ts @@ -0,0 +1,77 @@ +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isDigit, + isLetterOrUnderscore, + isNumeric, + legalizeCharacters, + splitIntoWords, +} from "../../support/Strings"; + +import { invalidSymbols, keywords } from "./constants"; + +/** + * Check if given parameter name should be wrapped in a backtick + * @param paramName + */ +export const shouldAddBacktick = (paramName: string): boolean => { + return ( + keywords.some((s) => paramName === s) || + invalidSymbols.some((s) => paramName.includes(s)) || + !isNaN(+Number.parseFloat(paramName)) || + !isNaN(Number.parseInt(paramName.charAt(0))) + ); +}; + +export const wrapOption = (s: string, optional: boolean): string => { + if (optional) { + return "Option[" + s + "]"; + } else { + return s; + } +}; + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function scalaNameStyle(isUpper: boolean, original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isStartCharacter, + ); +} + +/* function unicodeEscape(codePoint: number): string { + return "\\u" + intToHex(codePoint, 4); +} */ + +// const _stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); + +/* function stringEscape(s: string): string { + // "$this" is a template string in Kotlin so we have to escape $ + return _stringEscape(s).replace(/\$/g, "\\$"); +} */ + +export const upperNamingFunction = funPrefixNamer("upper", (s) => + scalaNameStyle(true, s), +); +export const lowerNamingFunction = funPrefixNamer("lower", (s) => + scalaNameStyle(false, s), +); diff --git a/packages/quicktype-core/src/language/Smithy4s.ts b/packages/quicktype-core/src/language/Smithy4s.ts deleted file mode 100644 index 3b4ece721..000000000 --- a/packages/quicktype-core/src/language/Smithy4s.ts +++ /dev/null @@ -1,537 +0,0 @@ -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated } from "../Source"; -import { - allLowerWordStyle, - allUpperWordStyle, - combineWords, - firstUpperWordStyle, - isDigit, - isLetterOrUnderscore, - isNumeric, - legalizeCharacters, - splitIntoWords - -} from "../support/Strings"; -import { assertNever } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { - ArrayType, - ClassProperty, - ClassType, - EnumType, - MapType, - ObjectType, - Type, - UnionType -} from "../Type"; -import { matchCompoundType, matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { RenderContext } from "../Renderer"; - -export enum Framework { - None -} - -export const SmithyOptions = { - framework: new EnumOption("framework", "Serialization framework", - [ - ["just-types", Framework.None] - ] - , undefined), - packageName: new StringOption("package", "Package", "PACKAGE", "quicktype") -}; - -// Use backticks for param names with symbols -const invalidSymbols = [ - ":", - "-", - "+", - "!", - "@", - "#", - "%", - "^", - "&", - "*", - "(", - ")", - ">", - "<", - "/", - ";", - "'", - '"', - "{", - "}", - ":", - "~", - "`", - "." -]; - -const keywords = [ - "abstract", - "case", - "catch", - "do", - "else", - "export", - "false", - "final", - "finally", - "for", - "forSome", - "if", - "implicit", - "import", - "new", - "override", - "package", - "private", - "protected", - "return", - "sealed", - "super", - "this", - "then", - "throw", - "trait", - "try", - "true", - "val", - "var", - "while", - "with", - "yield", - "Any", - "Boolean", - "Double", - "Float", - "Long", - "Int", - "Short", - "System", - "Byte", - "String", - "Array", - "List", - "Map", - "Enum" -]; - - -/** - * Check if given parameter name should be wrapped in a backtick - * @param paramName - */ -const shouldAddBacktick = (paramName: string): boolean => { - return keywords.some(s => paramName === s) || invalidSymbols.some(s => paramName.includes(s)) || !isNaN(parseFloat(paramName)) || !isNaN(parseInt(paramName.charAt(0))); -}; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function scalaNameStyle(isUpper: boolean, original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -const upperNamingFunction = funPrefixNamer("upper", s => scalaNameStyle(true, s)); -const lowerNamingFunction = funPrefixNamer("lower", s => scalaNameStyle(false, s)); - -export class Smithy4sRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _scalaOptions: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords; - } - - protected forbiddenForObjectProperties(_: ObjectType, _classNamed: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: false }; - } - - protected topLevelNameStyle(rawName: string): string { - return scalaNameStyle(true, rawName); - } - - protected makeNamedTypeNamer(): Namer { - return upperNamingFunction; - } - - protected namerForObjectProperty(): Namer { - return lowerNamingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("upper", s => scalaNameStyle(true, s) + "Value"); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("upper", s => s.replace(" ", "")); // TODO - add backticks where appropriate - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, " * ", "/**", " */"); - } - - protected emitBlock( - line: Sourcelike, - f: () => void, - delimiter: "curly" | "paren" | "lambda" | "none" = "curly" - ): void { - const [open, close] = - delimiter === "curly" - ? ["{", "}"] - : delimiter === "paren" - ? ["(", ")"] - : delimiter === "none" - ? ["", ""] - : ["{", "})"]; - this.emitLine(line, " ", open); - this.indent(f); - this.emitLine(close); - } - - protected anySourceType(_: boolean): Sourcelike { - return ["Document"]; - } - - // (asarazan): I've broken out the following two functions - // because some renderers, such as kotlinx, can cope with `any`, while some get mad. - protected arrayType(arrayType: ArrayType, _ = false): Sourcelike { - //this.emitTopLevelArray(arrayType, new Name(arrayType.getCombinedName().toString() + "List")) - return arrayType.getCombinedName().toString() + "List"; - } - - protected emitArrayType(_: ArrayType, smithyType: Sourcelike): void { - this.emitLine([ "list " , smithyType , " { member : ", "}" ]) - } - - protected mapType(mapType: MapType, _ = false): Sourcelike { - return mapType.getCombinedName().toString() + "Map" - //return [this.scalaType(mapType.values, withIssues), "Map"]; - } - - protected scalaType(t: Type, withIssues = false, noOptional = false): Sourcelike { - return matchType( - t, - _anyType => { - return maybeAnnotated(withIssues, anyTypeIssueAnnotation, this.anySourceType(!noOptional)); - }, - _nullType => { - //return "None.type" - return maybeAnnotated(withIssues, nullTypeIssueAnnotation, this.anySourceType(!noOptional)); - }, - _boolType => "Boolean", - _integerType => "Long", - _doubleType => "Double", - _stringType => "String", - arrayType => this.arrayType(arrayType, withIssues), - classType => this.nameForNamedType(classType), - mapType => this.mapType(mapType, withIssues), - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return [this.scalaType(nullable, withIssues)]; - } - return this.nameForNamedType(unionType); - } - ); - } - - - - protected emitUsageHeader(): void { - // To be overridden - } - - protected emitHeader(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else { - this.emitUsageHeader(); - } - - this.ensureBlankLine(); - this.emitLine("$version: \"2\""); - this.emitLine("namespace ", this._scalaOptions.packageName); - this.ensureBlankLine(); - - this.emitLine("document NullValue"); - this.ensureBlankLine(); - } - - protected emitTopLevelArray(t: ArrayType, name: Name): void { - const elementType = this.scalaType(t.items); - this.emitLine(["list ", name, " { member : ", elementType, "}"]); - } - - protected emitTopLevelMap(t: MapType, name: Name): void { - const elementType = this.scalaType(t.values); - this.emitLine(["map ", name, " { map[ key : String , value : ", elementType, "}"]); - } - - protected emitEmptyClassDefinition(c: ClassType, className: Name): void { - this.emitDescription(this.descriptionForType(c)); - this.emitLine("structure ", className, "{}"); - } - - protected emitClassDefinition(c: ClassType, className: Name): void { - if (c.getProperties().size === 0) { - this.emitEmptyClassDefinition(c, className); - return; - } - - const scalaType = (p: ClassProperty) => { - if (p.isOptional) { - return [this.scalaType(p.type, true, true)]; - } else { - return [this.scalaType(p.type, true)]; - } - }; - - const emitLater: Array = []; - - this.emitDescription(this.descriptionForType(c)); - this.emitLine("structure ", className, " {"); - this.indent(() => { - let count = c.getProperties().size; - let first = true; - - - this.forEachClassProperty(c, "none", (_, jsonName, p) => { - const nullable = p.type.kind === "union" && nullableFromUnion(p.type as UnionType) !== null; - const nullableOrOptional = p.isOptional || p.type.kind === "null" || nullable; - const last = --count === 0; - const meta: Array<() => void> = []; - - const laterType = p.type.kind === "array" || p.type.kind === "map" - if(laterType) { - emitLater.push(p) - } - - const description = this.descriptionForClassProperty(c, jsonName); - if (description !== undefined) { - meta.push(() => this.emitDescription(description)); - } - - if (meta.length > 0 && !first) { - this.ensureBlankLine(); - } - - for (const emit of meta) { - emit(); - } - const nameNeedsBackticks = jsonName.endsWith("_") || shouldAddBacktick(jsonName); - const nameWithBackticks = nameNeedsBackticks ? "`" + jsonName + "`" : jsonName; - this.emitLine( - p.isOptional ? "" : nullableOrOptional ? "" : "@required ", - nameWithBackticks, - " : ", - scalaType(p), - - last ? "" : "," - ); - - if (meta.length > 0 && !last) { - this.ensureBlankLine(); - } - - first = false; - }); - }); - this.emitClassDefinitionMethods(emitLater); - } - - protected emitClassDefinitionMethods( arrayTypes : ClassProperty[] ) { - this.emitLine("}"); - arrayTypes.forEach (p => { - function ignore(_: T): void { - return; - } - matchCompoundType(p.type, - at => { - this.emitLine([ "list ", this.scalaType(at, true) , "{ member: ", this.scalaType(at.items, true), "}" ])}, - ignore, - mt =>{ - this.emitLine([ "map ", this.scalaType(mt, true) , "{ key: String , value: ", this.scalaType(mt.values, true), "}" ]) - }, - ignore, - ignore) - - } - ) - - } - - protected emitEnumDefinition(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - this.ensureBlankLine(); - this.emitItem(["enum ", enumName, " { "]); - let count = e.cases.size; - - - this.forEachEnumCase(e, "none", (name, jsonName) => { - // if (!(jsonName == "")) { - /* const backticks = - shouldAddBacktick(jsonName) || - jsonName.includes(" ") || - !isNaN(parseInt(jsonName.charAt(0))) - if (backticks) {this.emitItem("`")} else */ - this.emitLine(); - - this.emitItem([name, " = \"", jsonName, "\""]); - - // if (backticks) {this.emitItem("`")} - if (--count > 0) this.emitItem([","]); - //} else { - //--count - //} - }); - - this.ensureBlankLine(); - this.emitItem(["}"]); - - } - - protected emitUnionDefinition(u: UnionType, unionName: Name): void { - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - const emitLater: Array = []; - - - this.emitDescription(this.descriptionForType(u)); - - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - const theTypes: Array = [] - this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { - const laterType = t.kind === "array" || t.kind === "map" - if(laterType) { - emitLater.push(t) - } - theTypes.push(this.scalaType(t)); - }); - if (maybeNull !== null) { - theTypes.push(this.nameForUnionMember(u, maybeNull)); - } - - this.emitLine(["@untagged union ", unionName, " { "]); - this.indent(() => { - theTypes.forEach((t, i) => { - this.emitLine([String.fromCharCode(i+65), " : ", t]); - }); - }); - this.emitLine("}") - this.ensureBlankLine(); - - emitLater.forEach (p => { - function ignore(_: T): void { - return; - } - matchCompoundType(p, - at => { - this.emitLine([ "list ", this.scalaType(at, true) , "{ member: ", this.scalaType(at.items, true), "}" ])}, - ignore, - mt =>{ - this.emitLine([ "map ", this.scalaType(mt, true) , "{ key: String , value: ", this.scalaType(mt.values, true), "}" ]) - }, - ignore, - ignore) - - } - ) - - } - - protected emitSourceStructure(): void { - this.emitHeader(); - - // Top-level arrays, maps - this.forEachTopLevel("leading", (t, name) => { - if (t instanceof ArrayType) { - this.emitTopLevelArray(t, name); - } else if (t instanceof MapType) { - this.emitTopLevelMap(t, name); - } - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClassDefinition(c, n), - (e, n) => this.emitEnumDefinition(e, n), - (u, n) => this.emitUnionDefinition(u, n) - ); - } -} - - -export class SmithyTargetLanguage extends TargetLanguage { - constructor() { - super("Smithy", ["Smithy"], "smithy"); - } - - protected getOptions(): Option[] { - return [SmithyOptions.framework, SmithyOptions.packageName]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): ConvenienceRenderer { - const options = getOptionValues(SmithyOptions, untypedOptionValues); - - switch (options.framework) { - case Framework.None: - return new Smithy4sRenderer(this, renderContext, options); - default: - return assertNever(options.framework); - } - } -} - diff --git a/packages/quicktype-core/src/language/Smithy4s/Smithy4sRenderer.ts b/packages/quicktype-core/src/language/Smithy4s/Smithy4sRenderer.ts new file mode 100644 index 000000000..da4141aa1 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/Smithy4sRenderer.ts @@ -0,0 +1,450 @@ +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated } from "../../Source"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + type EnumType, + MapType, + type ObjectType, + type Type, + type UnionType, +} from "../../Type"; +import { + matchCompoundType, + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { smithyOptions } from "./language"; +import { + lowerNamingFunction, + scalaNameStyle, + shouldAddBacktick, + upperNamingFunction, +} from "./utils"; + +export class Smithy4sRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _scalaOptions: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + return keywords; + } + + protected forbiddenForObjectProperties( + _: ObjectType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases( + _: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: false }; + } + + protected topLevelNameStyle(rawName: string): string { + return scalaNameStyle(true, rawName); + } + + protected makeNamedTypeNamer(): Namer { + return upperNamingFunction; + } + + protected namerForObjectProperty(): Namer { + return lowerNamingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer( + "upper", + (s) => `${scalaNameStyle(true, s)}Value`, + ); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("upper", (s) => s.replace(" ", "")); // TODO - add backticks where appropriate + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { + lineStart: " * ", + beforeComment: "/**", + afterComment: " */", + }); + } + + protected emitBlock( + line: Sourcelike, + f: () => void, + delimiter: "curly" | "paren" | "lambda" | "none" = "curly", + ): void { + const [open, close] = + delimiter === "curly" + ? ["{", "}"] + : delimiter === "paren" + ? ["(", ")"] + : delimiter === "none" + ? ["", ""] + : ["{", "})"]; + this.emitLine(line, " ", open); + this.indent(f); + this.emitLine(close); + } + + protected anySourceType(_: boolean): Sourcelike { + return ["Document"]; + } + + // (asarazan): I've broken out the following two functions + // because some renderers, such as kotlinx, can cope with `any`, while some get mad. + protected arrayType(arrayType: ArrayType, _ = false): Sourcelike { + // this.emitTopLevelArray(arrayType, new Name(arrayType.getCombinedName().toString() + "List")) + return arrayType.getCombinedName().toString() + "List"; + } + + protected emitArrayType(_: ArrayType, smithyType: Sourcelike): void { + this.emitLine(["list ", smithyType, " { member : ", "}"]); + } + + protected mapType(mapType: MapType, _ = false): Sourcelike { + return mapType.getCombinedName().toString() + "Map"; + // return [this.scalaType(mapType.values, withIssues), "Map"]; + } + + protected scalaType( + t: Type, + withIssues = false, + noOptional = false, + ): Sourcelike { + return matchType( + t, + (_anyType) => { + return maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + this.anySourceType(!noOptional), + ); + }, + (_nullType) => { + // return "None.type" + return maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + this.anySourceType(!noOptional), + ); + }, + (_boolType) => "Boolean", + (_integerType) => "Long", + (_doubleType) => "Double", + (_stringType) => "String", + (arrayType) => this.arrayType(arrayType, withIssues), + (classType) => this.nameForNamedType(classType), + (mapType) => this.mapType(mapType, withIssues), + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) { + return [this.scalaType(nullable, withIssues)]; + } + + return this.nameForNamedType(unionType); + }, + ); + } + + protected emitUsageHeader(): void { + // To be overridden + } + + protected emitHeader(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else { + this.emitUsageHeader(); + } + + this.ensureBlankLine(); + this.emitLine('$version: "2"'); + this.emitLine("namespace ", this._scalaOptions.packageName); + this.ensureBlankLine(); + + this.emitLine("document NullValue"); + this.ensureBlankLine(); + } + + protected emitTopLevelArray(t: ArrayType, name: Name): void { + const elementType = this.scalaType(t.items); + this.emitLine(["list ", name, " { member : ", elementType, "}"]); + } + + protected emitTopLevelMap(t: MapType, name: Name): void { + const elementType = this.scalaType(t.values); + this.emitLine([ + "map ", + name, + " { map[ key : String , value : ", + elementType, + "}", + ]); + } + + protected emitEmptyClassDefinition(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitLine("structure ", className, "{}"); + } + + protected emitClassDefinition(c: ClassType, className: Name): void { + if (c.getProperties().size === 0) { + this.emitEmptyClassDefinition(c, className); + return; + } + + const scalaType = (p: ClassProperty): Sourcelike => { + if (p.isOptional) { + return [this.scalaType(p.type, true, true)]; + } + + return [this.scalaType(p.type, true)]; + }; + + const emitLater: ClassProperty[] = []; + + this.emitDescription(this.descriptionForType(c)); + this.emitLine("structure ", className, " {"); + this.indent(() => { + let count = c.getProperties().size; + let first = true; + + this.forEachClassProperty(c, "none", (_, jsonName, p) => { + const nullable = + p.type.kind === "union" && + nullableFromUnion(p.type as UnionType) !== null; + const nullableOrOptional = + p.isOptional || p.type.kind === "null" || nullable; + const last = --count === 0; + const meta: Array<() => void> = []; + + const laterType = + p.type.kind === "array" || p.type.kind === "map"; + if (laterType) { + emitLater.push(p); + } + + const description = this.descriptionForClassProperty( + c, + jsonName, + ); + if (description !== undefined) { + meta.push(() => this.emitDescription(description)); + } + + if (meta.length > 0 && !first) { + this.ensureBlankLine(); + } + + for (const emit of meta) { + emit(); + } + + const nameNeedsBackticks = + jsonName.endsWith("_") || shouldAddBacktick(jsonName); + const nameWithBackticks = nameNeedsBackticks + ? "`" + jsonName + "`" + : jsonName; + this.emitLine( + p.isOptional ? "" : nullableOrOptional ? "" : "@required ", + nameWithBackticks, + " : ", + scalaType(p), + + last ? "" : ",", + ); + + if (meta.length > 0 && !last) { + this.ensureBlankLine(); + } + + first = false; + }); + }); + this.emitClassDefinitionMethods(emitLater); + } + + protected emitClassDefinitionMethods(arrayTypes: ClassProperty[]): void { + this.emitLine("}"); + arrayTypes.forEach((p) => { + function ignore(_: T): void { + return; + } + + matchCompoundType( + p.type, + (at) => { + this.emitLine([ + "list ", + this.scalaType(at, true), + "{ member: ", + this.scalaType(at.items, true), + "}", + ]); + }, + ignore, + (mt) => { + this.emitLine([ + "map ", + this.scalaType(mt, true), + "{ key: String , value: ", + this.scalaType(mt.values, true), + "}", + ]); + }, + ignore, + ignore, + ); + }); + } + + protected emitEnumDefinition(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + this.ensureBlankLine(); + this.emitItem(["enum ", enumName, " { "]); + let count = e.cases.size; + + this.forEachEnumCase(e, "none", (name, jsonName) => { + // if (!(jsonName == "")) { + /* const backticks = + shouldAddBacktick(jsonName) || + jsonName.includes(" ") || + !isNaN(parseInt(jsonName.charAt(0))) + if (backticks) {this.emitItem("`")} else */ + this.emitLine(); + + this.emitItem([name, ' = "', jsonName, '"']); + + // if (backticks) {this.emitItem("`")} + if (--count > 0) this.emitItem([","]); + // } else { + // --count + // } + }); + + this.ensureBlankLine(); + this.emitItem(["}"]); + } + + protected emitUnionDefinition(u: UnionType, unionName: Name): void { + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return `_${kind}`; + } + + const emitLater: Type[] = []; + + this.emitDescription(this.descriptionForType(u)); + + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + const theTypes: Sourcelike[] = []; + this.forEachUnionMember(u, nonNulls, "none", null, (_, t) => { + const laterType = t.kind === "array" || t.kind === "map"; + if (laterType) { + emitLater.push(t); + } + + theTypes.push(this.scalaType(t)); + }); + if (maybeNull !== null) { + theTypes.push(this.nameForUnionMember(u, maybeNull)); + } + + this.emitLine(["@untagged union ", unionName, " { "]); + this.indent(() => { + theTypes.forEach((t, i) => { + this.emitLine([String.fromCharCode(i + 65), " : ", t]); + }); + }); + this.emitLine("}"); + this.ensureBlankLine(); + + emitLater.forEach((p) => { + function ignore(_: T): void { + return; + } + + matchCompoundType( + p, + (at) => { + this.emitLine([ + "list ", + this.scalaType(at, true), + "{ member: ", + this.scalaType(at.items, true), + "}", + ]); + }, + ignore, + (mt) => { + this.emitLine([ + "map ", + this.scalaType(mt, true), + "{ key: String , value: ", + this.scalaType(mt.values, true), + "}", + ]); + }, + ignore, + ignore, + ); + }); + } + + protected emitSourceStructure(): void { + this.emitHeader(); + + // Top-level arrays, maps + this.forEachTopLevel("leading", (t, name) => { + if (t instanceof ArrayType) { + this.emitTopLevelArray(t, name); + } else if (t instanceof MapType) { + this.emitTopLevelMap(t, name); + } + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClassDefinition(c, n), + (e, n) => this.emitEnumDefinition(e, n), + (u, n) => this.emitUnionDefinition(u, n), + ); + } +} diff --git a/packages/quicktype-core/src/language/Smithy4s/constants.ts b/packages/quicktype-core/src/language/Smithy4s/constants.ts new file mode 100644 index 000000000..66660e7b6 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/constants.ts @@ -0,0 +1,77 @@ +// Use backticks for param names with symbols +export const invalidSymbols = [ + ":", + "-", + "+", + "!", + "@", + "#", + "%", + "^", + "&", + "*", + "(", + ")", + ">", + "<", + "/", + ";", + "'", + '"', + "{", + "}", + ":", + "~", + "`", + ".", +] as const; + +export const keywords = [ + "abstract", + "case", + "catch", + "do", + "else", + "export", + "false", + "final", + "finally", + "for", + "forSome", + "if", + "implicit", + "import", + "new", + "override", + "package", + "private", + "protected", + "return", + "sealed", + "super", + "this", + "then", + "throw", + "trait", + "try", + "true", + "val", + "var", + "while", + "with", + "yield", + "Any", + "Boolean", + "Double", + "Float", + "Long", + "Int", + "Short", + "System", + "Byte", + "String", + "Array", + "List", + "Map", + "Enum", +] as const; diff --git a/packages/quicktype-core/src/language/Smithy4s/index.ts b/packages/quicktype-core/src/language/Smithy4s/index.ts new file mode 100644 index 000000000..1dea97f90 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/index.ts @@ -0,0 +1,2 @@ +export { SmithyTargetLanguage, smithyOptions } from "./language"; +export { Smithy4sRenderer } from "./Smithy4sRenderer"; diff --git a/packages/quicktype-core/src/language/Smithy4s/language.ts b/packages/quicktype-core/src/language/Smithy4s/language.ts new file mode 100644 index 000000000..38186c8b2 --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/language.ts @@ -0,0 +1,67 @@ +import type { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import type { RenderContext } from "../../Renderer"; +import { + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { assertNever } from "../../support/Support"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { Smithy4sRenderer } from "./Smithy4sRenderer"; + +export enum Framework { + None = "None", +} + +export const smithyOptions = { + // FIXME: why does this exist + framework: new EnumOption( + "framework", + "Serialization framework", + { "just-types": Framework.None } as const, + "just-types", + ), + packageName: new StringOption("package", "Package", "PACKAGE", "quicktype"), +}; + +export const smithyLanguageConfig = { + displayName: "Smithy", + names: ["smithy4a"], + extension: "smithy", +} as const; + +export class SmithyTargetLanguage extends TargetLanguage< + typeof smithyLanguageConfig +> { + public constructor() { + super(smithyLanguageConfig); + } + + public getOptions(): typeof smithyOptions { + return smithyOptions; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): ConvenienceRenderer { + const options = getOptionValues(smithyOptions, untypedOptionValues); + + switch (options.framework) { + case Framework.None: + return new Smithy4sRenderer(this, renderContext, options); + default: + return assertNever(options.framework); + } + } +} diff --git a/packages/quicktype-core/src/language/Smithy4s/utils.ts b/packages/quicktype-core/src/language/Smithy4s/utils.ts new file mode 100644 index 000000000..a3d44bb4c --- /dev/null +++ b/packages/quicktype-core/src/language/Smithy4s/utils.ts @@ -0,0 +1,59 @@ +import { isDigit } from "unicode-properties"; + +import { funPrefixNamer } from "../../Naming"; +import { + allLowerWordStyle, + allUpperWordStyle, + combineWords, + firstUpperWordStyle, + isLetterOrUnderscore, + isNumeric, + legalizeCharacters, + splitIntoWords, +} from "../../support/Strings"; + +import { invalidSymbols, keywords } from "./constants"; + +/** + * Check if given parameter name should be wrapped in a backtick + * @param paramName + */ +export const shouldAddBacktick = (paramName: string): boolean => { + return ( + keywords.some((s) => paramName === s) || + invalidSymbols.some((s) => paramName.includes(s)) || + !isNaN(Number.parseFloat(paramName)) || + !isNaN(Number.parseInt(paramName.charAt(0))) + ); +}; + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function scalaNameStyle(isUpper: boolean, original: string): string { + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + allUpperWordStyle, + "", + isStartCharacter, + ); +} + +export const upperNamingFunction = funPrefixNamer("upper", (s) => + scalaNameStyle(true, s), +); +export const lowerNamingFunction = funPrefixNamer("lower", (s) => + scalaNameStyle(false, s), +); diff --git a/packages/quicktype-core/src/language/Swift.ts b/packages/quicktype-core/src/language/Swift.ts deleted file mode 100644 index 5abe711b2..000000000 --- a/packages/quicktype-core/src/language/Swift.ts +++ /dev/null @@ -1,1460 +0,0 @@ -import { arrayIntercalate } from "collection-utils"; -import { assert, defined } from "../support/Support"; - -import { TargetLanguage } from "../TargetLanguage"; -import { - Type, - ClassType, - EnumType, - UnionType, - ArrayType, - MapType, - TypeKind, - ClassProperty, - TransformedStringTypeKind, - PrimitiveStringTypeKind -} from "../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../TypeUtils"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { BooleanOption, EnumOption, Option, StringOption, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike, maybeAnnotated, modifySource } from "../Source"; -import { anyTypeIssueAnnotation, nullTypeIssueAnnotation } from "../Annotation"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../ConvenienceRenderer"; -import { - legalizeCharacters, - isLetterOrUnderscore, - isNumeric, - isDigit, - utf32ConcatMap, - escapeNonPrintableMapper, - isPrintable, - intToHex, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allLowerWordStyle, - allUpperWordStyle, - camelCase, - addPrefixIfNecessary -} from "../support/Strings"; -import { RenderContext, ForEachPosition } from "../Renderer"; -import { StringTypeMapping } from "../TypeBuilder"; -import { panic } from "../support/Support"; -import { DefaultDateTimeRecognizer, DateTimeRecognizer } from "../DateTime"; -import { acronymOption, acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; - -const MAX_SAMELINE_PROPERTIES = 4; - -export const swiftOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - convenienceInitializers: new BooleanOption("initializers", "Generate initializers and mutators", true), - explicitCodingKeys: new BooleanOption("coding-keys", "Explicit CodingKey values in Codable types", true), - alamofire: new BooleanOption("alamofire", "Alamofire extensions", false), - namedTypePrefix: new StringOption("type-prefix", "Prefix for type names", "PREFIX", "", "secondary"), - useClasses: new EnumOption("struct-or-class", "Structs or classes", [ - ["struct", false], - ["class", true] - ]), - mutableProperties: new BooleanOption("mutable-properties", "Use var instead of let for object properties", false), - acronymStyle: acronymOption(AcronymStyleOptions.Pascal), - dense: new EnumOption( - "density", - "Code density", - [ - ["dense", true], - ["normal", false] - ], - "dense", - "secondary" - ), - linux: new BooleanOption("support-linux", "Support Linux", false, "secondary"), - objcSupport: new BooleanOption( - "objective-c-support", - "Objects inherit from NSObject and @objcMembers is added to classes", - false - ), - optionalEnums: new BooleanOption("optional-enums", "If no matching case is found enum value is set to null", false), - swift5Support: new BooleanOption("swift-5-support", "Renders output in a Swift 5 compatible mode", false), - sendable: new BooleanOption("sendable", "Mark generated models as Sendable", false), - multiFileOutput: new BooleanOption( - "multi-file-output", - "Renders each top-level object in its own Swift file", - false - ), - accessLevel: new EnumOption( - "access-level", - "Access level", - [ - ["internal", "internal"], - ["public", "public"] - ], - "internal", - "secondary" - ), - protocol: new EnumOption( - "protocol", - "Make types implement protocol", - [ - ["none", { equatable: false, hashable: false }], - ["equatable", { equatable: true, hashable: false }], - ["hashable", { equatable: false, hashable: true }] - ], - "none", - "secondary" - ) -}; - -// These are all recognized by Swift as ISO8601 date-times: -// -// 2018-08-14T02:45:50+00:00 -// 2018-08-14T02:45:50+00 -// 2018-08-14T02:45:50+1 -// 2018-08-14T02:45:50+1111 -// 2018-08-14T02:45:50+1111:1:33 -// 2018-08-14T02:45:50-00 -// 2018-08-14T02:45:50z -// 2018-00008-1T002:45:3Z - -const swiftDateTimeRegex = /^\d+-\d+-\d+T\d+:\d+:\d+([zZ]|[+-]\d+(:\d+)?)$/; - -class SwiftDateTimeRecognizer extends DefaultDateTimeRecognizer { - isDateTime(str: string): boolean { - return str.match(swiftDateTimeRegex) !== null; - } -} - -export interface SwiftProperty { - name: Name; - jsonName: string; - parameter: ClassProperty; - position: ForEachPosition; -} - -export class SwiftTargetLanguage extends TargetLanguage { - constructor() { - super("Swift", ["swift", "swift4"], "swift"); - } - - protected getOptions(): Option[] { - return [ - swiftOptions.justTypes, - swiftOptions.useClasses, - swiftOptions.dense, - swiftOptions.convenienceInitializers, - swiftOptions.explicitCodingKeys, - swiftOptions.accessLevel, - swiftOptions.alamofire, - swiftOptions.linux, - swiftOptions.namedTypePrefix, - swiftOptions.protocol, - swiftOptions.acronymStyle, - swiftOptions.objcSupport, - swiftOptions.optionalEnums, - swiftOptions.sendable, - swiftOptions.swift5Support, - swiftOptions.multiFileOutput, - swiftOptions.mutableProperties - ]; - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - mapping.set("date-time", "date-time"); - return mapping; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - get supportsUnionsWithBothNumberTypes(): boolean { - return true; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): SwiftRenderer { - return new SwiftRenderer(this, renderContext, getOptionValues(swiftOptions, untypedOptionValues)); - } - - get dateTimeRecognizer(): DateTimeRecognizer { - return new SwiftDateTimeRecognizer(); - } -} - -const keywords = [ - "await", - "associatedtype", - "class", - "deinit", - "enum", - "extension", - "fileprivate", - "func", - "import", - "init", - "inout", - "internal", - "let", - "open", - "operator", - "private", - "protocol", - "public", - "static", - "struct", - "subscript", - "typealias", - "var", - "break", - "case", - "continue", - "default", - "defer", - "do", - "else", - "fallthrough", - "for", - "guard", - "if", - "in", - "repeat", - "return", - "switch", - "where", - "while", - "as", - "Any", - "catch", - "false", - "is", - "nil", - "rethrows", - "super", - "self", - "Self", - "throw", - "throws", - "true", - "try", - "_", - "associativity", - "convenience", - "dynamic", - "didSet", - "final", - "get", - "infix", - "indirect", - "lazy", - "left", - "mutating", - "nonmutating", - "optional", - "override", - "postfix", - "precedence", - "prefix", - "Protocol", - "required", - "right", - "set", - "Type", - "unowned", - "weak", - "willSet", - "String", - "Int", - "Double", - "Bool", - "Data", - "Date", - "URL", - "CommandLine", - "FileHandle", - "JSONSerialization", - "checkNull", - "removeNSNull", - "nilToNSNull", - "convertArray", - "convertOptional", - "convertDict", - "convertDouble", - "jsonString", - "jsonData" -]; - -function isPartCharacter(codePoint: number): boolean { - return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); -} - -function isStartCharacter(codePoint: number): boolean { - return isPartCharacter(codePoint) && !isDigit(codePoint); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function swiftNameStyle( - prefix: string, - isUpper: boolean, - original: string, - acronymsStyle: (s: string) => string = allUpperWordStyle -): string { - const words = splitIntoWords(original); - const combined = combineWords( - words, - legalizeName, - isUpper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - isUpper ? allUpperWordStyle : allLowerWordStyle, - acronymsStyle, - "", - isStartCharacter - ); - return addPrefixIfNecessary(prefix, combined); -} - -function unicodeEscape(codePoint: number): string { - return "\\u{" + intToHex(codePoint, 0) + "}"; -} - -const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -export class SwiftRenderer extends ConvenienceRenderer { - private _currentFilename: string | undefined; - private _needAny = false; - private _needNull = false; - - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - if (this._options.alamofire) { - return ["DataRequest", ...keywords]; - } - return keywords; - } - - protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { - return { names: ["fromURL", "json"], includeGlobalForbidden: true }; - } - - protected forbiddenForEnumCases(_e: EnumType, _enumName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected forbiddenForUnionMembers(_u: UnionType, _unionName: Name): ForbiddenWordsInfo { - return { names: [], includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("upper", s => - swiftNameStyle(this._options.namedTypePrefix, true, s, acronymStyle(this._options.acronymStyle)) - ); - } - - protected namerForObjectProperty(): Namer { - return this.lowerNamingFunction; - } - - protected makeUnionMemberNamer(): Namer { - return this.lowerNamingFunction; - } - - protected makeEnumCaseNamer(): Namer { - return this.lowerNamingFunction; - } - - protected isImplicitCycleBreaker(t: Type): boolean { - const kind = t.kind; - return kind === "array" || kind === "map"; - } - - protected emitDescriptionBlock(lines: Sourcelike[]): void { - this.emitCommentLines(lines, "/// "); - } - - private emitBlock(line: Sourcelike, f: () => void): void { - this.emitLine(line, " {"); - this.indent(f); - this.emitLine("}"); - } - - private emitBlockWithAccess(line: Sourcelike, f: () => void): void { - this.emitBlock([this.accessLevel, line], f); - } - - private justTypesCase(justTypes: Sourcelike, notJustTypes: Sourcelike): Sourcelike { - if (this._options.justTypes) return justTypes; - else return notJustTypes; - } - - private get lowerNamingFunction() { - return funPrefixNamer("lower", s => swiftNameStyle("", false, s, acronymStyle(this._options.acronymStyle))); - } - - protected swiftPropertyType(p: ClassProperty): Sourcelike { - if (p.isOptional || (this._options.optionalEnums && p.type.kind === "enum")) { - return [this.swiftType(p.type, true, true), "?"]; - } else { - return this.swiftType(p.type, true); - } - } - - protected swiftType(t: Type, withIssues = false, noOptional = false): Sourcelike { - const optional = noOptional ? "" : "?"; - return matchType( - t, - _anyType => { - this._needAny = true; - return maybeAnnotated( - withIssues, - anyTypeIssueAnnotation, - this.justTypesCase(["Any", optional], "JSONAny") - ); - }, - _nullType => { - this._needNull = true; - return maybeAnnotated( - withIssues, - nullTypeIssueAnnotation, - this.justTypesCase("NSNull", ["JSONNull", optional]) - ); - }, - _boolType => "Bool", - _integerType => "Int", - _doubleType => "Double", - _stringType => "String", - arrayType => ["[", this.swiftType(arrayType.items, withIssues), "]"], - classType => this.nameForNamedType(classType), - mapType => ["[String: ", this.swiftType(mapType.values, withIssues), "]"], - enumType => this.nameForNamedType(enumType), - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) return [this.swiftType(nullable, withIssues), optional]; - return this.nameForNamedType(unionType); - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return "Date"; - } else { - return panic(`Transformed string type ${transformedStringType.kind} not supported`); - } - } - ); - } - - protected proposedUnionMemberNameForTypeKind(kind: TypeKind): string | null { - if (kind === "enum") { - return "enumeration"; - } - if (kind === "union") { - return "one_of"; - } - return null; - } - - private renderSingleFileHeaderComments(): void { - this.emitLineOnce("// This file was generated from JSON Schema using quicktype, do not modify it directly."); - this.emitLineOnce("// To parse the JSON, add this file to your project and do:"); - this.emitLineOnce("//"); - this.forEachTopLevel("none", (t, topLevelName) => { - if (this._options.convenienceInitializers && !(t instanceof EnumType)) { - this.emitLineOnce( - "// let ", - modifySource(camelCase, topLevelName), - " = try ", - topLevelName, - "(json)" - ); - } else { - this.emitLineOnce( - "// let ", - modifySource(camelCase, topLevelName), - " = ", - "try? JSONDecoder().decode(", - topLevelName, - ".self, from: jsonData)" - ); - } - }); - } - - private renderHeader(type: Type, name: Name): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else if (!this._options.justTypes) { - if (this._options.multiFileOutput) { - this.emitLineOnce( - "// This file was generated from JSON Schema using quicktype, do not modify it directly." - ); - this.emitLineOnce("// To parse the JSON, add this file to your project and do:"); - this.emitLineOnce("//"); - if (this._options.convenienceInitializers && !(type instanceof EnumType)) { - this.emitLine("// let ", modifySource(camelCase, name), " = try ", name, "(json)"); - } else { - this.emitLine( - "// let ", - modifySource(camelCase, name), - " = ", - "try? newJSONDecoder().decode(", - name, - ".self, from: jsonData)" - ); - } - } - - if (this._options.alamofire) { - this.emitLine("//"); - this.emitLine("// To parse values from Alamofire responses:"); - this.emitLine("//"); - this.emitLine("// Alamofire.request(url).response", name, " { response in"); - this.emitLine("// if let ", modifySource(camelCase, name), " = response.result.value {"); - this.emitLine("// ..."); - this.emitLine("// }"); - this.emitLine("// }"); - } - - if (this._options.protocol.hashable || this._options.protocol.equatable) { - this.emitLine("//"); - this.emitLine("// Hashable or Equatable:"); - this.emitLine( - "// The compiler will not be able to synthesize the implementation of Hashable or Equatable" - ); - this.emitLine( - "// for types that require the use of JSONAny, nor will the implementation of Hashable be" - ); - this.emitLine("// synthesized for types that have collections (such as arrays or dictionaries)."); - } - } - this.ensureBlankLine(); - this.emitLineOnce("import Foundation"); - if (!this._options.justTypes && this._options.alamofire) { - this.emitLineOnce("import Alamofire"); - } - if (this._options.optionalEnums) { - this.emitLineOnce("import OptionallyDecodable // https://github.com/idrougge/OptionallyDecodable"); - } - this.ensureBlankLine(); - } - - private renderTopLevelAlias(t: Type, name: Name): void { - this.emitLine(this.accessLevel, "typealias ", name, " = ", this.swiftType(t, true)); - } - - protected getProtocolsArray(kind: "struct" | "class" | "enum"): string[] { - const protocols: string[] = []; - - // [Michael Fey (@MrRooni), 2019-4-24] Technically NSObject isn't a "protocol" in this instance, but this felt like the best place to slot in this superclass declaration. - const isClass = kind === "class"; - - if (isClass && this._options.objcSupport) { - protocols.push("NSObject"); - } - - if (!this._options.justTypes) { - protocols.push("Codable"); - } - - if (this._options.protocol.hashable) { - protocols.push("Hashable"); - } - - if (this._options.protocol.equatable) { - protocols.push("Equatable"); - } - - if (this._options.sendable && !this._options.mutableProperties && !this._options.objcSupport) { - protocols.push("Sendable"); - } - - return protocols; - } - - private getProtocolString(kind: "struct" | "class" | "enum", baseClass: string | undefined = undefined): Sourcelike { - let protocols = this.getProtocolsArray(kind); - if (baseClass) { - protocols.unshift(baseClass); - } - return protocols.length > 0 ? ": " + protocols.join(", ") : ""; - } - - private getEnumPropertyGroups(c: ClassType) { - type PropertyGroup = { name: Name; label?: string }[]; - - let groups: PropertyGroup[] = []; - let group: PropertyGroup = []; - - this.forEachClassProperty(c, "none", (name, jsonName) => { - const label = stringEscape(jsonName); - const redundant = this.sourcelikeToString(name) === label; - - if (this._options.dense && redundant) { - group.push({ name }); - } else { - if (group.length > 0) { - groups.push(group); - group = []; - } - groups.push([{ name, label }]); - } - }); - - if (group.length > 0) { - groups.push(group); - } - - return groups; - } - - /// Access level with trailing space (e.g. "public "), or empty string - private get accessLevel(): string { - return this._options.accessLevel === "internal" - ? "" // internal is default, so we don't have to emit it - : this._options.accessLevel + " "; - } - - private get objcMembersDeclaration(): string { - if (this._options.objcSupport) { - return "@objcMembers "; - } - - return ""; - } - - /// startFile takes a file name, appends ".swift" to it and sets it as the current filename. - protected startFile(basename: Sourcelike): void { - if (this._options.multiFileOutput === false) { - return; - } - - assert(this._currentFilename === undefined, "Previous file wasn't finished: " + this._currentFilename); - // FIXME: The filenames should actually be Sourcelikes, too - this._currentFilename = `${this.sourcelikeToString(basename)}.swift`; - this.initializeEmitContextForFilename(this._currentFilename); - } - - /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. - protected endFile(): void { - if (this._options.multiFileOutput === false) { - return; - } - - this.finishFile(defined(this._currentFilename)); - this._currentFilename = undefined; - } - - protected propertyLinesDefinition(name: Name, parameter: ClassProperty): Sourcelike { - const useMutableProperties = this._options.mutableProperties; - return [ - this.accessLevel, - useMutableProperties ? "var " : "let ", - name, - ": ", - this.swiftPropertyType(parameter) - ]; - } - - private renderClassDefinition(c: ClassType, className: Name): void { - this.startFile(className); - - this.renderHeader(c, className); - this.emitDescription(this.descriptionForType(c)); - - this.emitMark(this.sourcelikeToString(className), true); - - const isClass = this._options.useClasses || this.isCycleBreakerType(c); - const structOrClass = isClass ? "class" : "struct"; - - if (isClass && this._options.objcSupport) { - // [Michael Fey (@MrRooni), 2019-4-24] Swift 5 or greater, must come before the access declaration for the class. - this.emitItem(this.objcMembersDeclaration); - } - - this.emitBlockWithAccess([structOrClass, " ", className, this.getProtocolString(structOrClass)], () => { - if (this._options.dense) { - let lastProperty: ClassProperty | undefined = undefined; - let lastNames: Name[] = []; - - const emitLastProperty = () => { - if (lastProperty === undefined) return; - - const useMutableProperties = this._options.mutableProperties; - - let sources: Sourcelike[] = [ - [ - this._options.optionalEnums && lastProperty.type.kind === "enum" - ? `@OptionallyDecodable ` - : "", - this.accessLevel, - useMutableProperties || (this._options.optionalEnums && lastProperty.type.kind === "enum") - ? "var " - : "let " - ] - ]; - lastNames.forEach((n, i) => { - if (i > 0) sources.push(", "); - sources.push(n); - }); - sources.push(": "); - sources.push(this.swiftPropertyType(lastProperty)); - this.emitLine(sources); - - lastProperty = undefined; - lastNames = []; - }; - - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const description = this.descriptionForClassProperty(c, jsonName); - if ( - !p.equals(lastProperty) || - lastNames.length >= MAX_SAMELINE_PROPERTIES || - description !== undefined - ) { - emitLastProperty(); - } - if (lastProperty === undefined) { - lastProperty = p; - } - lastNames.push(name); - if (description !== undefined) { - this.emitDescription(description); - emitLastProperty(); - } - }); - emitLastProperty(); - } else { - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const description = this.descriptionForClassProperty(c, jsonName); - const propertyLines = this.propertyLinesDefinition(name, p); - this.emitDescription(description); - this.emitLine(propertyLines); - }); - } - - if (!this._options.justTypes) { - const groups = this.getEnumPropertyGroups(c); - const allPropertiesRedundant = groups.every(group => { - return group.every(p => p.label === undefined); - }); - if (!allPropertiesRedundant && c.getProperties().size > 0) { - this.ensureBlankLine(); - this.emitBlock("enum CodingKeys: String, CodingKey", () => { - for (const group of groups) { - const { name, label } = group[0]; - if (this._options.explicitCodingKeys && label !== undefined) { - this.emitLine("case ", name, ' = "', label, '"'); - } else { - const names = arrayIntercalate( - ", ", - group.map(p => p.name) - ); - this.emitLine("case ", names); - } - } - }); - } - } - - // this main initializer must be defined within the class - // declaration since it assigns let constants - if ( - isClass || - // Public structs need explicit initializers - // https://github.com/quicktype/quicktype/issues/899 - this._options.accessLevel === "public" - ) { - // Make an initializer that initalizes all fields - this.ensureBlankLine(); - let initProperties = this.initializableProperties(c); - let propertiesLines: Sourcelike[] = []; - for (let property of initProperties) { - if (propertiesLines.length > 0) propertiesLines.push(", "); - propertiesLines.push(property.name, ": ", this.swiftPropertyType(property.parameter)); - } - if (this.propertyCount(c) === 0 && this._options.objcSupport) { - this.emitBlockWithAccess(["override init()"], () => { - return ""; - }); - } else { - this.emitBlockWithAccess(["init(", ...propertiesLines, ")"], () => { - for (let property of initProperties) { - this.emitLine("self.", property.name, " = ", property.name); - } - }); - } - } - }); - - if (!this._options.justTypes) { - // FIXME: We emit only the MARK line for top-level-enum.schema - if (this._options.convenienceInitializers) { - this.ensureBlankLine(); - this.emitMark(this.sourcelikeToString(className) + " convenience initializers and mutators"); - this.ensureBlankLine(); - this.emitConvenienceInitializersExtension(c, className); - this.ensureBlankLine(); - } - } - - this.endFile(); - } - - protected initializableProperties(c: ClassType): SwiftProperty[] { - const properties: SwiftProperty[] = []; - this.forEachClassProperty(c, "none", (name, jsonName, parameter, position) => { - const property = { name, jsonName, parameter, position }; - properties.push(property); - }); - return properties; - } - - private emitNewEncoderDecoder(): void { - this.emitBlock("func newJSONDecoder() -> JSONDecoder", () => { - this.emitLine("let decoder = JSONDecoder()"); - if (!this._options.linux) { - this.emitBlock("if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)", () => { - this.emitLine("decoder.dateDecodingStrategy = .iso8601"); - }); - } else { - this.emitMultiline(`decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in - let container = try decoder.singleValueContainer() - let dateStr = try container.decode(String.self) - - let formatter = DateFormatter() - formatter.calendar = Calendar(identifier: .iso8601) - formatter.locale = Locale(identifier: "en_US_POSIX") - formatter.timeZone = TimeZone(secondsFromGMT: 0) - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" - if let date = formatter.date(from: dateStr) { - return date - } - formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" - if let date = formatter.date(from: dateStr) { - return date - } - throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date")) -})`); - } - this.emitLine("return decoder"); - }); - this.ensureBlankLine(); - this.emitBlock("func newJSONEncoder() -> JSONEncoder", () => { - this.emitLine("let encoder = JSONEncoder()"); - if (!this._options.linux) { - this.emitBlock("if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)", () => { - this.emitLine("encoder.dateEncodingStrategy = .iso8601"); - }); - } else { - this.emitMultiline(`let formatter = DateFormatter() -formatter.calendar = Calendar(identifier: .iso8601) -formatter.locale = Locale(identifier: "en_US_POSIX") -formatter.timeZone = TimeZone(secondsFromGMT: 0) -formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" -encoder.dateEncodingStrategy = .formatted(formatter)`); - } - this.emitLine("return encoder"); - }); - } - - private emitConvenienceInitializersExtension(c: ClassType, className: Name): void { - const isClass = this._options.useClasses || this.isCycleBreakerType(c); - const convenience = isClass ? "convenience " : ""; - - this.emitBlockWithAccess(["extension ", className], () => { - if (isClass) { - this.emitBlock("convenience init(data: Data) throws", () => { - if (this.propertyCount(c) > 0) { - this.emitLine("let me = try newJSONDecoder().decode(", this.swiftType(c), ".self, from: data)"); - } else { - this.emitLine("let _ = try newJSONDecoder().decode(", this.swiftType(c), ".self, from: data)"); - } - let args: Sourcelike[] = []; - this.forEachClassProperty(c, "none", name => { - if (args.length > 0) args.push(", "); - args.push(name, ": ", "me.", name); - }); - this.emitLine("self.init(", ...args, ")"); - }); - } else { - this.emitBlock("init(data: Data) throws", () => { - this.emitLine("self = try newJSONDecoder().decode(", this.swiftType(c), ".self, from: data)"); - }); - } - this.ensureBlankLine(); - this.emitBlock( - [convenience, "init(_ json: String, using encoding: String.Encoding = .utf8) throws"], - () => { - this.emitBlock("guard let data = json.data(using: encoding) else", () => { - this.emitLine(`throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)`); - }); - this.emitLine("try self.init(data: data)"); - } - ); - this.ensureBlankLine(); - this.emitBlock([convenience, `init(fromURL url: URL) throws`], () => { - this.emitLine("try self.init(data: try Data(contentsOf: url))"); - }); - - this.ensureBlankLine(); - this.emitConvenienceMutator(c, className); - - // Convenience serializers - this.ensureBlankLine(); - this.emitBlock(`func jsonData() throws -> Data`, () => { - this.emitLine("return try newJSONEncoder().encode(self)"); - }); - this.ensureBlankLine(); - this.emitBlock(`func jsonString(encoding: String.Encoding = .utf8) throws -> String?`, () => { - this.emitLine("return String(data: try self.jsonData(), encoding: encoding)"); - }); - }); - } - - private renderEnumDefinition(e: EnumType, enumName: Name): void { - this.startFile(enumName); - - this.emitLineOnce("import Foundation"); - this.ensureBlankLine(); - - this.emitDescription(this.descriptionForType(e)); - const protocolString = this.getProtocolString("enum", "String"); - - if (this._options.justTypes) { - this.emitBlockWithAccess(["enum ", enumName, protocolString], () => { - this.forEachEnumCase(e, "none", name => { - this.emitLine("case ", name); - }); - }); - } else { - this.emitBlockWithAccess(["enum ", enumName, protocolString], () => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine("case ", name, ' = "', stringEscape(jsonName), '"'); - }); - }); - } - - this.endFile(); - } - - private renderUnionDefinition(u: UnionType, unionName: Name): void { - this.startFile(unionName); - - this.emitLineOnce("import Foundation"); - this.ensureBlankLine(); - - function sortBy(t: Type): string { - const kind = t.kind; - if (kind === "class") return kind; - return "_" + kind; - } - - const renderUnionCase = (t: Type): void => { - this.emitBlock(["if let x = try? container.decode(", this.swiftType(t), ".self)"], () => { - this.emitLine("self = .", this.nameForUnionMember(u, t), "(x)"); - this.emitLine("return"); - }); - }; - - this.emitDescription(this.descriptionForType(u)); - - const indirect = this.isCycleBreakerType(u) ? "indirect " : ""; - const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); - this.emitBlockWithAccess([indirect, "enum ", unionName, this.getProtocolString("enum")], () => { - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - this.emitLine("case ", name, "(", this.swiftType(t), ")"); - }); - if (maybeNull !== null) { - this.emitLine("case ", this.nameForUnionMember(u, maybeNull)); - } - - if (!this._options.justTypes) { - this.ensureBlankLine(); - this.emitBlockWithAccess("init(from decoder: Decoder) throws", () => { - this.emitLine("let container = try decoder.singleValueContainer()"); - const boolMember = u.findMember("bool"); - if (boolMember !== undefined) renderUnionCase(boolMember); - const integerMember = u.findMember("integer"); - if (integerMember !== undefined) renderUnionCase(integerMember); - for (const t of nonNulls) { - if (t.kind === "bool" || t.kind === "integer") continue; - renderUnionCase(t); - } - if (maybeNull !== null) { - this.emitBlock("if container.decodeNil()", () => { - this.emitLine("self = .", this.nameForUnionMember(u, maybeNull)); - this.emitLine("return"); - }); - } - this.emitDecodingError(unionName); - }); - this.ensureBlankLine(); - this.emitBlockWithAccess("func encode(to encoder: Encoder) throws", () => { - this.emitLine("var container = encoder.singleValueContainer()"); - this.emitLine("switch self {"); - this.forEachUnionMember(u, nonNulls, "none", null, (name, _) => { - this.emitLine("case .", name, "(let x):"); - this.indent(() => this.emitLine("try container.encode(x)")); - }); - if (maybeNull !== null) { - this.emitLine("case .", this.nameForUnionMember(u, maybeNull), ":"); - this.indent(() => this.emitLine("try container.encodeNil()")); - } - this.emitLine("}"); - }); - } - }); - this.endFile(); - } - - private emitTopLevelMapAndArrayConvenienceInitializerExtensions(t: Type, name: Name): void { - let extensionSource: Sourcelike; - - if (t instanceof ArrayType) { - extensionSource = ["Array where Element == ", name, ".Element"]; - } else if (t instanceof MapType) { - extensionSource = ["Dictionary where Key == String, Value == ", this.swiftType(t.values)]; - } else { - return; - } - - this.emitBlockWithAccess(["extension ", extensionSource], () => { - this.emitBlock(["init(data: Data) throws"], () => { - this.emitLine("self = try newJSONDecoder().decode(", name, ".self, from: data)"); - }); - this.ensureBlankLine(); - this.emitBlock("init(_ json: String, using encoding: String.Encoding = .utf8) throws", () => { - this.emitBlock("guard let data = json.data(using: encoding) else", () => { - this.emitLine(`throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)`); - }); - this.emitLine("try self.init(data: data)"); - }); - this.ensureBlankLine(); - this.emitBlock(`init(fromURL url: URL) throws`, () => { - this.emitLine("try self.init(data: try Data(contentsOf: url))"); - }); - this.ensureBlankLine(); - this.emitBlock("func jsonData() throws -> Data", () => { - this.emitLine("return try newJSONEncoder().encode(self)"); - }); - this.ensureBlankLine(); - this.emitBlock("func jsonString(encoding: String.Encoding = .utf8) throws -> String?", () => { - this.emitLine("return String(data: try self.jsonData(), encoding: encoding)"); - }); - }); - } - - private emitDecodingError(name: Name): void { - this.emitLine( - "throw DecodingError.typeMismatch(", - name, - '.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ', - name, - '"))' - ); - } - - private emitSupportFunctions4 = (): void => { - this.startFile("JSONSchemaSupport"); - - this.emitLineOnce("import Foundation"); - - this.forEachTopLevel( - "leading", - (t: Type, name: Name) => this.renderTopLevelAlias(t, name), - t => this.namedTypeToNameForTopLevel(t) === undefined - ); - - if (this._options.convenienceInitializers) { - this.ensureBlankLine(); - this.forEachTopLevel("leading-and-interposing", (t: Type, name: Name) => - this.emitTopLevelMapAndArrayConvenienceInitializerExtensions(t, name) - ); - } - - if ((!this._options.justTypes && this._options.convenienceInitializers) || this._options.alamofire) { - this.ensureBlankLine(); - this.emitMark("Helper functions for creating encoders and decoders", true); - this.ensureBlankLine(); - this.emitNewEncoderDecoder(); - } - - if (this._options.alamofire) { - this.ensureBlankLine(); - this.emitMark("Alamofire response handlers", true); - this.ensureBlankLine(); - this.emitAlamofireExtension(); - } - - // This assumes that this method is called after declarations - // are emitted. - if (this._needAny || this._needNull) { - this.ensureBlankLine(); - this.emitMark("Encode/decode helpers", true); - this.ensureBlankLine(); - if (this._options.objcSupport) { - this.emitLine(this.objcMembersDeclaration, this.accessLevel, "class JSONNull: NSObject, Codable {"); - } else { - this.emitLine(this.accessLevel, "class JSONNull: Codable, Hashable {"); - } - this.ensureBlankLine(); - this.emitMultiline(` public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool { - return true - }`); - - if (this._options.objcSupport === false) { - this.ensureBlankLine(); - this.emitMultiline(` public var hashValue: Int { - return 0 - }`); - - if (this._options.swift5Support) { - this.ensureBlankLine(); - this.emitMultiline(` public func hash(into hasher: inout Hasher) { - // No-op - }`); - } - } - - this.ensureBlankLine(); - if (this._options.objcSupport) { - this.emitItem(" override "); - } else { - this.emitItem(" "); - } - this.emitMultiline(`public init() {} - - public required init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - if !container.decodeNil() { - throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull")) - } - } - - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - try container.encodeNil() - } -}`); - } - if (this._needAny) { - this.ensureBlankLine(); - this.emitMultiline(`class JSONCodingKey: CodingKey { - let key: String - - required init?(intValue: Int) { - return nil - } - - required init?(stringValue: String) { - key = stringValue - } - - var intValue: Int? { - return nil - } - - var stringValue: String { - return key - } -}`); - - this.ensureBlankLine(); - if (this._options.objcSupport) { - this.emitLine(this.objcMembersDeclaration, this.accessLevel, "class JSONAny: NSObject, Codable {"); - } else { - this.emitLine(this.accessLevel, "class JSONAny: Codable {"); - } - this.ensureBlankLine(); - this.emitMultiline(` ${this.accessLevel}let value: Any - - static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError { - let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny") - return DecodingError.typeMismatch(JSONAny.self, context) - } - - static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError { - let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny") - return EncodingError.invalidValue(value, context) - } - - static func decode(from container: SingleValueDecodingContainer) throws -> Any { - if let value = try? container.decode(Bool.self) { - return value - } - if let value = try? container.decode(Int64.self) { - return value - } - if let value = try? container.decode(Double.self) { - return value - } - if let value = try? container.decode(String.self) { - return value - } - if container.decodeNil() { - return JSONNull() - } - throw decodingError(forCodingPath: container.codingPath) - } - - static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any { - if let value = try? container.decode(Bool.self) { - return value - } - if let value = try? container.decode(Int64.self) { - return value - } - if let value = try? container.decode(Double.self) { - return value - } - if let value = try? container.decode(String.self) { - return value - } - if let value = try? container.decodeNil() { - if value { - return JSONNull() - } - } - if var container = try? container.nestedUnkeyedContainer() { - return try decodeArray(from: &container) - } - if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self) { - return try decodeDictionary(from: &container) - } - throw decodingError(forCodingPath: container.codingPath) - } - - static func decode(from container: inout KeyedDecodingContainer, forKey key: JSONCodingKey) throws -> Any { - if let value = try? container.decode(Bool.self, forKey: key) { - return value - } - if let value = try? container.decode(Int64.self, forKey: key) { - return value - } - if let value = try? container.decode(Double.self, forKey: key) { - return value - } - if let value = try? container.decode(String.self, forKey: key) { - return value - } - if let value = try? container.decodeNil(forKey: key) { - if value { - return JSONNull() - } - } - if var container = try? container.nestedUnkeyedContainer(forKey: key) { - return try decodeArray(from: &container) - } - if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) { - return try decodeDictionary(from: &container) - } - throw decodingError(forCodingPath: container.codingPath) - } - - static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any] { - var arr: [Any] = [] - while !container.isAtEnd { - let value = try decode(from: &container) - arr.append(value) - } - return arr - } - - static func decodeDictionary(from container: inout KeyedDecodingContainer) throws -> [String: Any] { - var dict = [String: Any]() - for key in container.allKeys { - let value = try decode(from: &container, forKey: key) - dict[key.stringValue] = value - } - return dict - } - - static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws { - for value in array { - if let value = value as? Bool { - try container.encode(value) - } else if let value = value as? Int64 { - try container.encode(value) - } else if let value = value as? Double { - try container.encode(value) - } else if let value = value as? String { - try container.encode(value) - } else if value is JSONNull { - try container.encodeNil() - } else if let value = value as? [Any] { - var container = container.nestedUnkeyedContainer() - try encode(to: &container, array: value) - } else if let value = value as? [String: Any] { - var container = container.nestedContainer(keyedBy: JSONCodingKey.self) - try encode(to: &container, dictionary: value) - } else { - throw encodingError(forValue: value, codingPath: container.codingPath) - } - } - } - - static func encode(to container: inout KeyedEncodingContainer, dictionary: [String: Any]) throws { - for (key, value) in dictionary { - let key = JSONCodingKey(stringValue: key)! - if let value = value as? Bool { - try container.encode(value, forKey: key) - } else if let value = value as? Int64 { - try container.encode(value, forKey: key) - } else if let value = value as? Double { - try container.encode(value, forKey: key) - } else if let value = value as? String { - try container.encode(value, forKey: key) - } else if value is JSONNull { - try container.encodeNil(forKey: key) - } else if let value = value as? [Any] { - var container = container.nestedUnkeyedContainer(forKey: key) - try encode(to: &container, array: value) - } else if let value = value as? [String: Any] { - var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) - try encode(to: &container, dictionary: value) - } else { - throw encodingError(forValue: value, codingPath: container.codingPath) - } - } - } - - static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws { - if let value = value as? Bool { - try container.encode(value) - } else if let value = value as? Int64 { - try container.encode(value) - } else if let value = value as? Double { - try container.encode(value) - } else if let value = value as? String { - try container.encode(value) - } else if value is JSONNull { - try container.encodeNil() - } else { - throw encodingError(forValue: value, codingPath: container.codingPath) - } - } - - public required init(from decoder: Decoder) throws { - if var arrayContainer = try? decoder.unkeyedContainer() { - self.value = try JSONAny.decodeArray(from: &arrayContainer) - } else if var container = try? decoder.container(keyedBy: JSONCodingKey.self) { - self.value = try JSONAny.decodeDictionary(from: &container) - } else { - let container = try decoder.singleValueContainer() - self.value = try JSONAny.decode(from: container) - } - } - - public func encode(to encoder: Encoder) throws { - if let arr = self.value as? [Any] { - var container = encoder.unkeyedContainer() - try JSONAny.encode(to: &container, array: arr) - } else if let dict = self.value as? [String: Any] { - var container = encoder.container(keyedBy: JSONCodingKey.self) - try JSONAny.encode(to: &container, dictionary: dict) - } else { - var container = encoder.singleValueContainer() - try JSONAny.encode(to: &container, value: self.value) - } - } -}`); - } - - this.endFile(); - }; - - private emitConvenienceMutator(c: ClassType, className: Name) { - this.emitLine("func with("); - this.indent(() => { - this.forEachClassProperty(c, "none", (name, _, p, position) => { - this.emitLine( - name, - ": ", - this.swiftPropertyType(p), - "? = nil", - position !== "only" && position !== "last" ? "," : "" - ); - }); - }); - this.emitBlock([") -> ", className], () => { - this.emitLine("return ", className, "("); - this.indent(() => { - this.forEachClassProperty(c, "none", (name, _, _p, position) => { - this.emitLine( - name, - ": ", - name, - " ?? self.", - name, - position !== "only" && position !== "last" ? "," : "" - ); - }); - }); - this.emitLine(")"); - }); - } - - protected emitMark(line: Sourcelike, horizontalLine = false) { - this.emitLine("// MARK:", horizontalLine ? " - " : " ", line); - } - - protected emitSourceStructure(): void { - if (this._options.multiFileOutput === false) { - this.renderSingleFileHeaderComments(); - } - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, className: Name) => this.renderClassDefinition(c, className), - (e: EnumType, enumName: Name) => this.renderEnumDefinition(e, enumName), - (u: UnionType, unionName: Name) => this.renderUnionDefinition(u, unionName) - ); - - if (!this._options.justTypes) { - this.emitSupportFunctions4(); - } - - } - - private emitAlamofireExtension() { - this.ensureBlankLine(); - this.emitBlockWithAccess("extension DataRequest", () => { - this - .emitMultiline(`fileprivate func decodableResponseSerializer() -> DataResponseSerializer { - return DataResponseSerializer { _, response, data, error in - guard error == nil else { return .failure(error!) } - - guard let data = data else { - return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) - } - - return Result { try newJSONDecoder().decode(T.self, from: data) } - } -} - -@discardableResult -fileprivate func responseDecodable(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse) -> Void) -> Self { - return response(queue: queue, responseSerializer: decodableResponseSerializer(), completionHandler: completionHandler) -}`); - this.ensureBlankLine(); - this.forEachTopLevel("leading-and-interposing", (_, name) => { - this.emitLine("@discardableResult"); - this.emitBlock( - [ - "func response", - name, - "(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse<", - name, - ">) -> Void) -> Self" - ], - () => { - this.emitLine(`return responseDecodable(queue: queue, completionHandler: completionHandler)`); - } - ); - }); - }); - } -} diff --git a/packages/quicktype-core/src/language/Swift/SwiftRenderer.ts b/packages/quicktype-core/src/language/Swift/SwiftRenderer.ts new file mode 100644 index 000000000..638c15fca --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/SwiftRenderer.ts @@ -0,0 +1,1550 @@ +import { arrayIntercalate } from "collection-utils"; + +import { + anyTypeIssueAnnotation, + nullTypeIssueAnnotation, +} from "../../Annotation"; +import { + ConvenienceRenderer, + type ForbiddenWordsInfo, +} from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { type Sourcelike, maybeAnnotated, modifySource } from "../../Source"; +import { acronymStyle } from "../../support/Acronyms"; +import { camelCase } from "../../support/Strings"; +import { assert, defined, panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + type ClassType, + EnumType, + MapType, + type Type, + type TypeKind, + type UnionType, +} from "../../Type"; +import { + matchType, + nullableFromUnion, + removeNullFromUnion, +} from "../../Type/TypeUtils"; + +import { keywords } from "./constants"; +import type { swiftOptions } from "./language"; +import { + MAX_SAMELINE_PROPERTIES, + type SwiftProperty, + stringEscape, + swiftNameStyle, +} from "./utils"; + +export class SwiftRenderer extends ConvenienceRenderer { + private _currentFilename: string | undefined; + + private _needAny = false; + + private _needNull = false; + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): readonly string[] { + if (this._options.alamofire) { + return ["DataRequest", ...keywords] as const; + } + + return keywords; + } + + protected forbiddenForObjectProperties( + _c: ClassType, + _classNamed: Name, + ): ForbiddenWordsInfo { + return { names: ["fromURL", "json"], includeGlobalForbidden: true }; + } + + protected forbiddenForEnumCases( + _e: EnumType, + _enumName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected forbiddenForUnionMembers( + _u: UnionType, + _unionName: Name, + ): ForbiddenWordsInfo { + return { names: [], includeGlobalForbidden: true }; + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("upper", (s) => + swiftNameStyle( + this._options.namedTypePrefix, + true, + s, + acronymStyle(this._options.acronymStyle), + ), + ); + } + + protected namerForObjectProperty(): Namer { + return this.lowerNamingFunction; + } + + protected makeUnionMemberNamer(): Namer { + return this.lowerNamingFunction; + } + + protected makeEnumCaseNamer(): Namer { + return this.lowerNamingFunction; + } + + protected isImplicitCycleBreaker(t: Type): boolean { + const kind = t.kind; + return kind === "array" || kind === "map"; + } + + protected emitDescriptionBlock(lines: Sourcelike[]): void { + this.emitCommentLines(lines, { lineStart: "/// " }); + } + + private emitBlock(line: Sourcelike, f: () => void): void { + this.emitLine(line, " {"); + this.indent(f); + this.emitLine("}"); + } + + private emitBlockWithAccess(line: Sourcelike, f: () => void): void { + this.emitBlock([this.accessLevel, line], f); + } + + private justTypesCase( + justTypes: Sourcelike, + notJustTypes: Sourcelike, + ): Sourcelike { + if (this._options.justTypes) { + return justTypes; + } + + return notJustTypes; + } + + private get lowerNamingFunction(): Namer { + return funPrefixNamer("lower", (s) => + swiftNameStyle( + "", + false, + s, + acronymStyle(this._options.acronymStyle), + ), + ); + } + + protected swiftPropertyType(p: ClassProperty): Sourcelike { + if ( + p.isOptional || + (this._options.optionalEnums && p.type.kind === "enum") + ) { + return [this.swiftType(p.type, true, true), "?"]; + } + + return this.swiftType(p.type, true); + } + + protected swiftType( + t: Type, + withIssues = false, + noOptional = false, + ): Sourcelike { + const optional = noOptional ? "" : "?"; + return matchType( + t, + (_anyType) => { + this._needAny = true; + return maybeAnnotated( + withIssues, + anyTypeIssueAnnotation, + this.justTypesCase(["Any", optional], "JSONAny"), + ); + }, + (_nullType) => { + this._needNull = true; + return maybeAnnotated( + withIssues, + nullTypeIssueAnnotation, + this.justTypesCase("NSNull", ["JSONNull", optional]), + ); + }, + (_boolType) => "Bool", + (_integerType) => "Int", + (_doubleType) => "Double", + (_stringType) => "String", + (arrayType) => [ + "[", + this.swiftType(arrayType.items, withIssues), + "]", + ], + (classType) => this.nameForNamedType(classType), + (mapType) => [ + "[String: ", + this.swiftType(mapType.values, withIssues), + "]", + ], + (enumType) => this.nameForNamedType(enumType), + (unionType) => { + const nullable = nullableFromUnion(unionType); + if (nullable !== null) + return [this.swiftType(nullable, withIssues), optional]; + return this.nameForNamedType(unionType); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return "Date"; + } + + return panic( + `Transformed string type ${transformedStringType.kind} not supported`, + ); + }, + ); + } + + protected proposedUnionMemberNameForTypeKind( + kind: TypeKind, + ): string | null { + if (kind === "enum") { + return "enumeration"; + } + + if (kind === "union") { + return "one_of"; + } + + return null; + } + + private renderSingleFileHeaderComments(): void { + this.emitLineOnce( + "// This file was generated from JSON Schema using quicktype, do not modify it directly.", + ); + this.emitLineOnce( + "// To parse the JSON, add this file to your project and do:", + ); + this.emitLineOnce("//"); + this.forEachTopLevel("none", (t, topLevelName) => { + if ( + this._options.convenienceInitializers && + !(t instanceof EnumType) + ) { + this.emitLineOnce( + "// let ", + modifySource(camelCase, topLevelName), + " = try ", + topLevelName, + "(json)", + ); + } else { + this.emitLineOnce( + "// let ", + modifySource(camelCase, topLevelName), + " = ", + "try? JSONDecoder().decode(", + topLevelName, + ".self, from: jsonData)", + ); + } + }); + } + + private renderHeader(type: Type, name: Name): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } else if (!this._options.justTypes) { + if (this._options.multiFileOutput) { + this.emitLineOnce( + "// This file was generated from JSON Schema using quicktype, do not modify it directly.", + ); + this.emitLineOnce( + "// To parse the JSON, add this file to your project and do:", + ); + this.emitLineOnce("//"); + if ( + this._options.convenienceInitializers && + !(type instanceof EnumType) + ) { + this.emitLine( + "// let ", + modifySource(camelCase, name), + " = try ", + name, + "(json)", + ); + } else { + this.emitLine( + "// let ", + modifySource(camelCase, name), + " = ", + "try? newJSONDecoder().decode(", + name, + ".self, from: jsonData)", + ); + } + } + + if (this._options.alamofire) { + this.emitLine("//"); + this.emitLine("// To parse values from Alamofire responses:"); + this.emitLine("//"); + this.emitLine( + "// Alamofire.request(url).response", + name, + " { response in", + ); + this.emitLine( + "// if let ", + modifySource(camelCase, name), + " = response.result.value {", + ); + this.emitLine("// ..."); + this.emitLine("// }"); + this.emitLine("// }"); + } + + if ( + this._options.protocol.hashable || + this._options.protocol.equatable + ) { + this.emitLine("//"); + this.emitLine("// Hashable or Equatable:"); + this.emitLine( + "// The compiler will not be able to synthesize the implementation of Hashable or Equatable", + ); + this.emitLine( + "// for types that require the use of JSONAny, nor will the implementation of Hashable be", + ); + this.emitLine( + "// synthesized for types that have collections (such as arrays or dictionaries).", + ); + } + } + + this.ensureBlankLine(); + this.emitLineOnce("import Foundation"); + if (!this._options.justTypes && this._options.alamofire) { + this.emitLineOnce("import Alamofire"); + } + + if (this._options.optionalEnums) { + this.emitLineOnce( + "import OptionallyDecodable // https://github.com/idrougge/OptionallyDecodable", + ); + } + + this.ensureBlankLine(); + } + + private renderTopLevelAlias(t: Type, name: Name): void { + this.emitLine( + this.accessLevel, + "typealias ", + name, + " = ", + this.swiftType(t, true), + ); + } + + protected getProtocolsArray(kind: "struct" | "class" | "enum"): string[] { + const protocols: string[] = []; + + // [Michael Fey (@MrRooni), 2019-4-24] Technically NSObject isn't a "protocol" in this instance, but this felt like the best place to slot in this superclass declaration. + const isClass = kind === "class"; + + if (isClass && this._options.objcSupport) { + protocols.push("NSObject"); + } + + if (!this._options.justTypes) { + protocols.push("Codable"); + } + + if (this._options.protocol.hashable) { + protocols.push("Hashable"); + } + + if (this._options.protocol.equatable) { + protocols.push("Equatable"); + } + + if ( + this._options.sendable && + (!this._options.mutableProperties || !isClass) && + !this._options.objcSupport + ) { + protocols.push("Sendable"); + } + + return protocols; + } + + private getProtocolString( + kind: "struct" | "class" | "enum", + baseClass: string | undefined = undefined, + ): Sourcelike { + const protocols = this.getProtocolsArray(kind); + if (baseClass) { + protocols.unshift(baseClass); + } + + return protocols.length > 0 ? `: ${protocols.join(", ")}` : ""; + } + + private getEnumPropertyGroups(c: ClassType): typeof groups { + type PropertyGroup = Array<{ label?: string; name: Name }>; + + const groups: PropertyGroup[] = []; + let group: PropertyGroup = []; + + this.forEachClassProperty(c, "none", (name, jsonName) => { + const label = stringEscape(jsonName); + const redundant = this.sourcelikeToString(name) === label; + + if (this._options.dense && redundant) { + group.push({ name }); + } else { + if (group.length > 0) { + groups.push(group); + group = []; + } + + groups.push([{ name, label }]); + } + }); + + if (group.length > 0) { + groups.push(group); + } + + return groups; + } + + /// Access level with trailing space (e.g. "public "), or empty string + private get accessLevel(): string { + return this._options.accessLevel === "internal" + ? "" // internal is default, so we don't have to emit it + : this._options.accessLevel + " "; + } + + private get objcMembersDeclaration(): string { + if (this._options.objcSupport) { + return "@objcMembers "; + } + + return ""; + } + + /// startFile takes a file name, appends ".swift" to it and sets it as the current filename. + protected startFile(basename: Sourcelike): void { + if (this._options.multiFileOutput === false) { + return; + } + + assert( + this._currentFilename === undefined, + `Previous file wasn't finished: ${this._currentFilename}`, + ); + // FIXME: The filenames should actually be Sourcelikes, too + this._currentFilename = `${this.sourcelikeToString(basename)}.swift`; + this.initializeEmitContextForFilename(this._currentFilename); + } + + /// endFile pushes the current file name onto the collection of finished files and then resets the current file name. These finished files are used in index.ts to write the output. + protected endFile(): void { + if (this._options.multiFileOutput === false) { + return; + } + + this.finishFile(defined(this._currentFilename)); + this._currentFilename = undefined; + } + + protected propertyLinesDefinition( + name: Name, + parameter: ClassProperty, + ): Sourcelike { + const useMutableProperties = this._options.mutableProperties; + return [ + this.accessLevel, + useMutableProperties ? "var " : "let ", + name, + ": ", + this.swiftPropertyType(parameter), + ]; + } + + private renderClassDefinition(c: ClassType, className: Name): void { + this.startFile(className); + + this.renderHeader(c, className); + this.emitDescription(this.descriptionForType(c)); + + this.emitMark(this.sourcelikeToString(className), true); + + const isClass = this._options.useClasses || this.isCycleBreakerType(c); + const structOrClass = isClass ? "class" : "struct"; + + if (isClass && this._options.objcSupport) { + // [Michael Fey (@MrRooni), 2019-4-24] Swift 5 or greater, must come before the access declaration for the class. + this.emitItem(this.objcMembersDeclaration); + } + + this.emitBlockWithAccess( + [ + structOrClass, + " ", + className, + this.getProtocolString(structOrClass), + ], + () => { + if (this._options.dense) { + let lastProperty: ClassProperty | undefined = undefined; + let lastNames: Name[] = []; + + const emitLastProperty = (): void => { + if (lastProperty === undefined) return; + + const useMutableProperties = + this._options.mutableProperties; + + const sources: Sourcelike[] = [ + [ + this._options.optionalEnums && + lastProperty.type.kind === "enum" + ? "@OptionallyDecodable " + : "", + this.accessLevel, + useMutableProperties || + (this._options.optionalEnums && + lastProperty.type.kind === "enum") + ? "var " + : "let ", + ], + ]; + lastNames.forEach((n, i) => { + if (i > 0) sources.push(", "); + sources.push(n); + }); + sources.push(": "); + sources.push(this.swiftPropertyType(lastProperty)); + this.emitLine(sources); + + lastProperty = undefined; + lastNames = []; + }; + + this.forEachClassProperty( + c, + "none", + (name, jsonName, p) => { + const description = + this.descriptionForClassProperty(c, jsonName); + if ( + (lastProperty && !p.equals(lastProperty)) || + lastNames.length >= MAX_SAMELINE_PROPERTIES || + description !== undefined + ) { + emitLastProperty(); + } + + if (lastProperty === undefined) { + lastProperty = p; + } + + lastNames.push(name); + if (description !== undefined) { + this.emitDescription(description); + emitLastProperty(); + } + }, + ); + emitLastProperty(); + } else { + this.forEachClassProperty( + c, + "none", + (name, jsonName, p) => { + const description = + this.descriptionForClassProperty(c, jsonName); + const propertyLines = this.propertyLinesDefinition( + name, + p, + ); + this.emitDescription(description); + this.emitLine(propertyLines); + }, + ); + } + + if (!this._options.justTypes) { + const groups = this.getEnumPropertyGroups(c); + const allPropertiesRedundant = groups.every((group) => { + return group.every((p) => p.label === undefined); + }); + if (!allPropertiesRedundant && c.getProperties().size > 0) { + this.ensureBlankLine(); + let enumDeclaration = this.accessLevel; + enumDeclaration += "enum CodingKeys: String, CodingKey"; + if ( + this._options.codingKeysProtocol && + this._options.codingKeysProtocol.length > 0 + ) { + enumDeclaration += ", "; + enumDeclaration += this._options.codingKeysProtocol; + } + + this.emitBlock(enumDeclaration, () => { + for (const group of groups) { + const { name, label } = group[0]; + if ( + this._options.explicitCodingKeys && + label !== undefined + ) { + this.emitLine( + "case ", + name, + ' = "', + label, + '"', + ); + } else { + const names = arrayIntercalate( + ", ", + group.map((p) => p.name), + ); + this.emitLine("case ", names); + } + } + }); + } + } + + // this main initializer must be defined within the class + // declaration since it assigns let constants + if ( + isClass || + // Public structs need explicit initializers + // https://github.com/quicktype/quicktype/issues/899 + this._options.accessLevel === "public" + ) { + // Make an initializer that initalizes all fields + this.ensureBlankLine(); + const initProperties = this.initializableProperties(c); + const propertiesLines: Sourcelike[] = []; + for (const property of initProperties) { + if (propertiesLines.length > 0) + propertiesLines.push(", "); + propertiesLines.push( + property.name, + ": ", + this.swiftPropertyType(property.parameter), + ); + } + + if ( + this.propertyCount(c) === 0 && + this._options.objcSupport + ) { + this.emitBlockWithAccess(["override init()"], () => { + return ""; + }); + } else { + this.emitBlockWithAccess( + ["init(", ...propertiesLines, ")"], + () => { + for (const property of initProperties) { + this.emitLine( + "self.", + property.name, + " = ", + property.name, + ); + } + }, + ); + } + } + }, + ); + + if (!this._options.justTypes) { + // FIXME: We emit only the MARK line for top-level-enum.schema + if (this._options.convenienceInitializers) { + this.ensureBlankLine(); + this.emitMark( + this.sourcelikeToString(className) + + " convenience initializers and mutators", + ); + this.ensureBlankLine(); + this.emitConvenienceInitializersExtension(c, className); + this.ensureBlankLine(); + } + } + + this.endFile(); + } + + protected initializableProperties(c: ClassType): SwiftProperty[] { + const properties: SwiftProperty[] = []; + this.forEachClassProperty( + c, + "none", + (name, jsonName, parameter, position) => { + const property = { name, jsonName, parameter, position }; + properties.push(property); + }, + ); + return properties; + } + + private emitNewEncoderDecoder(): void { + this.emitBlock("func newJSONDecoder() -> JSONDecoder", () => { + this.emitLine("let decoder = JSONDecoder()"); + if (!this._options.linux) { + this.emitBlock( + "if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)", + () => { + this.emitLine( + "decoder.dateDecodingStrategy = .iso8601", + ); + }, + ); + } else { + this.emitMultiline(`decoder.dateDecodingStrategy = .custom({ (decoder) -> Date in + let container = try decoder.singleValueContainer() + let dateStr = try container.decode(String.self) + + let formatter = DateFormatter() + formatter.calendar = Calendar(identifier: .iso8601) + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(secondsFromGMT: 0) + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX" + if let date = formatter.date(from: dateStr) { + return date + } + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" + if let date = formatter.date(from: dateStr) { + return date + } + throw DecodingError.typeMismatch(Date.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Could not decode date")) +})`); + } + + this.emitLine("return decoder"); + }); + this.ensureBlankLine(); + this.emitBlock("func newJSONEncoder() -> JSONEncoder", () => { + this.emitLine("let encoder = JSONEncoder()"); + if (!this._options.linux) { + this.emitBlock( + "if #available(iOS 10.0, OSX 10.12, tvOS 10.0, watchOS 3.0, *)", + () => { + this.emitLine( + "encoder.dateEncodingStrategy = .iso8601", + ); + }, + ); + } else { + this.emitMultiline(`let formatter = DateFormatter() +formatter.calendar = Calendar(identifier: .iso8601) +formatter.locale = Locale(identifier: "en_US_POSIX") +formatter.timeZone = TimeZone(secondsFromGMT: 0) +formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX" +encoder.dateEncodingStrategy = .formatted(formatter)`); + } + + this.emitLine("return encoder"); + }); + } + + private emitConvenienceInitializersExtension( + c: ClassType, + className: Name, + ): void { + const isClass = this._options.useClasses || this.isCycleBreakerType(c); + const convenience = isClass ? "convenience " : ""; + + this.emitBlockWithAccess(["extension ", className], () => { + if (isClass) { + this.emitBlock("convenience init(data: Data) throws", () => { + if (this.propertyCount(c) > 0) { + this.emitLine( + "let me = try newJSONDecoder().decode(", + this.swiftType(c), + ".self, from: data)", + ); + } else { + this.emitLine( + "let _ = try newJSONDecoder().decode(", + this.swiftType(c), + ".self, from: data)", + ); + } + + const args: Sourcelike[] = []; + this.forEachClassProperty(c, "none", (name) => { + if (args.length > 0) args.push(", "); + args.push(name, ": ", "me.", name); + }); + this.emitLine("self.init(", ...args, ")"); + }); + } else { + this.emitBlock("init(data: Data) throws", () => { + this.emitLine( + "self = try newJSONDecoder().decode(", + this.swiftType(c), + ".self, from: data)", + ); + }); + } + + this.ensureBlankLine(); + this.emitBlock( + [ + convenience, + "init(_ json: String, using encoding: String.Encoding = .utf8) throws", + ], + () => { + this.emitBlock( + "guard let data = json.data(using: encoding) else", + () => { + this.emitLine( + 'throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)', + ); + }, + ); + this.emitLine("try self.init(data: data)"); + }, + ); + this.ensureBlankLine(); + this.emitBlock( + [convenience, "init(fromURL url: URL) throws"], + () => { + this.emitLine( + "try self.init(data: try Data(contentsOf: url))", + ); + }, + ); + + this.ensureBlankLine(); + this.emitConvenienceMutator(c, className); + + // Convenience serializers + this.ensureBlankLine(); + this.emitBlock("func jsonData() throws -> Data", () => { + this.emitLine("return try newJSONEncoder().encode(self)"); + }); + this.ensureBlankLine(); + this.emitBlock( + "func jsonString(encoding: String.Encoding = .utf8) throws -> String?", + () => { + this.emitLine( + "return String(data: try self.jsonData(), encoding: encoding)", + ); + }, + ); + }); + } + + private renderEnumDefinition(e: EnumType, enumName: Name): void { + this.startFile(enumName); + + this.emitLineOnce("import Foundation"); + this.ensureBlankLine(); + + this.emitDescription(this.descriptionForType(e)); + const protocolString = this.getProtocolString("enum", "String"); + + if (this._options.justTypes) { + this.emitBlockWithAccess( + ["enum ", enumName, protocolString], + () => { + this.forEachEnumCase(e, "none", (name) => { + this.emitLine("case ", name); + }); + }, + ); + } else { + this.emitBlockWithAccess( + ["enum ", enumName, protocolString], + () => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine( + "case ", + name, + ' = "', + stringEscape(jsonName), + '"', + ); + }); + }, + ); + } + + this.endFile(); + } + + private renderUnionDefinition(u: UnionType, unionName: Name): void { + this.startFile(unionName); + + this.emitLineOnce("import Foundation"); + this.ensureBlankLine(); + + function sortBy(t: Type): string { + const kind = t.kind; + if (kind === "class") return kind; + return `_${kind}`; + } + + const renderUnionCase = (t: Type): void => { + this.emitBlock( + [ + "if let x = try? container.decode(", + this.swiftType(t), + ".self)", + ], + () => { + this.emitLine( + "self = .", + this.nameForUnionMember(u, t), + "(x)", + ); + this.emitLine("return"); + }, + ); + }; + + this.emitDescription(this.descriptionForType(u)); + + const indirect = this.isCycleBreakerType(u) ? "indirect " : ""; + const [maybeNull, nonNulls] = removeNullFromUnion(u, sortBy); + this.emitBlockWithAccess( + [indirect, "enum ", unionName, this.getProtocolString("enum")], + () => { + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (name, t) => { + this.emitLine( + "case ", + name, + "(", + this.swiftType(t), + ")", + ); + }, + ); + if (maybeNull !== null) { + this.emitLine( + "case ", + this.nameForUnionMember(u, maybeNull), + ); + } + + if (!this._options.justTypes) { + this.ensureBlankLine(); + this.emitBlockWithAccess( + "init(from decoder: Decoder) throws", + () => { + this.emitLine( + "let container = try decoder.singleValueContainer()", + ); + const boolMember = u.findMember("bool"); + if (boolMember !== undefined) + renderUnionCase(boolMember); + const integerMember = u.findMember("integer"); + if (integerMember !== undefined) + renderUnionCase(integerMember); + for (const t of nonNulls) { + if (t.kind === "bool" || t.kind === "integer") + continue; + renderUnionCase(t); + } + + if (maybeNull !== null) { + this.emitBlock( + "if container.decodeNil()", + () => { + this.emitLine( + "self = .", + this.nameForUnionMember( + u, + maybeNull, + ), + ); + this.emitLine("return"); + }, + ); + } + + this.emitDecodingError(unionName); + }, + ); + this.ensureBlankLine(); + this.emitBlockWithAccess( + "func encode(to encoder: Encoder) throws", + () => { + this.emitLine( + "var container = encoder.singleValueContainer()", + ); + this.emitLine("switch self {"); + this.forEachUnionMember( + u, + nonNulls, + "none", + null, + (name, _) => { + this.emitLine("case .", name, "(let x):"); + this.indent(() => + this.emitLine( + "try container.encode(x)", + ), + ); + }, + ); + if (maybeNull !== null) { + this.emitLine( + "case .", + this.nameForUnionMember(u, maybeNull), + ":", + ); + this.indent(() => + this.emitLine("try container.encodeNil()"), + ); + } + + this.emitLine("}"); + }, + ); + } + }, + ); + this.endFile(); + } + + private emitTopLevelMapAndArrayConvenienceInitializerExtensions( + t: Type, + name: Name, + ): void { + let extensionSource: Sourcelike; + + if (t instanceof ArrayType) { + extensionSource = ["Array where Element == ", name, ".Element"]; + } else if (t instanceof MapType) { + extensionSource = [ + "Dictionary where Key == String, Value == ", + this.swiftType(t.values), + ]; + } else { + return; + } + + this.emitBlockWithAccess(["extension ", extensionSource], () => { + this.emitBlock(["init(data: Data) throws"], () => { + this.emitLine( + "self = try newJSONDecoder().decode(", + name, + ".self, from: data)", + ); + }); + this.ensureBlankLine(); + this.emitBlock( + "init(_ json: String, using encoding: String.Encoding = .utf8) throws", + () => { + this.emitBlock( + "guard let data = json.data(using: encoding) else", + () => { + this.emitLine( + 'throw NSError(domain: "JSONDecoding", code: 0, userInfo: nil)', + ); + }, + ); + this.emitLine("try self.init(data: data)"); + }, + ); + this.ensureBlankLine(); + this.emitBlock("init(fromURL url: URL) throws", () => { + this.emitLine("try self.init(data: try Data(contentsOf: url))"); + }); + this.ensureBlankLine(); + this.emitBlock("func jsonData() throws -> Data", () => { + this.emitLine("return try newJSONEncoder().encode(self)"); + }); + this.ensureBlankLine(); + this.emitBlock( + "func jsonString(encoding: String.Encoding = .utf8) throws -> String?", + () => { + this.emitLine( + "return String(data: try self.jsonData(), encoding: encoding)", + ); + }, + ); + }); + } + + private emitDecodingError(name: Name): void { + this.emitLine( + "throw DecodingError.typeMismatch(", + name, + '.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for ', + name, + '"))', + ); + } + + private readonly emitSupportFunctions4 = (): void => { + this.startFile("JSONSchemaSupport"); + + this.emitLineOnce("import Foundation"); + + this.forEachTopLevel( + "leading", + (t: Type, name: Name) => this.renderTopLevelAlias(t, name), + (t) => this.namedTypeToNameForTopLevel(t) === undefined, + ); + + if (this._options.convenienceInitializers) { + this.ensureBlankLine(); + this.forEachTopLevel( + "leading-and-interposing", + (t: Type, name: Name) => + this.emitTopLevelMapAndArrayConvenienceInitializerExtensions( + t, + name, + ), + ); + } + + if ( + (!this._options.justTypes && + this._options.convenienceInitializers) || + this._options.alamofire + ) { + this.ensureBlankLine(); + this.emitMark( + "Helper functions for creating encoders and decoders", + true, + ); + this.ensureBlankLine(); + this.emitNewEncoderDecoder(); + } + + if (this._options.alamofire) { + this.ensureBlankLine(); + this.emitMark("Alamofire response handlers", true); + this.ensureBlankLine(); + this.emitAlamofireExtension(); + } + + // This assumes that this method is called after declarations + // are emitted. + if (this._needAny || this._needNull) { + this.ensureBlankLine(); + this.emitMark("Encode/decode helpers", true); + this.ensureBlankLine(); + if (this._options.objcSupport) { + this.emitLine( + this.objcMembersDeclaration, + this.accessLevel, + "class JSONNull: NSObject, Codable {", + ); + } else { + this.emitLine( + this.accessLevel, + "class JSONNull: Codable, Hashable {", + ); + } + + this.ensureBlankLine(); + this.emitMultiline(` public static func == (lhs: JSONNull, rhs: JSONNull) -> Bool { + return true + }`); + + if (this._options.objcSupport === false) { + this.ensureBlankLine(); + this.emitMultiline(` public var hashValue: Int { + return 0 + }`); + + if (this._options.swift5Support) { + this.ensureBlankLine(); + this.emitMultiline(` public func hash(into hasher: inout Hasher) { + // No-op + }`); + } + } + + this.ensureBlankLine(); + if (this._options.objcSupport) { + this.emitItem(" override "); + } else { + this.emitItem(" "); + } + + this.emitMultiline(`public init() {} + + public required init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if !container.decodeNil() { + throw DecodingError.typeMismatch(JSONNull.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for JSONNull")) + } + } + + public func encode(to encoder: Encoder) throws { + var container = encoder.singleValueContainer() + try container.encodeNil() + } +}`); + } + + if (this._needAny) { + this.ensureBlankLine(); + this.emitMultiline(`class JSONCodingKey: CodingKey { + let key: String + + required init?(intValue: Int) { + return nil + } + + required init?(stringValue: String) { + key = stringValue + } + + var intValue: Int? { + return nil + } + + var stringValue: String { + return key + } +}`); + + this.ensureBlankLine(); + if (this._options.objcSupport) { + this.emitLine( + this.objcMembersDeclaration, + this.accessLevel, + "class JSONAny: NSObject, Codable {", + ); + } else { + this.emitLine(this.accessLevel, "class JSONAny: Codable {"); + } + + this.ensureBlankLine(); + this.emitMultiline(` ${this.accessLevel}let value: Any + + static func decodingError(forCodingPath codingPath: [CodingKey]) -> DecodingError { + let context = DecodingError.Context(codingPath: codingPath, debugDescription: "Cannot decode JSONAny") + return DecodingError.typeMismatch(JSONAny.self, context) + } + + static func encodingError(forValue value: Any, codingPath: [CodingKey]) -> EncodingError { + let context = EncodingError.Context(codingPath: codingPath, debugDescription: "Cannot encode JSONAny") + return EncodingError.invalidValue(value, context) + } + + static func decode(from container: SingleValueDecodingContainer) throws -> Any { + if let value = try? container.decode(Bool.self) { + return value + } + if let value = try? container.decode(Int64.self) { + return value + } + if let value = try? container.decode(Double.self) { + return value + } + if let value = try? container.decode(String.self) { + return value + } + if container.decodeNil() { + return JSONNull() + } + throw decodingError(forCodingPath: container.codingPath) + } + + static func decode(from container: inout UnkeyedDecodingContainer) throws -> Any { + if let value = try? container.decode(Bool.self) { + return value + } + if let value = try? container.decode(Int64.self) { + return value + } + if let value = try? container.decode(Double.self) { + return value + } + if let value = try? container.decode(String.self) { + return value + } + if let value = try? container.decodeNil() { + if value { + return JSONNull() + } + } + if var container = try? container.nestedUnkeyedContainer() { + return try decodeArray(from: &container) + } + if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self) { + return try decodeDictionary(from: &container) + } + throw decodingError(forCodingPath: container.codingPath) + } + + static func decode(from container: inout KeyedDecodingContainer, forKey key: JSONCodingKey) throws -> Any { + if let value = try? container.decode(Bool.self, forKey: key) { + return value + } + if let value = try? container.decode(Int64.self, forKey: key) { + return value + } + if let value = try? container.decode(Double.self, forKey: key) { + return value + } + if let value = try? container.decode(String.self, forKey: key) { + return value + } + if let value = try? container.decodeNil(forKey: key) { + if value { + return JSONNull() + } + } + if var container = try? container.nestedUnkeyedContainer(forKey: key) { + return try decodeArray(from: &container) + } + if var container = try? container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) { + return try decodeDictionary(from: &container) + } + throw decodingError(forCodingPath: container.codingPath) + } + + static func decodeArray(from container: inout UnkeyedDecodingContainer) throws -> [Any] { + var arr: [Any] = [] + while !container.isAtEnd { + let value = try decode(from: &container) + arr.append(value) + } + return arr + } + + static func decodeDictionary(from container: inout KeyedDecodingContainer) throws -> [String: Any] { + var dict = [String: Any]() + for key in container.allKeys { + let value = try decode(from: &container, forKey: key) + dict[key.stringValue] = value + } + return dict + } + + static func encode(to container: inout UnkeyedEncodingContainer, array: [Any]) throws { + for value in array { + if let value = value as? Bool { + try container.encode(value) + } else if let value = value as? Int64 { + try container.encode(value) + } else if let value = value as? Double { + try container.encode(value) + } else if let value = value as? String { + try container.encode(value) + } else if value is JSONNull { + try container.encodeNil() + } else if let value = value as? [Any] { + var container = container.nestedUnkeyedContainer() + try encode(to: &container, array: value) + } else if let value = value as? [String: Any] { + var container = container.nestedContainer(keyedBy: JSONCodingKey.self) + try encode(to: &container, dictionary: value) + } else { + throw encodingError(forValue: value, codingPath: container.codingPath) + } + } + } + + static func encode(to container: inout KeyedEncodingContainer, dictionary: [String: Any]) throws { + for (key, value) in dictionary { + let key = JSONCodingKey(stringValue: key)! + if let value = value as? Bool { + try container.encode(value, forKey: key) + } else if let value = value as? Int64 { + try container.encode(value, forKey: key) + } else if let value = value as? Double { + try container.encode(value, forKey: key) + } else if let value = value as? String { + try container.encode(value, forKey: key) + } else if value is JSONNull { + try container.encodeNil(forKey: key) + } else if let value = value as? [Any] { + var container = container.nestedUnkeyedContainer(forKey: key) + try encode(to: &container, array: value) + } else if let value = value as? [String: Any] { + var container = container.nestedContainer(keyedBy: JSONCodingKey.self, forKey: key) + try encode(to: &container, dictionary: value) + } else { + throw encodingError(forValue: value, codingPath: container.codingPath) + } + } + } + + static func encode(to container: inout SingleValueEncodingContainer, value: Any) throws { + if let value = value as? Bool { + try container.encode(value) + } else if let value = value as? Int64 { + try container.encode(value) + } else if let value = value as? Double { + try container.encode(value) + } else if let value = value as? String { + try container.encode(value) + } else if value is JSONNull { + try container.encodeNil() + } else { + throw encodingError(forValue: value, codingPath: container.codingPath) + } + } + + public required init(from decoder: Decoder) throws { + if var arrayContainer = try? decoder.unkeyedContainer() { + self.value = try JSONAny.decodeArray(from: &arrayContainer) + } else if var container = try? decoder.container(keyedBy: JSONCodingKey.self) { + self.value = try JSONAny.decodeDictionary(from: &container) + } else { + let container = try decoder.singleValueContainer() + self.value = try JSONAny.decode(from: container) + } + } + + public func encode(to encoder: Encoder) throws { + if let arr = self.value as? [Any] { + var container = encoder.unkeyedContainer() + try JSONAny.encode(to: &container, array: arr) + } else if let dict = self.value as? [String: Any] { + var container = encoder.container(keyedBy: JSONCodingKey.self) + try JSONAny.encode(to: &container, dictionary: dict) + } else { + var container = encoder.singleValueContainer() + try JSONAny.encode(to: &container, value: self.value) + } + } +}`); + } + + this.endFile(); + }; + + private emitConvenienceMutator(c: ClassType, className: Name): void { + this.emitLine("func with("); + this.indent(() => { + this.forEachClassProperty(c, "none", (name, _, p, position) => { + this.emitLine( + name, + ": ", + this.swiftPropertyType(p), + "? = nil", + position !== "only" && position !== "last" ? "," : "", + ); + }); + }); + this.emitBlock([") -> ", className], () => { + this.emitLine("return ", className, "("); + this.indent(() => { + this.forEachClassProperty( + c, + "none", + (name, _, _p, position) => { + this.emitLine( + name, + ": ", + name, + " ?? self.", + name, + position !== "only" && position !== "last" + ? "," + : "", + ); + }, + ); + }); + this.emitLine(")"); + }); + } + + protected emitMark(line: Sourcelike, horizontalLine = false): void { + this.emitLine("// MARK:", horizontalLine ? " - " : " ", line); + } + + protected emitSourceStructure(): void { + if (this._options.multiFileOutput === false) { + this.renderSingleFileHeaderComments(); + } + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, className: Name) => + this.renderClassDefinition(c, className), + (e: EnumType, enumName: Name) => + this.renderEnumDefinition(e, enumName), + (u: UnionType, unionName: Name) => + this.renderUnionDefinition(u, unionName), + ); + + if (!this._options.justTypes) { + this.emitSupportFunctions4(); + } + } + + private emitAlamofireExtension(): void { + this.ensureBlankLine(); + this.emitBlockWithAccess("extension DataRequest", () => { + this.emitMultiline(`fileprivate func decodableResponseSerializer() -> DataResponseSerializer { + return DataResponseSerializer { _, response, data, error in + guard error == nil else { return .failure(error!) } + + guard let data = data else { + return .failure(AFError.responseSerializationFailed(reason: .inputDataNil)) + } + + return Result { try newJSONDecoder().decode(T.self, from: data) } + } +} + +@discardableResult +fileprivate func responseDecodable(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse) -> Void) -> Self { + return response(queue: queue, responseSerializer: decodableResponseSerializer(), completionHandler: completionHandler) +}`); + this.ensureBlankLine(); + this.forEachTopLevel("leading-and-interposing", (_, name) => { + this.emitLine("@discardableResult"); + this.emitBlock( + [ + "func response", + name, + "(queue: DispatchQueue? = nil, completionHandler: @escaping (DataResponse<", + name, + ">) -> Void) -> Self", + ], + () => { + this.emitLine( + "return responseDecodable(queue: queue, completionHandler: completionHandler)", + ); + }, + ); + }); + }); + } +} diff --git a/packages/quicktype-core/src/language/Swift/constants.ts b/packages/quicktype-core/src/language/Swift/constants.ts new file mode 100644 index 000000000..2298d1bd6 --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/constants.ts @@ -0,0 +1,101 @@ +export const keywords = [ + "await", + "associatedtype", + "class", + "deinit", + "enum", + "extension", + "fileprivate", + "func", + "import", + "init", + "inout", + "internal", + "let", + "open", + "operator", + "private", + "protocol", + "public", + "static", + "struct", + "subscript", + "typealias", + "var", + "break", + "case", + "continue", + "default", + "defer", + "do", + "else", + "fallthrough", + "for", + "guard", + "if", + "in", + "repeat", + "return", + "switch", + "where", + "while", + "as", + "Any", + "catch", + "false", + "is", + "nil", + "rethrows", + "super", + "self", + "Self", + "throw", + "throws", + "true", + "try", + "_", + "associativity", + "convenience", + "dynamic", + "didSet", + "final", + "get", + "infix", + "indirect", + "lazy", + "left", + "mutating", + "nonmutating", + "optional", + "override", + "postfix", + "precedence", + "prefix", + "Protocol", + "required", + "right", + "set", + "Type", + "unowned", + "weak", + "willSet", + "String", + "Int", + "Double", + "Bool", + "Data", + "Date", + "URL", + "CommandLine", + "FileHandle", + "JSONSerialization", + "checkNull", + "removeNSNull", + "nilToNSNull", + "convertArray", + "convertOptional", + "convertDict", + "convertDouble", + "jsonString", + "jsonData", +] as const; diff --git a/packages/quicktype-core/src/language/Swift/index.ts b/packages/quicktype-core/src/language/Swift/index.ts new file mode 100644 index 000000000..902d4fff7 --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/index.ts @@ -0,0 +1,2 @@ +export { SwiftTargetLanguage, swiftOptions } from "./language"; +export { SwiftRenderer } from "./SwiftRenderer"; diff --git a/packages/quicktype-core/src/language/Swift/language.ts b/packages/quicktype-core/src/language/Swift/language.ts new file mode 100644 index 000000000..d40d0af10 --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/language.ts @@ -0,0 +1,173 @@ +import type { DateTimeRecognizer } from "../../DateTime"; +import type { RenderContext } from "../../Renderer"; +import { + BooleanOption, + EnumOption, + StringOption, + getOptionValues, +} from "../../RendererOptions"; +import { AcronymStyleOptions, acronymOption } from "../../support/Acronyms"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { SwiftRenderer } from "./SwiftRenderer"; +import { SwiftDateTimeRecognizer } from "./utils"; + +export const swiftOptions = { + justTypes: new BooleanOption("just-types", "Plain types only", false), + convenienceInitializers: new BooleanOption( + "initializers", + "Generate initializers and mutators", + true, + ), + explicitCodingKeys: new BooleanOption( + "coding-keys", + "Explicit CodingKey values in Codable types", + true, + ), + codingKeysProtocol: new StringOption( + "coding-keys-protocol", + "CodingKeys implements protocols", + "protocol1, protocol2...", + "", + "secondary", + ), + alamofire: new BooleanOption("alamofire", "Alamofire extensions", false), + namedTypePrefix: new StringOption( + "type-prefix", + "Prefix for type names", + "PREFIX", + "", + "secondary", + ), + useClasses: new EnumOption( + "struct-or-class", + "Structs or classes", + { + struct: false, + class: true, + } as const, + "struct", + ), + mutableProperties: new BooleanOption( + "mutable-properties", + "Use var instead of let for object properties", + false, + ), + acronymStyle: acronymOption(AcronymStyleOptions.Pascal), + dense: new EnumOption( + "density", + "Code density", + { + dense: true, + normal: false, + } as const, + "dense", + "secondary", + ), + linux: new BooleanOption( + "support-linux", + "Support Linux", + false, + "secondary", + ), + objcSupport: new BooleanOption( + "objective-c-support", + "Objects inherit from NSObject and @objcMembers is added to classes", + false, + ), + optionalEnums: new BooleanOption( + "optional-enums", + "If no matching case is found enum value is set to null", + false, + ), + swift5Support: new BooleanOption( + "swift-5-support", + "Renders output in a Swift 5 compatible mode", + false, + ), + sendable: new BooleanOption( + "sendable", + "Mark generated models as Sendable", + false, + ), + multiFileOutput: new BooleanOption( + "multi-file-output", + "Renders each top-level object in its own Swift file", + false, + ), + accessLevel: new EnumOption( + "access-level", + "Access level", + { + internal: "internal", + public: "public", + } as const, + "internal", + "secondary", + ), + protocol: new EnumOption( + "protocol", + "Make types implement protocol", + { + none: { equatable: false, hashable: false }, + equatable: { equatable: true, hashable: false }, + hashable: { equatable: false, hashable: true }, + } as const, + "none", + "secondary", + ), +}; + +export const swiftLanguageConfig = { + displayName: "Swift", + names: ["swift", "swift4"], + extension: "swift", +} as const; + +export class SwiftTargetLanguage extends TargetLanguage< + typeof swiftLanguageConfig +> { + public constructor() { + super(swiftLanguageConfig); + } + + public getOptions(): typeof swiftOptions { + return swiftOptions; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + mapping.set("date-time", "date-time"); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsUnionsWithBothNumberTypes(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): SwiftRenderer { + return new SwiftRenderer( + this, + renderContext, + getOptionValues(swiftOptions, untypedOptionValues), + ); + } + + public get dateTimeRecognizer(): DateTimeRecognizer { + return new SwiftDateTimeRecognizer(); + } +} diff --git a/packages/quicktype-core/src/language/Swift/utils.ts b/packages/quicktype-core/src/language/Swift/utils.ts new file mode 100644 index 000000000..ee452517b --- /dev/null +++ b/packages/quicktype-core/src/language/Swift/utils.ts @@ -0,0 +1,86 @@ +import { DefaultDateTimeRecognizer } from "../../DateTime"; +import type { Name } from "../../Naming"; +import type { ForEachPosition } from "../../Renderer"; +import { + addPrefixIfNecessary, + allLowerWordStyle, + allUpperWordStyle, + combineWords, + escapeNonPrintableMapper, + firstUpperWordStyle, + intToHex, + isDigit, + isLetterOrUnderscore, + isNumeric, + isPrintable, + legalizeCharacters, + splitIntoWords, + utf32ConcatMap, +} from "../../support/Strings"; +import type { ClassProperty } from "../../Type"; + +export const MAX_SAMELINE_PROPERTIES = 4; + +// These are all recognized by Swift as ISO8601 date-times: +// +// 2018-08-14T02:45:50+00:00 +// 2018-08-14T02:45:50+00 +// 2018-08-14T02:45:50+1 +// 2018-08-14T02:45:50+1111 +// 2018-08-14T02:45:50+1111:1:33 +// 2018-08-14T02:45:50-00 +// 2018-08-14T02:45:50z +// 2018-00008-1T002:45:3Z + +const swiftDateTimeRegex = /^\d+-\d+-\d+T\d+:\d+:\d+([zZ]|[+-]\d+(:\d+)?)$/; + +export class SwiftDateTimeRecognizer extends DefaultDateTimeRecognizer { + public isDateTime(str: string): boolean { + return swiftDateTimeRegex.exec(str) !== null; + } +} + +export interface SwiftProperty { + jsonName: string; + name: Name; + parameter: ClassProperty; + position: ForEachPosition; +} + +function isPartCharacter(codePoint: number): boolean { + return isLetterOrUnderscore(codePoint) || isNumeric(codePoint); +} + +function isStartCharacter(codePoint: number): boolean { + return isPartCharacter(codePoint) && !isDigit(codePoint); +} + +const legalizeName = legalizeCharacters(isPartCharacter); + +export function swiftNameStyle( + prefix: string, + isUpper: boolean, + original: string, + acronymsStyle: (s: string) => string = allUpperWordStyle, +): string { + const words = splitIntoWords(original); + const combined = combineWords( + words, + legalizeName, + isUpper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + isUpper ? allUpperWordStyle : allLowerWordStyle, + acronymsStyle, + "", + isStartCharacter, + ); + return addPrefixIfNecessary(prefix, combined); +} + +function unicodeEscape(codePoint: number): string { + return "\\u{" + intToHex(codePoint, 0) + "}"; +} + +export const stringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, unicodeEscape), +); diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts deleted file mode 100644 index c615add4d..000000000 --- a/packages/quicktype-core/src/language/TypeScriptEffectSchema.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { arrayIntercalate } from "collection-utils"; -import { ClassProperty, EnumType, ObjectType, Type } from "../Type"; -import { matchType } from "../TypeUtils"; -import { funPrefixNamer, Name, Namer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, getOptionValues, Option, OptionValues } from "../RendererOptions"; -import { acronymStyle, AcronymStyleOptions } from "../support/Acronyms"; -import { - allLowerWordStyle, - capitalize, - combineWords, - firstUpperWordStyle, - isLetterOrUnderscore, - splitIntoWords, - stringEscape, - utf16StringEscape -} from "../support/Strings"; -import { TargetLanguage } from "../TargetLanguage"; -import { legalizeName } from "./JavaScript"; -import { Sourcelike } from "../Source"; -import { panic } from "../support/Support"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; - -export const typeScriptEffectSchemaOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false) -}; - -export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return []; - } - - constructor( - displayName: string = "TypeScript Effect Schema", - names: string[] = ["typescript-effect-schema"], - extension: string = "ts" - ) { - super(displayName, names, extension); - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): TypeScriptEffectSchemaRenderer { - return new TypeScriptEffectSchemaRenderer( - this, - renderContext, - getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues) - ); - } -} - -export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; - } - - protected nameStyle(original: string, upper: boolean): string { - const acronyms = acronymStyle(AcronymStyleOptions.Camel); - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, - acronyms, - "", - isLetterOrUnderscore - ); - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("types", s => this.nameStyle(s, true)); - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("properties", s => this.nameStyle(s, true)); - } - - protected namerForObjectProperty(): Namer { - return funPrefixNamer("properties", s => this.nameStyle(s, true)); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); - } - - private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { - return ["import ", lhs, " from ", moduleName, ";"]; - } - - protected emitImports(): void { - this.ensureBlankLine(); - this.emitLine(this.importStatement("* as S", '"@effect/schema/Schema"')); - } - - typeMapTypeForProperty(p: ClassProperty): Sourcelike { - const typeMap = this.typeMapTypeFor(p.type); - return p.isOptional ? ["S.optional(", typeMap, ")"] : typeMap; - } - - typeMapTypeFor(t: Type, required: boolean = true): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { - return ["S.lazy(() => ", this.nameForNamedType(t), ")"]; - } - - const match = matchType( - t, - _anyType => "S.any", - _nullType => "S.null", - _boolType => "S.boolean", - _integerType => "S.number", - _doubleType => "S.number", - _stringType => "S.string", - arrayType => ["S.array(", this.typeMapTypeFor(arrayType.items, false), ")"], - _classType => panic("Should already be handled."), - _mapType => ["S.record(S.string, ", this.typeMapTypeFor(_mapType.values, false), ")"], - _enumType => panic("Should already be handled."), - unionType => { - const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false) - ); - return ["S.union(", ...arrayIntercalate(", ", children), ")"]; - }, - _transformedStringType => { - return "S.string"; - } - ); - - if (required) { - return [match]; - } - - return match; - } - - private emitObject(name: Name, t: ObjectType) { - this.ensureBlankLine(); - if (this._options.justSchema) { - this.emitLine("\nexport const ", name, " = S.struct({"); - } else { - this.emitLine("\nconst ", name, "_ = S.struct({"); - } - this.indent(() => { - this.forEachClassProperty(t, "none", (_, jsonName, property) => { - this.emitLine(`"${utf16StringEscape(jsonName)}"`, ": ", this.typeMapTypeForProperty(property), ","); - }); - }); - this.emitLine("});"); - if (!this._options.justSchema) { - this.emitLine("export interface ", name, " extends S.Schema.To {}"); - this.emitLine( - "export const ", - name, - ": S.Schema, ", - name, - "> = ", - name, - "_;" - ); - } - } - - private emitEnum(e: EnumType, enumName: Name): void { - this.ensureBlankLine(); - this.emitDescription(this.descriptionForType(e)); - this.emitLine("\nexport const ", enumName, " = ", "S.enums({"); - this.indent(() => - this.forEachEnumCase(e, "none", (_, jsonName) => { - const name = stringEscape(jsonName); - this.emitLine('"', name, '": "', name, '",'); - }) - ); - this.emitLine("});"); - if (!this._options.justSchema) { - this.emitLine("export type ", enumName, " = S.Schema.To;"); - } - } - - protected emitSchemas(): void { - this.ensureBlankLine(); - - this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => { - this.emitEnum(u, enumName); - }); - - const order: number[] = []; - const mapKey: Name[] = []; - const mapValue: Sourcelike[][] = []; - this.forEachObject("none", (type: ObjectType, name: Name) => { - mapKey.push(name); - mapValue.push(this.gatherSource(() => this.emitObject(name, type))); - }); - - mapKey.forEach((_, index) => { - // assume first - let ordinal = 0; - - // pull out all names - const source = mapValue[index]; - const names = source.filter(value => value as Name); - - // must be behind all these names - for (let i = 0; i < names.length; i++) { - const depName = names[i]; - - // find this name's ordinal, if it has already been added - for (let j = 0; j < order.length; j++) { - const depIndex = order[j]; - if (mapKey[depIndex] === depName) { - // this is the index of the dependency, so make sure we come after it - ordinal = Math.max(ordinal, depIndex + 1); - } - } - } - - // insert index - order.splice(ordinal, 0, index); - }); - - // now emit ordered source - order.forEach(i => this.emitGatheredSource(mapValue[i])); - } - - protected emitSourceStructure(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } - - this.emitImports(); - this.emitSchemas(); - } -} diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts new file mode 100644 index 000000000..f5d117c34 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/TypeScriptEffectSchemaRenderer.ts @@ -0,0 +1,306 @@ +import { arrayIntercalate } from "collection-utils"; + +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import type { Sourcelike } from "../../Source"; +import { AcronymStyleOptions, acronymStyle } from "../../support/Acronyms"; +import { + allLowerWordStyle, + capitalize, + combineWords, + firstUpperWordStyle, + isLetterOrUnderscore, + splitIntoWords, + stringEscape, + utf16StringEscape, +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + EnumType, + MapType, + type ObjectType, + type Type, +} from "../../Type"; +import { matchType } from "../../Type/TypeUtils"; +import { legalizeName } from "../JavaScript/utils"; + +import type { typeScriptEffectSchemaOptions } from "./language"; + +export class TypeScriptEffectSchemaRenderer extends ConvenienceRenderer { + private emittedObjects = new Set(); + + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + private readonly _options: OptionValues< + typeof typeScriptEffectSchemaOptions + >, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; + } + + protected nameStyle(original: string, upper: boolean): string { + const acronyms = acronymStyle(AcronymStyleOptions.Camel); + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, + acronyms, + "", + isLetterOrUnderscore, + ); + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("types", (s) => this.nameStyle(s, true)); + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer("properties", (s) => this.nameStyle(s, true)); + } + + protected namerForObjectProperty(): Namer { + return funPrefixNamer("properties", (s) => this.nameStyle(s, true)); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("enum-cases", (s) => this.nameStyle(s, false)); + } + + private importStatement( + lhs: Sourcelike, + moduleName: Sourcelike, + ): Sourcelike { + return ["import ", lhs, " from ", moduleName, ";"]; + } + + protected emitImports(): void { + this.ensureBlankLine(); + this.emitLine(this.importStatement("* as S", '"effect/Schema"')); + } + + private typeMapTypeForProperty(p: ClassProperty): Sourcelike { + if (!p.isOptional) { + return this.typeMapTypeFor(p.type); + } + + return ["S.optional(", this.typeMapTypeFor(p.type), ")"]; + } + + private typeMapTypeFor(t: Type, required = true): Sourcelike { + if (t.kind === "class" || t.kind === "object" || t.kind === "enum") { + const name = this.nameForNamedType(t); + if (this.emittedObjects.has(name)) { + return [name]; + } + + return ["S.suspend(() => ", name, ")"]; + } + + const match = matchType( + t, + (_anyType) => "S.Any", + (_nullType) => "S.Null", + (_boolType) => "S.Boolean", + (_integerType) => "S.Number", + (_doubleType) => "S.Number", + (_stringType) => "S.String", + (arrayType) => [ + "S.Array(", + this.typeMapTypeFor(arrayType.items, false), + ")", + ], + (_classType) => panic("Should already be handled."), + (_mapType) => [ + "S.Record({ key: S.String, value: ", + this.typeMapTypeFor(_mapType.values, false), + "})", + ], + (_enumType) => panic("Should already be handled."), + (unionType) => { + const types = Array.from(unionType.getChildren()); + const children: Sourcelike[] = []; + let nullable = false; + for (const type of types) { + if (type.kind === "null") { + nullable = true; + } else { + children.push(this.typeMapTypeFor(type, false)); + } + } + + if (nullable && children.length === 1) { + return ["S.NullOr(", children[0], ")"]; + } + + return [ + "S.Union(", + ...arrayIntercalate(", ", children), + nullable ? ", S.Null)" : ")", + ]; + }, + (_transformedStringType) => { + return "S.String"; + }, + ); + + if (required) { + return [match]; + } + + return match; + } + + private emitObject(name: Name, t: ObjectType): void { + this.emittedObjects.add(name); + this.ensureBlankLine(); + this.emitLine( + "\nexport class ", + name, + " extends S.Class<", + name, + '>("', + name, + '")({', + ); + this.indent(() => { + this.forEachClassProperty(t, "none", (_, jsonName, property) => { + this.emitLine( + `"${utf16StringEscape(jsonName)}"`, + ": ", + this.typeMapTypeForProperty(property), + ",", + ); + }); + }); + this.emitLine("}) {}"); + } + + private emitEnum(e: EnumType, enumName: Name): void { + this.emittedObjects.add(enumName); + this.ensureBlankLine(); + this.emitDescription(this.descriptionForType(e)); + this.emitLine("\nexport const ", enumName, " = ", "S.Literal("); + this.indent(() => + this.forEachEnumCase(e, "none", (_, jsonName) => { + this.emitLine('"', stringEscape(jsonName), '",'); + }), + ); + this.emitLine(");"); + if (!this._options.justSchema) { + this.emitLine( + "export type ", + enumName, + " = S.Schema.Type;", + ); + } + } + + protected walkObjectNames(objectType: ObjectType): Name[] { + const names: Name[] = []; + + const recurse = (type: Type): void => { + if (type.kind === "object" || type.kind === "class") { + names.push(this.nameForNamedType(type)); + this.forEachClassProperty( + type as ObjectType, + "none", + (_, __, prop) => { + recurse(prop.type); + }, + ); + } else if (type instanceof ArrayType) { + recurse(type.items); + } else if (type instanceof MapType) { + recurse(type.values); + } else if (type instanceof EnumType) { + for (const t of type.getChildren()) { + recurse(t); + } + } + }; + + this.forEachClassProperty(objectType, "none", (_, __, prop) => { + recurse(prop.type); + }); + + return names; + } + + protected emitSchemas(): void { + this.ensureBlankLine(); + + this.forEachEnum( + "leading-and-interposing", + (u: EnumType, enumName: Name) => { + this.emitEnum(u, enumName); + }, + ); + + const order: number[] = []; + const mapKey: Name[] = []; + const mapValue: ObjectType[] = []; + this.forEachObject("none", (type: ObjectType, name: Name) => { + mapKey.push(name); + mapValue.push(type); + }); + + mapKey.forEach((_, index) => { + // assume first + let ordinal = 0; + + // pull out all names + const source = mapValue[index]; + const names = this.walkObjectNames(source); + + // must be behind all these names + names.forEach((name) => { + const depName = name; + + // find this name's ordinal, if it has already been added + order.forEach((orderItem) => { + const depIndex = orderItem; + if (mapKey[depIndex] === depName) { + // this is the index of the dependency, so make sure we come after it + ordinal = Math.max(ordinal, depIndex + 1); + } + }); + }); + + // insert index + order.splice(ordinal, 0, index); + }); + + // now emit ordered source + order.forEach((i) => + this.emitGatheredSource( + this.gatherSource(() => + this.emitObject(mapKey[i], mapValue[i]), + ), + ), + ); + } + + protected emitSourceStructure(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } + + this.emitImports(); + this.emitSchemas(); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts new file mode 100644 index 000000000..555704cfa --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/index.ts @@ -0,0 +1,5 @@ +export { + TypeScriptEffectSchemaTargetLanguage, + typeScriptEffectSchemaOptions, +} from "./language"; +export { TypeScriptEffectSchemaRenderer } from "./TypeScriptEffectSchemaRenderer"; diff --git a/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts new file mode 100644 index 000000000..d55ecc1be --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptEffectSchema/language.ts @@ -0,0 +1,41 @@ +import type { RenderContext } from "../../Renderer"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { TypeScriptEffectSchemaRenderer } from "./TypeScriptEffectSchemaRenderer"; + +export const typeScriptEffectSchemaOptions = { + justSchema: new BooleanOption("just-schema", "Schema only", false), +}; + +export const typeScriptEffectSchemaLanguageConfig = { + displayName: "TypeScript Effect Schema", + names: ["typescript-effect-schema"], + extension: "ts", +} as const; + +export class TypeScriptEffectSchemaTargetLanguage extends TargetLanguage< + typeof typeScriptEffectSchemaLanguageConfig +> { + public constructor() { + super(typeScriptEffectSchemaLanguageConfig); + } + + public getOptions(): {} { + return {}; + } + + protected makeRenderer< + Lang extends LanguageName = "typescript-effect-schema", + >( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): TypeScriptEffectSchemaRenderer { + return new TypeScriptEffectSchemaRenderer( + this, + renderContext, + getOptionValues(typeScriptEffectSchemaOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow.ts b/packages/quicktype-core/src/language/TypeScriptFlow.ts deleted file mode 100644 index 3bc02e2a9..000000000 --- a/packages/quicktype-core/src/language/TypeScriptFlow.ts +++ /dev/null @@ -1,378 +0,0 @@ -import { Type, ArrayType, UnionType, ClassType, EnumType } from "../Type"; -import { matchType, nullableFromUnion, isNamedType } from "../TypeUtils"; -import { utf16StringEscape, camelCase } from "../support/Strings"; - -import { Sourcelike, modifySource, MultiWord, singleWord, parenIfNeeded, multiWord } from "../Source"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; -import { - javaScriptOptions, - JavaScriptTargetLanguage, - JavaScriptRenderer, - JavaScriptTypeAnnotations, - legalizeName -} from "./JavaScript"; -import { defined, panic } from "../support/Support"; -import { TargetLanguage } from "../TargetLanguage"; -import { RenderContext } from "../Renderer"; -import { isES3IdentifierStart } from "./JavaScriptUnicodeMaps"; - -export const tsFlowOptions = Object.assign({}, javaScriptOptions, { - justTypes: new BooleanOption("just-types", "Interfaces only", false), - nicePropertyNames: new BooleanOption("nice-property-names", "Transform property names to be JavaScripty", false), - declareUnions: new BooleanOption("explicit-unions", "Explicitly name unions", false), - preferUnions: new BooleanOption("prefer-unions", "Use union type instead of enum", false), - preferTypes: new BooleanOption("prefer-types", "Use types instead of interfaces", false), - preferConstValues: new BooleanOption( - "prefer-const-values", - "Use string instead of enum for string enums with single value", - false - ) -}); - -const tsFlowTypeAnnotations = { - any: ": any", - anyArray: ": any[]", - anyMap: ": { [k: string]: any }", - string: ": string", - stringArray: ": string[]", - boolean: ": boolean" -}; - -export abstract class TypeScriptFlowBaseTargetLanguage extends JavaScriptTargetLanguage { - protected getOptions(): Option[] { - return [ - tsFlowOptions.justTypes, - tsFlowOptions.nicePropertyNames, - tsFlowOptions.declareUnions, - tsFlowOptions.runtimeTypecheck, - tsFlowOptions.runtimeTypecheckIgnoreUnknownProperties, - tsFlowOptions.acronymStyle, - tsFlowOptions.converters, - tsFlowOptions.rawType, - tsFlowOptions.preferUnions, - tsFlowOptions.preferTypes - ]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - protected abstract makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): JavaScriptRenderer; -} - -export class TypeScriptTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor() { - super("TypeScript", ["typescript", "ts", "tsx"], "ts"); - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): TypeScriptRenderer { - return new TypeScriptRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); - } -} - -function quotePropertyName(original: string): string { - const escaped = utf16StringEscape(original); - const quoted = `"${escaped}"`; - - if (original.length === 0) { - return quoted; - } else if (!isES3IdentifierStart(original.codePointAt(0) as number)) { - return quoted; - } else if (escaped !== original) { - return quoted; - } else if (legalizeName(original) !== original) { - return quoted; - } else { - return original; - } -} - -export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - protected readonly _tsFlowOptions: OptionValues - ) { - super(targetLanguage, renderContext, _tsFlowOptions); - } - - protected namerForObjectProperty(): Namer { - if (this._tsFlowOptions.nicePropertyNames) { - return funPrefixNamer("properties", s => this.nameStyle(s, false)); - } else { - return super.namerForObjectProperty(); - } - } - - protected sourceFor(t: Type): MultiWord { - if (this._tsFlowOptions.preferConstValues && t.kind === "enum" && t instanceof EnumType && t.cases.size === 1) { - const item = t.cases.values().next().value; - return singleWord(`"${utf16StringEscape(item)}"`); - } - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { - return singleWord(this.nameForNamedType(t)); - } - return matchType( - t, - _anyType => singleWord("any"), - _nullType => singleWord("null"), - _boolType => singleWord("boolean"), - _integerType => singleWord("number"), - _doubleType => singleWord("number"), - _stringType => singleWord("string"), - arrayType => { - const itemType = this.sourceFor(arrayType.items); - if ( - (arrayType.items instanceof UnionType && !this._tsFlowOptions.declareUnions) || - arrayType.items instanceof ArrayType - ) { - return singleWord(["Array<", itemType.source, ">"]); - } else { - return singleWord([parenIfNeeded(itemType), "[]"]); - } - }, - _classType => panic("We handled this above"), - mapType => singleWord(["{ [key: string]: ", this.sourceFor(mapType.values).source, " }"]), - _enumType => panic("We handled this above"), - unionType => { - if (!this._tsFlowOptions.declareUnions || nullableFromUnion(unionType) !== null) { - const children = Array.from(unionType.getChildren()).map(c => parenIfNeeded(this.sourceFor(c))); - return multiWord(" | ", ...children); - } else { - return singleWord(this.nameForNamedType(unionType)); - } - }, - transformedStringType => { - if (transformedStringType.kind === "date-time") { - return singleWord("Date"); - } - return singleWord("string"); - } - ); - } - - protected abstract emitEnum(e: EnumType, enumName: Name): void; - - protected abstract emitClassBlock(c: ClassType, className: Name): void; - - protected emitClassBlockBody(c: ClassType): void { - this.emitPropertyTable(c, (name, _jsonName, p) => { - const t = p.type; - return [ - [modifySource(quotePropertyName, name), p.isOptional ? "?" : "", ": "], - [this.sourceFor(t).source, ";"] - ]; - }); - - const additionalProperties = c.getAdditionalProperties(); - if (additionalProperties) { - this.emitTable([["[property: string]", ": ", this.sourceFor(additionalProperties).source, ";"]]); - } - } - - private emitClass(c: ClassType, className: Name) { - this.emitDescription(this.descriptionForType(c)); - this.emitClassBlock(c, className); - } - - emitUnion(u: UnionType, unionName: Name) { - if (!this._tsFlowOptions.declareUnions) { - return; - } - - this.emitDescription(this.descriptionForType(u)); - - const children = multiWord(" | ", ...Array.from(u.getChildren()).map(c => parenIfNeeded(this.sourceFor(c)))); - this.emitLine("export type ", unionName, " = ", children.source, ";"); - } - - protected emitTypes(): void { - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClass(c, n), - (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) - ); - } - - protected emitUsageComments(): void { - if (this._tsFlowOptions.justTypes) return; - super.emitUsageComments(); - } - - protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { - const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["function to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; - } - - protected serializerFunctionLine(t: Type, name: Name): Sourcelike { - const camelCaseName = modifySource(camelCase, name); - const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["function ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; - } - - protected get moduleLine(): string | undefined { - return undefined; - } - - protected get castFunctionLines(): [string, string] { - return ["function cast(val: any, typ: any): T", "function uncast(val: T, typ: any): any"]; - } - - protected get typeAnnotations(): JavaScriptTypeAnnotations { - throw new Error("not implemented"); - } - - protected emitConvertModule(): void { - if (this._tsFlowOptions.justTypes) return; - super.emitConvertModule(); - } - - protected emitConvertModuleHelpers(): void { - if (this._tsFlowOptions.justTypes) return; - super.emitConvertModuleHelpers(); - } - - protected emitModuleExports(): void { - if (this._tsFlowOptions.justTypes) { - return; - } else { - super.emitModuleExports(); - } - } -} - -export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["Array", "Date"]; - } - - protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { - const jsonType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["public static to", name, "(json: ", jsonType, "): ", this.sourceFor(t).source]; - } - - protected serializerFunctionLine(t: Type, name: Name): Sourcelike { - const camelCaseName = modifySource(camelCase, name); - const returnType = this._tsFlowOptions.rawType === "json" ? "string" : "any"; - return ["public static ", camelCaseName, "ToJson(value: ", this.sourceFor(t).source, "): ", returnType]; - } - - protected get moduleLine(): string | undefined { - return "export class Convert"; - } - - protected get typeAnnotations(): JavaScriptTypeAnnotations { - return Object.assign({ never: ": never" }, tsFlowTypeAnnotations); - } - - protected emitModuleExports(): void { - return; - } - - protected emitUsageImportComment(): void { - const topLevelNames: Sourcelike[] = []; - this.forEachTopLevel( - "none", - (_t, name) => { - topLevelNames.push(", ", name); - }, - isNamedType - ); - this.emitLine("// import { Convert", topLevelNames, ' } from "./file";'); - } - - protected emitEnum(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - - // enums with only one value are emitted as constants - if (this._tsFlowOptions.preferConstValues && e.cases.size === 1) return; - - if (this._tsFlowOptions.preferUnions) { - let items = ""; - e.cases.forEach(item => { - if (items === "") { - items += `"${utf16StringEscape(item)}"`; - return; - } - items += ` | "${utf16StringEscape(item)}"`; - }); - this.emitLine("export type ", enumName, " = ", items, ";"); - } else { - this.emitBlock(["export enum ", enumName, " "], "", () => { - this.forEachEnumCase(e, "none", (name, jsonName) => { - this.emitLine(name, ` = "${utf16StringEscape(jsonName)}",`); - }); - }); - } - } - - protected emitClassBlock(c: ClassType, className: Name): void { - this.emitBlock( - this._tsFlowOptions.preferTypes - ? ["export type ", className, " = "] - : ["export interface ", className, " "], - "", - () => { - this.emitClassBlockBody(c); - } - ); - } -} - -export class FlowTargetLanguage extends TypeScriptFlowBaseTargetLanguage { - constructor() { - super("Flow", ["flow"], "js"); - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): FlowRenderer { - return new FlowRenderer(this, renderContext, getOptionValues(tsFlowOptions, untypedOptionValues)); - } -} - -export class FlowRenderer extends TypeScriptFlowBaseRenderer { - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; - } - - protected get typeAnnotations(): JavaScriptTypeAnnotations { - return Object.assign({ never: "" }, tsFlowTypeAnnotations); - } - - protected emitEnum(e: EnumType, enumName: Name): void { - this.emitDescription(this.descriptionForType(e)); - const lines: string[][] = []; - this.forEachEnumCase(e, "none", (_, jsonName) => { - const maybeOr = lines.length === 0 ? " " : "| "; - lines.push([maybeOr, '"', utf16StringEscape(jsonName), '"']); - }); - defined(lines[lines.length - 1]).push(";"); - - this.emitLine("export type ", enumName, " ="); - this.indent(() => { - for (const line of lines) { - this.emitLine(line); - } - }); - } - - protected emitClassBlock(c: ClassType, className: Name): void { - this.emitBlock(["export type ", className, " = "], ";", () => { - this.emitClassBlockBody(c); - }); - } - - protected emitSourceStructure() { - this.emitLine("// @flow"); - this.ensureBlankLine(); - super.emitSourceStructure(); - } -} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts b/packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts new file mode 100644 index 000000000..02e82aee5 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/FlowRenderer.ts @@ -0,0 +1,47 @@ +import type { Name } from "../../Naming"; +import { utf16StringEscape } from "../../support/Strings"; +import { defined } from "../../support/Support"; +import type { ClassType, EnumType } from "../../Type"; +import type { JavaScriptTypeAnnotations } from "../JavaScript"; + +import { TypeScriptFlowBaseRenderer } from "./TypeScriptFlowBaseRenderer"; +import { tsFlowTypeAnnotations } from "./utils"; + +export class FlowRenderer extends TypeScriptFlowBaseRenderer { + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; + } + + protected get typeAnnotations(): JavaScriptTypeAnnotations { + return Object.assign({ never: "" }, tsFlowTypeAnnotations); + } + + protected emitEnum(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + const lines: string[][] = []; + this.forEachEnumCase(e, "none", (_, jsonName) => { + const maybeOr = lines.length === 0 ? " " : "| "; + lines.push([maybeOr, '"', utf16StringEscape(jsonName), '"']); + }); + defined(lines[lines.length - 1]).push(";"); + + this.emitLine("export type ", enumName, " ="); + this.indent(() => { + for (const line of lines) { + this.emitLine(line); + } + }); + } + + protected emitClassBlock(c: ClassType, className: Name): void { + this.emitBlock(["export type ", className, " = "], ";", () => { + this.emitClassBlockBody(c); + }); + } + + protected emitSourceStructure(): void { + this.emitLine("// @flow"); + this.ensureBlankLine(); + super.emitSourceStructure(); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts new file mode 100644 index 000000000..2acc4da23 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptFlowBaseRenderer.ts @@ -0,0 +1,258 @@ +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import { + type MultiWord, + type Sourcelike, + modifySource, + multiWord, + parenIfNeeded, + singleWord, +} from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import { panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassType, + EnumType, + type Type, + UnionType, +} from "../../Type"; +import { matchType, nullableFromUnion } from "../../Type/TypeUtils"; +import { + JavaScriptRenderer, + type JavaScriptTypeAnnotations, +} from "../JavaScript"; + +import type { tsFlowOptions } from "./language"; +import { quotePropertyName } from "./utils"; + +export abstract class TypeScriptFlowBaseRenderer extends JavaScriptRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _tsFlowOptions: OptionValues, + ) { + super(targetLanguage, renderContext, _tsFlowOptions); + } + + protected namerForObjectProperty(): Namer { + if (this._tsFlowOptions.nicePropertyNames) { + return funPrefixNamer("properties", (s) => + this.nameStyle(s, false), + ); + } + + return super.namerForObjectProperty(); + } + + protected sourceFor(t: Type): MultiWord { + if ( + this._tsFlowOptions.preferConstValues && + t.kind === "enum" && + t instanceof EnumType && + t.cases.size === 1 + ) { + const item = t.cases.values().next().value ?? ""; + return singleWord(`"${utf16StringEscape(item)}"`); + } + + if (["class", "object", "enum"].includes(t.kind)) { + return singleWord(this.nameForNamedType(t)); + } + + return matchType( + t, + (_anyType) => singleWord("any"), + (_nullType) => singleWord("null"), + (_boolType) => singleWord("boolean"), + (_integerType) => singleWord("number"), + (_doubleType) => singleWord("number"), + (_stringType) => singleWord("string"), + (arrayType) => { + const itemType = this.sourceFor(arrayType.items); + if ( + (arrayType.items instanceof UnionType && + !this._tsFlowOptions.declareUnions) || + arrayType.items instanceof ArrayType + ) { + return singleWord(["Array<", itemType.source, ">"]); + } + + return singleWord([parenIfNeeded(itemType), "[]"]); + }, + (_classType) => panic("We handled this above"), + (mapType) => + singleWord([ + "{ [key: string]: ", + this.sourceFor(mapType.values).source, + " }", + ]), + (_enumType) => panic("We handled this above"), + (unionType) => { + if ( + !this._tsFlowOptions.declareUnions || + nullableFromUnion(unionType) !== null + ) { + const children = Array.from(unionType.getChildren()).map( + (c) => parenIfNeeded(this.sourceFor(c)), + ); + return multiWord(" | ", ...children); + } + + return singleWord(this.nameForNamedType(unionType)); + }, + (transformedStringType) => { + if (transformedStringType.kind === "date-time") { + return singleWord("Date"); + } + + return singleWord("string"); + }, + ); + } + + protected abstract emitEnum(e: EnumType, enumName: Name): void; + + protected abstract emitClassBlock(c: ClassType, className: Name): void; + + protected emitClassBlockBody(c: ClassType): void { + this.emitPropertyTable(c, (name, _jsonName, p) => { + const t = p.type; + + let propertyName: Sourcelike = name; + propertyName = modifySource(quotePropertyName, name); + + if (this._tsFlowOptions.readonly) { + propertyName = modifySource( + (_propertyName) => `readonly ${_propertyName}`, + propertyName, + ); + } + + return [ + [propertyName, p.isOptional ? "?" : "", ": "], + [this.sourceFor(t).source, ";"], + ]; + }); + + const additionalProperties = c.getAdditionalProperties(); + if (additionalProperties) { + this.emitTable([ + [ + "[property: string]", + ": ", + this.sourceFor(additionalProperties).source, + ";", + ], + ]); + } + } + + private emitClass(c: ClassType, className: Name): void { + this.emitDescription(this.descriptionForType(c)); + this.emitClassBlock(c, className); + } + + protected emitUnion(u: UnionType, unionName: Name): void { + if (!this._tsFlowOptions.declareUnions) { + return; + } + + this.emitDescription(this.descriptionForType(u)); + + const children = multiWord( + " | ", + ...Array.from(u.getChildren()).map((c) => + parenIfNeeded(this.sourceFor(c)), + ), + ); + this.emitLine("export type ", unionName, " = ", children.source, ";"); + } + + protected emitTypes(): void { + // emit primitive top levels + this.forEachTopLevel("none", (t, name) => { + if (!t.isPrimitive()) { + return; + } + + this.ensureBlankLine(); + this.emitDescription(this.descriptionForType(t)); + this.emitLine("type ", name, " = ", this.sourceFor(t).source, ";"); + }); + + this.forEachNamedType( + "leading-and-interposing", + (c: ClassType, n: Name) => this.emitClass(c, n), + (e, n) => this.emitEnum(e, n), + (u, n) => this.emitUnion(u, n), + ); + } + + protected emitUsageComments(): void { + if (this._tsFlowOptions.justTypes) return; + super.emitUsageComments(); + } + + protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { + const jsonType = + this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return [ + "function to", + name, + "(json: ", + jsonType, + "): ", + this.sourceFor(t).source, + ]; + } + + protected serializerFunctionLine(t: Type, name: Name): Sourcelike { + const camelCaseName = modifySource(camelCase, name); + const returnType = + this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return [ + "function ", + camelCaseName, + "ToJson(value: ", + this.sourceFor(t).source, + "): ", + returnType, + ]; + } + + protected get moduleLine(): string | undefined { + return undefined; + } + + protected get castFunctionLines(): [string, string] { + return [ + "function cast(val: any, typ: any): T", + "function uncast(val: T, typ: any): any", + ]; + } + + protected get typeAnnotations(): JavaScriptTypeAnnotations { + throw new Error("not implemented"); + } + + protected emitConvertModule(): void { + if (this._tsFlowOptions.justTypes) return; + super.emitConvertModule(); + } + + protected emitConvertModuleHelpers(): void { + if (this._tsFlowOptions.justTypes) return; + super.emitConvertModuleHelpers(); + } + + protected emitModuleExports(): void { + if (this._tsFlowOptions.justTypes) { + return; + } else { + super.emitModuleExports(); + } + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts new file mode 100644 index 000000000..82d272484 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/TypeScriptRenderer.ts @@ -0,0 +1,108 @@ +import type { Name } from "../../Naming"; +import { type Sourcelike, modifySource } from "../../Source"; +import { camelCase, utf16StringEscape } from "../../support/Strings"; +import type { ClassType, EnumType, Type } from "../../Type"; +import { isNamedType } from "../../Type/TypeUtils"; +import type { JavaScriptTypeAnnotations } from "../JavaScript"; + +import { TypeScriptFlowBaseRenderer } from "./TypeScriptFlowBaseRenderer"; +import { tsFlowTypeAnnotations } from "./utils"; + +export class TypeScriptRenderer extends TypeScriptFlowBaseRenderer { + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["Array", "Date"]; + } + + protected deserializerFunctionLine(t: Type, name: Name): Sourcelike { + const jsonType = + this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return [ + "public static to", + name, + "(json: ", + jsonType, + "): ", + this.sourceFor(t).source, + ]; + } + + protected serializerFunctionLine(t: Type, name: Name): Sourcelike { + const camelCaseName = modifySource(camelCase, name); + const returnType = + this._tsFlowOptions.rawType === "json" ? "string" : "any"; + return [ + "public static ", + camelCaseName, + "ToJson(value: ", + this.sourceFor(t).source, + "): ", + returnType, + ]; + } + + protected get moduleLine(): string | undefined { + return "export class Convert"; + } + + protected get typeAnnotations(): JavaScriptTypeAnnotations { + return Object.assign({ never: ": never" }, tsFlowTypeAnnotations); + } + + protected emitModuleExports(): void { + return; + } + + protected emitUsageImportComment(): void { + const topLevelNames: Sourcelike[] = []; + this.forEachTopLevel( + "none", + (_t, name) => { + topLevelNames.push(", ", name); + }, + isNamedType, + ); + this.emitLine( + "// import { Convert", + topLevelNames, + ' } from "./file";', + ); + } + + protected emitEnum(e: EnumType, enumName: Name): void { + this.emitDescription(this.descriptionForType(e)); + + // enums with only one value are emitted as constants + if (this._tsFlowOptions.preferConstValues && e.cases.size === 1) return; + + if (this._tsFlowOptions.preferUnions) { + let items = ""; + e.cases.forEach((item) => { + if (items === "") { + items += `"${utf16StringEscape(item)}"`; + return; + } + + items += ` | "${utf16StringEscape(item)}"`; + }); + this.emitLine("export type ", enumName, " = ", items, ";"); + } else { + this.emitBlock(["export enum ", enumName, " "], "", () => { + this.forEachEnumCase(e, "none", (name, jsonName) => { + this.emitLine(name, ` = "${utf16StringEscape(jsonName)}",`); + }); + }); + } + } + + protected emitClassBlock(c: ClassType, className: Name): void { + this.emitBlock( + this._tsFlowOptions.preferTypes + ? ["export type ", className, " = "] + : ["export interface ", className, " "], + "", + () => { + this.emitClassBlockBody(c); + }, + ); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/index.ts b/packages/quicktype-core/src/language/TypeScriptFlow/index.ts new file mode 100644 index 000000000..42d51fa3f --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/index.ts @@ -0,0 +1,7 @@ +export { FlowRenderer } from "./FlowRenderer"; +export { TypeScriptRenderer } from "./TypeScriptRenderer"; +export { + FlowTargetLanguage, + TypeScriptTargetLanguage, + tsFlowOptions, +} from "./language"; diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/language.ts b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts new file mode 100644 index 000000000..1a5bdde8d --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/language.ts @@ -0,0 +1,135 @@ +import type { RenderContext } from "../../Renderer"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; +import { javaScriptOptions } from "../JavaScript"; + +import { FlowRenderer } from "./FlowRenderer"; +import { TypeScriptRenderer } from "./TypeScriptRenderer"; + +export const tsFlowOptions = Object.assign({}, javaScriptOptions, { + justTypes: new BooleanOption("just-types", "Interfaces only", false), + nicePropertyNames: new BooleanOption( + "nice-property-names", + "Transform property names to be JavaScripty", + false, + ), + declareUnions: new BooleanOption( + "explicit-unions", + "Explicitly name unions", + false, + ), + preferUnions: new BooleanOption( + "prefer-unions", + "Use union type instead of enum", + false, + ), + preferTypes: new BooleanOption( + "prefer-types", + "Use types instead of interfaces", + false, + ), + preferConstValues: new BooleanOption( + "prefer-const-values", + "Use string instead of enum for string enums with single value", + false, + ), + readonly: new BooleanOption("readonly", "Use readonly type members", false), +}); + +export const typeScriptLanguageConfig = { + displayName: "TypeScript", + names: ["typescript", "ts", "tsx"], + extension: "ts", +} as const; + +export class TypeScriptTargetLanguage extends TargetLanguage< + typeof typeScriptLanguageConfig +> { + public constructor() { + super(typeScriptLanguageConfig); + } + + public getOptions(): typeof tsFlowOptions { + return tsFlowOptions; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("date-time", dateTimeType); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsFullObjectType(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): TypeScriptRenderer { + return new TypeScriptRenderer( + this, + renderContext, + getOptionValues(tsFlowOptions, untypedOptionValues), + ); + } +} + +export const flowLanguageConfig = { + displayName: "Flow", + names: ["flow"], + extension: "js", +} as const; + +export class FlowTargetLanguage extends TargetLanguage< + typeof flowLanguageConfig +> { + public constructor() { + super(flowLanguageConfig); + } + + public getOptions(): typeof tsFlowOptions { + return tsFlowOptions; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + const dateTimeType = "date-time"; + mapping.set("date", dateTimeType); + mapping.set("date-time", dateTimeType); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + public get supportsFullObjectType(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): FlowRenderer { + return new FlowRenderer( + this, + renderContext, + getOptionValues(tsFlowOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptFlow/utils.ts b/packages/quicktype-core/src/language/TypeScriptFlow/utils.ts new file mode 100644 index 000000000..0d01ca9cd --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptFlow/utils.ts @@ -0,0 +1,29 @@ +import { utf16StringEscape } from "../../support/Strings"; +import { isES3IdentifierStart } from "../JavaScript/unicodeMaps"; +import { legalizeName } from "../JavaScript/utils"; + +export const tsFlowTypeAnnotations = { + any: ": any", + anyArray: ": any[]", + anyMap: ": { [k: string]: any }", + string: ": string", + stringArray: ": string[]", + boolean: ": boolean", +}; + +export function quotePropertyName(original: string): string { + const escaped = utf16StringEscape(original); + const quoted = `"${escaped}"`; + + if (original.length === 0) { + return quoted; + } else if (!isES3IdentifierStart(original.codePointAt(0) as number)) { + return quoted; + } else if (escaped !== original) { + return quoted; + } else if (legalizeName(original) !== original) { + return quoted; + } else { + return original; + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptZod.ts b/packages/quicktype-core/src/language/TypeScriptZod.ts deleted file mode 100644 index 2ec7df178..000000000 --- a/packages/quicktype-core/src/language/TypeScriptZod.ts +++ /dev/null @@ -1,239 +0,0 @@ -import { StringTypeMapping } from "TypeBuilder"; -import { arrayIntercalate } from "collection-utils"; -import { ConvenienceRenderer } from "../ConvenienceRenderer"; -import { Name, Namer, funPrefixNamer } from "../Naming"; -import { RenderContext } from "../Renderer"; -import { BooleanOption, Option, OptionValues, getOptionValues } from "../RendererOptions"; -import { Sourcelike } from "../Source"; -import { TargetLanguage } from "../TargetLanguage"; -import { ClassProperty, EnumType, ObjectType, PrimitiveStringTypeKind, TransformedStringTypeKind, Type } from "../Type"; -import { matchType } from "../TypeUtils"; -import { AcronymStyleOptions, acronymStyle } from "../support/Acronyms"; -import { - allLowerWordStyle, - capitalize, - combineWords, - firstUpperWordStyle, - isLetterOrUnderscore, - splitIntoWords, - stringEscape, - utf16StringEscape -} from "../support/Strings"; -import { panic } from "../support/Support"; -import { legalizeName } from "./JavaScript"; - -export const typeScriptZodOptions = { - justSchema: new BooleanOption("just-schema", "Schema only", false) -}; - -export class TypeScriptZodTargetLanguage extends TargetLanguage { - protected getOptions(): Option[] { - return []; - } - - constructor( - displayName: string = "TypeScript Zod", - names: string[] = ["typescript-zod"], - extension: string = "ts" - ) { - super(displayName, names, extension); - } - - get stringTypeMapping(): StringTypeMapping { - const mapping: Map = new Map(); - const dateTimeType = "date-time"; - mapping.set("date-time", dateTimeType); - return mapping; - } - - protected makeRenderer( - renderContext: RenderContext, - untypedOptionValues: { [name: string]: any } - ): TypeScriptZodRenderer { - return new TypeScriptZodRenderer( - this, - renderContext, - getOptionValues(typeScriptZodOptions, untypedOptionValues) - ); - } -} - -export class TypeScriptZodRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; - } - - protected nameStyle(original: string, upper: boolean): string { - const acronyms = acronymStyle(AcronymStyleOptions.Camel); - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - upper ? firstUpperWordStyle : allLowerWordStyle, - firstUpperWordStyle, - upper ? s => capitalize(acronyms(s)) : allLowerWordStyle, - acronyms, - "", - isLetterOrUnderscore - ); - } - - protected makeNamedTypeNamer(): Namer { - return funPrefixNamer("types", s => this.nameStyle(s, true)); - } - - protected makeUnionMemberNamer(): Namer { - return funPrefixNamer("properties", s => this.nameStyle(s, true)); - } - - protected namerForObjectProperty(): Namer { - return funPrefixNamer("properties", s => this.nameStyle(s, true)); - } - - protected makeEnumCaseNamer(): Namer { - return funPrefixNamer("enum-cases", s => this.nameStyle(s, false)); - } - - private importStatement(lhs: Sourcelike, moduleName: Sourcelike): Sourcelike { - return ["import ", lhs, " from ", moduleName, ";"]; - } - - protected emitImports(): void { - this.ensureBlankLine(); - this.emitLine(this.importStatement("* as z", '"zod"')); - } - - typeMapTypeForProperty(p: ClassProperty): Sourcelike { - const typeMap = this.typeMapTypeFor(p.type); - return p.isOptional ? [typeMap, ".optional()"] : typeMap; - } - - typeMapTypeFor(t: Type, required: boolean = true): Sourcelike { - if (["class", "object", "enum"].indexOf(t.kind) >= 0) { - return [this.nameForNamedType(t), "Schema"]; - } - - const match = matchType( - t, - _anyType => "z.any()", - _nullType => "z.null()", - _boolType => "z.boolean()", - _integerType => "z.number()", - _doubleType => "z.number()", - _stringType => "z.string()", - arrayType => ["z.array(", this.typeMapTypeFor(arrayType.items, false), ")"], - _classType => panic("Should already be handled."), - _mapType => ["z.record(z.string(), ", this.typeMapTypeFor(_mapType.values, false), ")"], - _enumType => panic("Should already be handled."), - unionType => { - const children = Array.from(unionType.getChildren()).map((type: Type) => - this.typeMapTypeFor(type, false) - ); - return ["z.union([", ...arrayIntercalate(", ", children), "])"]; - }, - _transformedStringType => { - if (_transformedStringType.kind === "date-time") { - return "z.coerce.date()"; - } - return "z.string()"; - } - ); - - if (required) { - return [match]; - } - - return match; - } - - private emitObject(name: Name, t: ObjectType) { - this.ensureBlankLine(); - this.emitLine("\nexport const ", name, "Schema = ", "z.object({"); - this.indent(() => { - this.forEachClassProperty(t, "none", (_, jsonName, property) => { - this.emitLine(`"${utf16StringEscape(jsonName)}"`, ": ", this.typeMapTypeForProperty(property), ","); - }); - }); - this.emitLine("});"); - if (!this._options.justSchema) { - this.emitLine("export type ", name, " = z.infer;"); - } - } - - private emitEnum(e: EnumType, enumName: Name): void { - this.ensureBlankLine(); - this.emitDescription(this.descriptionForType(e)); - this.emitLine("\nexport const ", enumName, "Schema = ", "z.enum(["); - this.indent(() => - this.forEachEnumCase(e, "none", (_, jsonName) => { - this.emitLine('"', stringEscape(jsonName), '",'); - }) - ); - this.emitLine("]);"); - if (!this._options.justSchema) { - this.emitLine("export type ", enumName, " = z.infer;"); - } - } - - protected emitSchemas(): void { - this.ensureBlankLine(); - - this.forEachEnum("leading-and-interposing", (u: EnumType, enumName: Name) => { - this.emitEnum(u, enumName); - }); - - const order: number[] = []; - const mapKey: Name[] = []; - const mapValue: Sourcelike[][] = []; - this.forEachObject("none", (type: ObjectType, name: Name) => { - mapKey.push(name); - mapValue.push(this.gatherSource(() => this.emitObject(name, type))); - }); - - mapKey.forEach((_, index) => { - // assume first - let ordinal = 0; - - // pull out all names - const source = mapValue[index]; - const names = source.filter(value => value as Name); - - // must be behind all these names - for (let i = 0; i < names.length; i++) { - const depName = names[i]; - - // find this name's ordinal, if it has already been added - for (let j = 0; j < order.length; j++) { - const depIndex = order[j]; - if (mapKey[depIndex] === depName) { - // this is the index of the dependency, so make sure we come after it - ordinal = Math.max(ordinal, depIndex + 1); - } - } - } - - // insert index - order.splice(ordinal, 0, index); - }); - - // now emit ordered source - order.forEach(i => this.emitGatheredSource(mapValue[i])); - } - - protected emitSourceStructure(): void { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } - - this.emitImports(); - this.emitSchemas(); - } -} diff --git a/packages/quicktype-core/src/language/TypeScriptZod/TypeScriptZodRenderer.ts b/packages/quicktype-core/src/language/TypeScriptZod/TypeScriptZodRenderer.ts new file mode 100644 index 000000000..bcd9aa4c8 --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptZod/TypeScriptZodRenderer.ts @@ -0,0 +1,367 @@ +import { arrayIntercalate } from "collection-utils"; + +import { ConvenienceRenderer } from "../../ConvenienceRenderer"; +import { type Name, type Namer, funPrefixNamer } from "../../Naming"; +import type { RenderContext } from "../../Renderer"; +import type { OptionValues } from "../../RendererOptions"; +import type { Sourcelike } from "../../Source"; +import { AcronymStyleOptions, acronymStyle } from "../../support/Acronyms"; +import { + allLowerWordStyle, + capitalize, + combineWords, + firstUpperWordStyle, + isLetterOrUnderscore, + splitIntoWords, + stringEscape, + utf16StringEscape, +} from "../../support/Strings"; +import { panic } from "../../support/Support"; +import type { TargetLanguage } from "../../TargetLanguage"; +import { + ArrayType, + type ClassProperty, + ClassType, + type EnumType, + ObjectType, + SetOperationType, + type Type, +} from "../../Type"; +import { matchType } from "../../Type/TypeUtils"; +import { legalizeName } from "../JavaScript/utils"; + +import type { typeScriptZodOptions } from "./language"; + +export class TypeScriptZodRenderer extends ConvenienceRenderer { + public constructor( + targetLanguage: TargetLanguage, + renderContext: RenderContext, + protected readonly _options: OptionValues, + ) { + super(targetLanguage, renderContext); + } + + protected forbiddenNamesForGlobalNamespace(): string[] { + return ["Class", "Date", "Object", "String", "Array", "JSON", "Error"]; + } + + protected nameStyle(original: string, upper: boolean): string { + const acronyms = acronymStyle(AcronymStyleOptions.Camel); + const words = splitIntoWords(original); + return combineWords( + words, + legalizeName, + upper ? firstUpperWordStyle : allLowerWordStyle, + firstUpperWordStyle, + upper ? (s): string => capitalize(acronyms(s)) : allLowerWordStyle, + acronyms, + "", + isLetterOrUnderscore, + ); + } + + protected makeNamedTypeNamer(): Namer { + return funPrefixNamer("types", (s) => this.nameStyle(s, true)); + } + + protected makeUnionMemberNamer(): Namer { + return funPrefixNamer("properties", (s) => this.nameStyle(s, true)); + } + + protected namerForObjectProperty(): Namer { + return funPrefixNamer("properties", (s) => this.nameStyle(s, true)); + } + + protected makeEnumCaseNamer(): Namer { + return funPrefixNamer("enum-cases", (s) => this.nameStyle(s, false)); + } + + protected importStatement( + lhs: Sourcelike, + moduleName: Sourcelike, + ): Sourcelike { + return ["import ", lhs, " from ", moduleName, ";"]; + } + + protected emitImports(): void { + this.ensureBlankLine(); + this.emitLine(this.importStatement("* as z", '"zod"')); + } + + protected typeMapTypeForProperty(p: ClassProperty): Sourcelike { + const typeMap = this.typeMapTypeFor(p.type); + return p.isOptional ? [typeMap, ".optional()"] : typeMap; + } + + protected typeMapTypeFor(t: Type, required = true): Sourcelike { + if (["class", "object", "enum"].includes(t.kind)) { + return [this.nameForNamedType(t), "Schema"]; + } + + const match = matchType( + t, + (_anyType) => "z.any()", + (_nullType) => "z.null()", + (_boolType) => "z.boolean()", + (_integerType) => "z.number()", + (_doubleType) => "z.number()", + (_stringType) => "z.string()", + (arrayType) => [ + "z.array(", + this.typeMapTypeFor(arrayType.items, false), + ")", + ], + (_classType) => panic("Should already be handled."), + (_mapType) => [ + "z.record(z.string(), ", + this.typeMapTypeFor(_mapType.values, false), + ")", + ], + (_enumType) => panic("Should already be handled."), + (unionType) => { + const children = Array.from(unionType.getChildren()).map( + (type: Type) => this.typeMapTypeFor(type, false), + ); + return ["z.union([", ...arrayIntercalate(", ", children), "])"]; + }, + (_transformedStringType) => { + if (_transformedStringType.kind === "date-time") { + return "z.coerce.date()"; + } + + return "z.string()"; + }, + ); + + if (required) { + return [match]; + } + + return match; + } + + protected emitObject(name: Name, t: ObjectType): void { + this.ensureBlankLine(); + this.emitLine("\nexport const ", name, "Schema = ", "z.object({"); + this.indent(() => { + this.forEachClassProperty(t, "none", (_, jsonName, property) => { + this.emitLine( + `"${utf16StringEscape(jsonName)}"`, + ": ", + this.typeMapTypeForProperty(property), + ",", + ); + }); + }); + this.emitLine("});"); + if (!this._options.justSchema) { + this.emitLine( + "export type ", + name, + " = z.infer;", + ); + } + } + + protected emitEnum(e: EnumType, enumName: Name): void { + this.ensureBlankLine(); + this.emitDescription(this.descriptionForType(e)); + this.emitLine("\nexport const ", enumName, "Schema = ", "z.enum(["); + this.indent(() => + this.forEachEnumCase(e, "none", (_, jsonName) => { + this.emitLine('"', stringEscape(jsonName), '",'); + }), + ); + this.emitLine("]);"); + if (!this._options.justSchema) { + this.emitLine( + "export type ", + enumName, + " = z.infer;", + ); + } + } + + /** Static function that extracts underlying type refs for types that form part of the + * definition of the passed type - used to ensure that these appear in generated source + * before types that reference them. + * + * Primitive types don't need defining and enums are output before other types, hence, + * these are ignored. + */ + private static extractUnderlyingTyperefs(type: Type): number[] { + const typeRefs: number[] = []; + // Ignore enums and primitives + if (!type.isPrimitive() && type.kind !== "enum") { + // need to extract constituent types for unions and intersections (which both extend SetOperationType) + // and can ignore the union/intersection itself + if (type instanceof SetOperationType) { + (type as SetOperationType).members.forEach((member) => { + // recurse as the underlying type could itself be a union, instersection or array etc. + typeRefs.push( + ...TypeScriptZodRenderer.extractUnderlyingTyperefs( + member, + ), + ); + }); + } + + // need to extract additional properties for object, class and map types (which all extend ObjectType) + if (type instanceof ObjectType) { + const addType = (type as ObjectType).getAdditionalProperties(); + if (addType) { + // recurse as the underlying type could itself be a union, instersection or array etc. + typeRefs.push( + ...TypeScriptZodRenderer.extractUnderlyingTyperefs( + addType, + ), + ); + } + } + + // need to extract items types for ArrayType + if (type instanceof ArrayType) { + const itemsType = (type as ArrayType).items; + if (itemsType) { + // recurse as the underlying type could itself be a union, instersection or array etc. + typeRefs.push( + ...TypeScriptZodRenderer.extractUnderlyingTyperefs( + itemsType, + ), + ); + } + } + + // Finally return the reference to a class as that will need to be defined (where objects, maps, unions, intersections and arrays do not) + if (type instanceof ClassType) { + typeRefs.push(type.typeRef); + } + } + + return typeRefs; + } + + protected emitSchemas(): void { + this.ensureBlankLine(); + + this.forEachEnum( + "leading-and-interposing", + (u: EnumType, enumName: Name) => { + this.emitEnum(u, enumName); + }, + ); + + // All children must be defined before this type to avoid forward references in generated code + // Build a model that will tell us if a referenced type has been defined then make multiple + // passes over the defined objects to put them into the correct order for output in the + // generated sourcecode + + const order: number[] = []; + const mapType: ObjectType[] = []; + const mapTypeRef: number[] = []; + const mapName: Name[] = []; + const mapChildTypeRefs: number[][] = []; + + this.forEachObject("none", (type: ObjectType, name: Name) => { + mapType.push(type); + mapTypeRef.push(type.typeRef); + mapName.push(name); + + const children = type.getChildren(); + let childTypeRefs: number[] = []; + + children.forEach((child) => { + childTypeRefs = childTypeRefs.concat( + TypeScriptZodRenderer.extractUnderlyingTyperefs(child), + ); + }); + mapChildTypeRefs.push(childTypeRefs); + }); + + // Items to process on this pass + let indices: number[] = []; + mapType.forEach((_, index) => { + indices.push(index); + }); + // items to process on the next pass + let deferredIndices: number[] = []; + + // defensive: make sure we don't loop forever, even complex sets shouldn't require many passes + const MAX_PASSES = 999; + let passNum = 0; + do { + indices.forEach((index) => { + // must be behind all these children + const childTypeRefs = mapChildTypeRefs[index]; + let foundAllChildren = true; + + childTypeRefs.forEach((childRef) => { + // defensive: first check if there is a definition for the referenced type (there should be) + if (mapTypeRef.includes(childRef)) { + let found = false; + // find this childs's ordinal, if it has already been added + // faster to go through what we've defined so far than all definitions + + // FIXME: refactor this + // eslint-disable-next-line @typescript-eslint/prefer-for-of + for (let j = 0; j < order.length; j++) { + const childIndex = order[j]; + if (mapTypeRef[childIndex] === childRef) { + found = true; + break; + } + } + + foundAllChildren = foundAllChildren && found; + } else { + console.error( + "A child type reference was not found amongst all Object definitions! TypeRef: " + + childRef, + ); + } + }); + + if (foundAllChildren) { + // insert index into order as we are safe to define this type + order.push(index); + } else { + // defer to a subsequent pass as we need to define other types + deferredIndices.push(index); + } + }); + indices = deferredIndices; + deferredIndices = []; + passNum++; + + if (passNum > MAX_PASSES) { + // giving up + order.push(...deferredIndices); + console.warn( + "Exceeded maximum number of passes when determining output order, output may contain forward references", + ); + } + } while (indices.length > 0 && passNum <= MAX_PASSES); + + // now emit ordered source + order.forEach((i) => + this.emitGatheredSource( + this.gatherSource(() => + this.emitObject(mapName[i], mapType[i]), + ), + ), + ); + } + + protected emitSourceStructure(): void { + if (this.leadingComments !== undefined) { + this.emitComments(this.leadingComments); + } + + this.emitImports(); + this.emitSchemas(); + } +} diff --git a/packages/quicktype-core/src/language/TypeScriptZod/index.ts b/packages/quicktype-core/src/language/TypeScriptZod/index.ts new file mode 100644 index 000000000..657c2f91c --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptZod/index.ts @@ -0,0 +1,2 @@ +export { TypeScriptZodTargetLanguage, typeScriptZodOptions } from "./language"; +export { TypeScriptZodRenderer } from "./TypeScriptZodRenderer"; diff --git a/packages/quicktype-core/src/language/TypeScriptZod/language.ts b/packages/quicktype-core/src/language/TypeScriptZod/language.ts new file mode 100644 index 000000000..37e5a2e7f --- /dev/null +++ b/packages/quicktype-core/src/language/TypeScriptZod/language.ts @@ -0,0 +1,56 @@ +import type { RenderContext } from "../../Renderer"; +import { BooleanOption, getOptionValues } from "../../RendererOptions"; +import { TargetLanguage } from "../../TargetLanguage"; +import type { + PrimitiveStringTypeKind, + TransformedStringTypeKind, +} from "../../Type"; +import type { StringTypeMapping } from "../../Type/TypeBuilderUtils"; +import type { LanguageName, RendererOptions } from "../../types"; + +import { TypeScriptZodRenderer } from "./TypeScriptZodRenderer"; + +export const typeScriptZodOptions = { + justSchema: new BooleanOption("just-schema", "Schema only", false), +}; + +export const typeScriptZodLanguageConfig = { + displayName: "TypeScript Zod", + names: ["typescript-zod"], + extension: "ts", +} as const; + +export class TypeScriptZodTargetLanguage extends TargetLanguage< + typeof typeScriptZodLanguageConfig +> { + public constructor() { + super(typeScriptZodLanguageConfig); + } + + public getOptions(): {} { + return {}; + } + + public get stringTypeMapping(): StringTypeMapping { + const mapping: Map = + new Map(); + const dateTimeType = "date-time"; + mapping.set("date-time", dateTimeType); + return mapping; + } + + public get supportsOptionalClassProperties(): boolean { + return true; + } + + protected makeRenderer( + renderContext: RenderContext, + untypedOptionValues: RendererOptions, + ): TypeScriptZodRenderer { + return new TypeScriptZodRenderer( + this, + renderContext, + getOptionValues(typeScriptZodOptions, untypedOptionValues), + ); + } +} diff --git a/packages/quicktype-core/src/language/index.ts b/packages/quicktype-core/src/language/index.ts new file mode 100644 index 000000000..38bac8e41 --- /dev/null +++ b/packages/quicktype-core/src/language/index.ts @@ -0,0 +1,34 @@ +export * from "./CJSON"; +export * from "./CPlusPlus"; +export * from "./Crystal"; +export * from "./CSharp"; +export * from "./Dart"; +export * from "./Elixir"; +export * from "./Elm"; +export * from "./Golang"; +export * from "./Haskell"; +export * from "./Java"; +export * from "./JavaScript"; +export * from "./JavaScriptPropTypes"; +export * from "./JSONSchema"; +export * from "./Kotlin"; +export * from "./Objective-C"; +export * from "./Php"; +export * from "./Pike"; +export * from "./Python"; +export * from "./Ruby"; +export * from "./Rust"; +export * from "./Scala3"; +export * from "./Smithy4s"; +export * from "./Swift"; +export * from "./TypeScriptFlow"; +export * from "./TypeScriptEffectSchema"; +export * from "./TypeScriptZod"; + +export { + all as defaultTargetLanguages, + languageNamed, + isLanguageName, +} from "./All"; +export type { LanguageName, LanguageDisplayName } from "./types"; +export type { RendererOptions } from "./options.types"; diff --git a/packages/quicktype-core/src/language/options.types.ts b/packages/quicktype-core/src/language/options.types.ts new file mode 100644 index 000000000..d3fa7d5aa --- /dev/null +++ b/packages/quicktype-core/src/language/options.types.ts @@ -0,0 +1,20 @@ +import type { OptionMap } from "../RendererOptions"; + +import type { LanguageName, LanguageNameMap } from "./types"; + +export type LanguageRawOptionMap = Readonly<{ + [Lang in keyof LanguageNameMap]: ReturnType< + LanguageNameMap[Lang]["getOptions"] + >; +}>; + +export type LanguageOptionMap = Readonly<{ + [Lang in keyof LanguageRawOptionMap]: OptionMap; +}>; + +export type RendererOptions< + Lang extends LanguageName = LanguageName, + Options = LanguageOptionMap[Lang], +> = { + -readonly [K in keyof Options]: Options[K]; +}; diff --git a/packages/quicktype-core/src/language/ruby/index.ts b/packages/quicktype-core/src/language/ruby/index.ts deleted file mode 100644 index 321e6cc58..000000000 --- a/packages/quicktype-core/src/language/ruby/index.ts +++ /dev/null @@ -1,706 +0,0 @@ -import unicode from "unicode-properties"; - -import { Sourcelike, modifySource } from "../../Source"; -import { Namer, Name } from "../../Naming"; -import { ConvenienceRenderer, ForbiddenWordsInfo } from "../../ConvenienceRenderer"; -import { TargetLanguage } from "../../TargetLanguage"; -import { Option, BooleanOption, EnumOption, OptionValues, getOptionValues, StringOption } from "../../RendererOptions"; - -import * as keywords from "./keywords"; - -const forbiddenForObjectProperties = Array.from(new Set([...keywords.keywords, ...keywords.reservedProperties])); - -import { Type, EnumType, ClassType, UnionType, ArrayType, MapType, ClassProperty } from "../../Type"; -import { matchType, nullableFromUnion, removeNullFromUnion } from "../../TypeUtils"; - -import { - legalizeCharacters, - splitIntoWords, - combineWords, - firstUpperWordStyle, - allUpperWordStyle, - allLowerWordStyle, - utf32ConcatMap, - isPrintable, - escapeNonPrintableMapper, - intToHex, - snakeCase, - isLetterOrUnderscore -} from "../../support/Strings"; -import { RenderContext } from "../../Renderer"; - -function unicodeEscape(codePoint: number): string { - return "\\u{" + intToHex(codePoint, 0) + "}"; -} - -const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, unicodeEscape)); - -export enum Strictness { - Strict = "Strict::", - Coercible = "Coercible::", - None = "Types::" -} - -export const rubyOptions = { - justTypes: new BooleanOption("just-types", "Plain types only", false), - strictness: new EnumOption("strictness", "Type strictness", [ - ["strict", Strictness.Strict], - ["coercible", Strictness.Coercible], - ["none", Strictness.None] - ]), - namespace: new StringOption("namespace", "Specify a wrapping Namespace", "NAME", "", "secondary") -}; - -export class RubyTargetLanguage extends TargetLanguage { - constructor() { - super("Ruby", ["ruby"], "rb"); - } - - protected getOptions(): Option[] { - return [rubyOptions.justTypes, rubyOptions.strictness, rubyOptions.namespace]; - } - - get supportsOptionalClassProperties(): boolean { - return true; - } - - protected get defaultIndentation(): string { - return " "; - } - - protected makeRenderer(renderContext: RenderContext, untypedOptionValues: { [name: string]: any }): RubyRenderer { - return new RubyRenderer(this, renderContext, getOptionValues(rubyOptions, untypedOptionValues)); - } -} - -const isStartCharacter = isLetterOrUnderscore; - -function isPartCharacter(utf16Unit: number): boolean { - const category: string = unicode.getCategory(utf16Unit); - return ["Nd", "Pc", "Mn", "Mc"].indexOf(category) >= 0 || isStartCharacter(utf16Unit); -} - -const legalizeName = legalizeCharacters(isPartCharacter); - -function simpleNameStyle(original: string, uppercase: boolean): string { - if (/^[0-9]+$/.test(original)) { - original = original + "N"; - } - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - uppercase ? firstUpperWordStyle : allLowerWordStyle, - uppercase ? firstUpperWordStyle : allLowerWordStyle, - allUpperWordStyle, - allUpperWordStyle, - "", - isStartCharacter - ); -} - -function memberNameStyle(original: string): string { - const words = splitIntoWords(original); - return combineWords( - words, - legalizeName, - allLowerWordStyle, - allLowerWordStyle, - allLowerWordStyle, - allLowerWordStyle, - "_", - isStartCharacter - ); -} - -export class RubyRenderer extends ConvenienceRenderer { - constructor( - targetLanguage: TargetLanguage, - renderContext: RenderContext, - private readonly _options: OptionValues - ) { - super(targetLanguage, renderContext); - } - - protected get commentLineStart(): string { - return "# "; - } - - protected get needsTypeDeclarationBeforeUse(): boolean { - return true; - } - - protected canBeForwardDeclared(t: Type): boolean { - return "class" === t.kind; - } - - protected forbiddenNamesForGlobalNamespace(): string[] { - return keywords.globals.concat(["Types", "JSON", "Dry", "Constructor", "Self"]); - } - - protected forbiddenForObjectProperties(_c: ClassType, _classNamed: Name): ForbiddenWordsInfo { - return { names: forbiddenForObjectProperties, includeGlobalForbidden: true }; - } - - protected makeNamedTypeNamer(): Namer { - return new Namer("types", n => simpleNameStyle(n, true), []); - } - - protected namerForObjectProperty(): Namer { - return new Namer("properties", memberNameStyle, []); - } - - protected makeUnionMemberNamer(): Namer { - return new Namer("properties", memberNameStyle, []); - } - - protected makeEnumCaseNamer(): Namer { - return new Namer("enum-cases", n => simpleNameStyle(n, true), []); - } - - private dryType(t: Type, isOptional = false): Sourcelike { - const optional = isOptional ? ".optional" : ""; - return matchType( - t, - _anyType => ["Types::Any", optional], - _nullType => ["Types::Nil", optional], - _boolType => ["Types::Bool", optional], - _integerType => ["Types::Integer", optional], - _doubleType => ["Types::Double", optional], - _stringType => ["Types::String", optional], - arrayType => ["Types.Array(", this.dryType(arrayType.items), ")", optional], - classType => [this.nameForNamedType(classType), optional], - mapType => ["Types::Hash.meta(of: ", this.dryType(mapType.values), ")", optional], - enumType => ["Types::", this.nameForNamedType(enumType), optional], - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return [this.dryType(nullable), ".optional"]; - } - return ["Types.Instance(", this.nameForNamedType(unionType), ")", optional]; - } - ); - } - - private exampleUse(t: Type, exp: Sourcelike, depth = 6, optional = false): Sourcelike { - if (depth-- <= 0) { - return exp; - } - - const safeNav = optional ? "&" : ""; - - return matchType( - t, - _anyType => exp, - _nullType => [exp, ".nil?"], - _boolType => exp, - _integerType => [exp, ".even?"], - _doubleType => exp, - _stringType => exp, - arrayType => this.exampleUse(arrayType.items, [exp, safeNav, ".first"], depth), - classType => { - let info: { name: Name; prop: ClassProperty } | undefined; - this.forEachClassProperty(classType, "none", (name, _json, prop) => { - if (["class", "map", "array"].indexOf(prop.type.kind) >= 0) { - info = { name, prop }; - } else if (info === undefined) { - info = { name, prop }; - } - }); - if (info !== undefined) { - return this.exampleUse(info.prop.type, [exp, safeNav, ".", info.name], depth, info.prop.isOptional); - } - return exp; - }, - mapType => this.exampleUse(mapType.values, [exp, safeNav, `["…"]`], depth), - enumType => { - let name: Name | undefined; - // FIXME: This is a terrible way to get the first enum case name. - this.forEachEnumCase(enumType, "none", theName => { - if (name === undefined) { - name = theName; - } - }); - if (name !== undefined) { - return [exp, " == ", this.nameForNamedType(enumType), "::", name]; - } - return exp; - }, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - if (["class", "map", "array"].indexOf(nullable.kind) >= 0) { - return this.exampleUse(nullable, exp, depth, true); - } - return [exp, ".nil?"]; - } - return exp; - } - ); - } - - private jsonSample(t: Type): Sourcelike { - function inner() { - if (t instanceof ArrayType) { - return "[…]"; - } else if (t instanceof MapType) { - return "{…}"; - } else if (t instanceof ClassType) { - return "{…}"; - } else { - return "…"; - } - } - return `"${inner()}"`; - } - - private fromDynamic(t: Type, e: Sourcelike, optional = false, castPrimitives = false): Sourcelike { - const primitiveCast = [this.dryType(t, optional), "[", e, "]"]; - const primitive = castPrimitives ? primitiveCast : e; - const safeAccess = optional ? "&" : ""; - return matchType( - t, - _anyType => primitive, - _nullType => primitive, - _boolType => primitive, - _integerType => primitive, - _doubleType => primitive, - _stringType => primitive, - arrayType => [e, safeAccess, ".map { |x| ", this.fromDynamic(arrayType.items, "x", false, true), " }"], - classType => { - const expression = [this.nameForNamedType(classType), ".from_dynamic!(", e, ")"]; - return optional ? [e, " ? ", expression, " : nil"] : expression; - }, - mapType => [ - ["Types::Hash", optional ? ".optional" : "", "[", e, "]"], - safeAccess, - ".map { |k, v| [k, ", - this.fromDynamic(mapType.values, "v", false, true), - "] }", - safeAccess, - ".to_h" - ], - enumType => { - const expression = ["Types::", this.nameForNamedType(enumType), "[", e, "]"]; - return optional ? [e, ".nil? ? nil : ", expression] : expression; - }, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return this.fromDynamic(nullable, e, true); - } - const expression = [this.nameForNamedType(unionType), ".from_dynamic!(", e, ")"]; - return optional ? [e, " ? ", expression, " : nil"] : expression; - } - ); - } - - private toDynamic(t: Type, e: Sourcelike, optional = false): Sourcelike { - if (this.marshalsImplicitlyToDynamic(t)) { - return e; - } - return matchType( - t, - _anyType => e, - _nullType => e, - _boolType => e, - _integerType => e, - _doubleType => e, - _stringType => e, - arrayType => [e, optional ? "&" : "", ".map { |x| ", this.toDynamic(arrayType.items, "x"), " }"], - _classType => [e, optional ? "&" : "", ".to_dynamic"], - mapType => [e, optional ? "&" : "", ".map { |k, v| [k, ", this.toDynamic(mapType.values, "v"), "] }.to_h"], - _enumType => e, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return this.toDynamic(nullable, e, true); - } - if (this.marshalsImplicitlyToDynamic(unionType)) { - return e; - } - return [e, optional ? "&" : "", ".to_dynamic"]; - } - ); - } - - private marshalsImplicitlyToDynamic(t: Type): boolean { - return matchType( - t, - _anyType => true, - _nullType => true, - _boolType => true, - _integerType => true, - _doubleType => true, - _stringType => true, - arrayType => this.marshalsImplicitlyToDynamic(arrayType.items), - _classType => false, - mapType => this.marshalsImplicitlyToDynamic(mapType.values), - _enumType => true, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return this.marshalsImplicitlyToDynamic(nullable); - } - return false; - } - ); - } - - // This is only to be used to allow class properties to possibly - // marshal implicitly. They are allowed to do this because they will - // be checked in Dry::Struct.new - private propertyTypeMarshalsImplicitlyFromDynamic(t: Type): boolean { - return matchType( - t, - _anyType => true, - _nullType => true, - _boolType => true, - _integerType => true, - _doubleType => true, - _stringType => true, - arrayType => this.propertyTypeMarshalsImplicitlyFromDynamic(arrayType.items), - _classType => false, - // Map properties must be checked because Dry:Types doesn't have a generic Map - _mapType => false, - _enumType => true, - unionType => { - const nullable = nullableFromUnion(unionType); - if (nullable !== null) { - return this.propertyTypeMarshalsImplicitlyFromDynamic(nullable); - } - return false; - } - ); - } - - private emitBlock(source: Sourcelike, emit: () => void) { - this.emitLine(source); - this.indent(emit); - this.emitLine("end"); - } - - private emitModule(emit: () => void) { - const emitModuleInner = (moduleName: string) => { - const [firstModule, ...subModules] = moduleName.split("::"); - if (subModules.length > 0) { - this.emitBlock(["module ", firstModule], () => { - emitModuleInner(subModules.join("::")); - }); - } else { - this.emitBlock(["module ", moduleName], emit); - } - }; - if (this._options.namespace !== undefined && this._options.namespace !== "") { - emitModuleInner(this._options.namespace); - } else { - emit(); - } - } - - private emitClass(c: ClassType, className: Name) { - this.emitDescription(this.descriptionForType(c)); - this.emitBlock(["class ", className, " < Dry::Struct"], () => { - let table: Sourcelike[][] = []; - let count = c.getProperties().size; - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const last = --count === 0; - const description = this.descriptionForClassProperty(c, jsonName); - const attribute = [ - ["attribute :", name, ","], - [" ", this.dryType(p.type), p.isOptional ? ".optional" : ""] - ]; - if (description !== undefined) { - if (table.length > 0) { - this.emitTable(table); - table = []; - } - this.ensureBlankLine(); - this.emitDescriptionBlock(description); - this.emitLine(attribute); - if (!last) { - this.ensureBlankLine(); - } - } else { - table.push(attribute); - } - }); - if (table.length > 0) { - this.emitTable(table); - } - - if (this._options.justTypes) { - return; - } - - this.ensureBlankLine(); - this.emitBlock(["def self.from_dynamic!(d)"], () => { - this.emitLine("d = Types::Hash[d]"); - this.emitLine("new("); - this.indent(() => { - const inits: Sourcelike[][] = []; - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const dynamic = p.isOptional - ? // If key is not found in hash, this will be nil - `d["${stringEscape(jsonName)}"]` - : // This will raise a runtime error if the key is not found in the hash - `d.fetch("${stringEscape(jsonName)}")`; - - if (this.propertyTypeMarshalsImplicitlyFromDynamic(p.type)) { - inits.push([ - [name, ": "], - [dynamic, ","] - ]); - } else { - const expression = this.fromDynamic(p.type, dynamic, p.isOptional); - inits.push([ - [name, ": "], - [expression, ","] - ]); - } - }); - this.emitTable(inits); - }); - this.emitLine(")"); - }); - - this.ensureBlankLine(); - this.emitBlock("def self.from_json!(json)", () => { - this.emitLine("from_dynamic!(JSON.parse(json))"); - }); - - this.ensureBlankLine(); - this.emitBlock(["def to_dynamic"], () => { - this.emitLine("{"); - this.indent(() => { - const inits: Sourcelike[][] = []; - this.forEachClassProperty(c, "none", (name, jsonName, p) => { - const expression = this.toDynamic(p.type, name, p.isOptional); - inits.push([[`"${stringEscape(jsonName)}"`], [" => ", expression, ","]]); - }); - this.emitTable(inits); - }); - this.emitLine("}"); - }); - this.ensureBlankLine(); - this.emitBlock("def to_json(options = nil)", () => { - this.emitLine("JSON.generate(to_dynamic, options)"); - }); - }); - } - - private emitEnum(e: EnumType, enumName: Name) { - this.emitDescription(this.descriptionForType(e)); - this.emitBlock(["module ", enumName], () => { - const table: Sourcelike[][] = []; - this.forEachEnumCase(e, "none", (name, json) => { - table.push([[name], [` = "${stringEscape(json)}"`]]); - }); - this.emitTable(table); - }); - } - - private emitUnion(u: UnionType, unionName: Name) { - this.emitDescription(this.descriptionForType(u)); - this.emitBlock(["class ", unionName, " < Dry::Struct"], () => { - const table: Sourcelike[][] = []; - this.forEachUnionMember(u, u.getChildren(), "none", null, (name, t) => { - table.push([["attribute :", name, ", "], [this.dryType(t, true)]]); - }); - this.emitTable(table); - - if (this._options.justTypes) { - return; - } - - this.ensureBlankLine(); - const [maybeNull, nonNulls] = removeNullFromUnion(u, false); - this.emitBlock("def self.from_dynamic!(d)", () => { - const memberNames = Array.from(u.getChildren()).map(member => this.nameForUnionMember(u, member)); - this.forEachUnionMember(u, u.getChildren(), "none", null, (name, t) => { - const nilMembers = memberNames - .filter(n => n !== name) - .map(memberName => [", ", memberName, ": nil"]); - if (this.propertyTypeMarshalsImplicitlyFromDynamic(t)) { - this.emitBlock(["if schema[:", name, "].right.valid? d"], () => { - this.emitLine("return new(", name, ": d", nilMembers, ")"); - }); - } else { - this.emitLine("begin"); - this.indent(() => { - this.emitLine("value = ", this.fromDynamic(t, "d")); - this.emitBlock(["if schema[:", name, "].right.valid? value"], () => { - this.emitLine("return new(", name, ": value", nilMembers, ")"); - }); - }); - this.emitLine("rescue"); - this.emitLine("end"); - } - }); - this.emitLine(`raise "Invalid union"`); - }); - - this.ensureBlankLine(); - this.emitBlock("def self.from_json!(json)", () => { - this.emitLine("from_dynamic!(JSON.parse(json))"); - }); - - this.ensureBlankLine(); - this.emitBlock("def to_dynamic", () => { - let first = true; - this.forEachUnionMember(u, nonNulls, "none", null, (name, t) => { - this.emitLine(first ? "if" : "elsif", " ", name, " != nil"); - this.indent(() => { - this.emitLine(this.toDynamic(t, name)); - }); - first = false; - }); - if (maybeNull !== null) { - this.emitLine("else"); - this.indent(() => { - this.emitLine("nil"); - }); - } - this.emitLine("end"); - }); - - this.ensureBlankLine(); - this.emitBlock("def to_json(options = nil)", () => { - this.emitLine("JSON.generate(to_dynamic, options)"); - }); - }); - } - - private emitTypesModule() { - this.emitBlock(["module Types"], () => { - this.emitLine("include Dry.Types(default: :nominal)"); - - const declarations: Sourcelike[][] = []; - - if (this._options.strictness !== Strictness.None) { - let has = { int: false, nil: false, bool: false, hash: false, string: false, double: false }; - this.forEachType(t => { - has = { - int: has.int || t.kind === "integer", - nil: has.nil || t.kind === "null", - bool: has.bool || t.kind === "bool", - hash: has.hash || t.kind === "map" || t.kind === "class", - string: has.string || t.kind === "string" || t.kind === "enum", - double: has.double || t.kind === "double" - }; - }); - if (has.int) declarations.push([["Integer"], [` = ${this._options.strictness}Integer`]]); - if (this._options.strictness === Strictness.Strict) { - if (has.nil) declarations.push([["Nil"], [` = ${this._options.strictness}Nil`]]); - } - if (has.bool) declarations.push([["Bool"], [` = ${this._options.strictness}Bool`]]); - if (has.hash) declarations.push([["Hash"], [` = ${this._options.strictness}Hash`]]); - if (has.string) declarations.push([["String"], [` = ${this._options.strictness}String`]]); - if (has.double) - declarations.push([ - ["Double"], - [` = ${this._options.strictness}Float | ${this._options.strictness}Integer`] - ]); - } - - this.forEachEnum("none", (enumType, enumName) => { - const cases: Sourcelike[][] = []; - this.forEachEnumCase(enumType, "none", (_name, json) => { - cases.push([cases.length === 0 ? "" : ", ", `"${stringEscape(json)}"`]); - }); - declarations.push([[enumName], [" = ", this._options.strictness, "String.enum(", ...cases, ")"]]); - }); - - if (declarations.length > 0) { - this.ensureBlankLine(); - this.emitTable(declarations); - } - }); - } - - protected emitSourceStructure() { - if (this.leadingComments !== undefined) { - this.emitCommentLines(this.leadingComments); - } else if (!this._options.justTypes) { - this.emitLine("# This code may look unusually verbose for Ruby (and it is), but"); - this.emitLine("# it performs some subtle and complex validation of JSON data."); - this.emitLine("#"); - this.emitLine("# To parse this JSON, add 'dry-struct' and 'dry-types' gems, then do:"); - this.emitLine("#"); - this.forEachTopLevel("none", (topLevel, name) => { - const variable = modifySource(snakeCase, name); - this.emitLine("# ", variable, " = ", name, ".from_json! ", this.jsonSample(topLevel)); - this.emitLine("# puts ", this.exampleUse(topLevel, variable)); - this.emitLine("#"); - }); - this.emitLine("# If from_json! succeeds, the value returned matches the schema."); - } - this.ensureBlankLine(); - - this.emitLine("require 'json'"); - this.emitLine("require 'dry-types'"); - this.emitLine("require 'dry-struct'"); - - this.ensureBlankLine(); - - this.emitModule(() => { - this.emitTypesModule(); - - this.forEachDeclaration("leading-and-interposing", decl => { - if (decl.kind === "forward") { - this.emitCommentLines(["(forward declaration)"]); - this.emitModule(() => { - this.emitLine("class ", this.nameForNamedType(decl.type), " < Dry::Struct; end"); - }); - } - }); - - this.forEachNamedType( - "leading-and-interposing", - (c: ClassType, n: Name) => this.emitClass(c, n), - (e, n) => this.emitEnum(e, n), - (u, n) => this.emitUnion(u, n) - ); - - if (!this._options.justTypes) { - this.forEachTopLevel( - "leading-and-interposing", - (topLevel, name) => { - const self = modifySource(snakeCase, name); - - // The json gem defines to_json on maps and primitives, so we only need to supply - // it for arrays. - const needsToJsonDefined = "array" === topLevel.kind; - - const classDeclaration = () => { - this.emitBlock(["class ", name], () => { - this.emitBlock(["def self.from_json!(json)"], () => { - if (needsToJsonDefined) { - this.emitLine( - self, - " = ", - this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)") - ); - this.emitBlock([self, ".define_singleton_method(:to_json) do"], () => { - this.emitLine("JSON.generate(", this.toDynamic(topLevel, "self"), ")"); - }); - this.emitLine(self); - } else { - this.emitLine( - this.fromDynamic(topLevel, "JSON.parse(json, quirks_mode: true)") - ); - } - }); - }); - }; - - this.emitModule(() => { - classDeclaration(); - }); - }, - t => this.namedTypeToNameForTopLevel(t) === undefined - ); - } - }); - } -} diff --git a/packages/quicktype-core/src/language/types.ts b/packages/quicktype-core/src/language/types.ts new file mode 100644 index 000000000..46af973bc --- /dev/null +++ b/packages/quicktype-core/src/language/types.ts @@ -0,0 +1,18 @@ +import type { TargetLanguage } from "../TargetLanguage"; + +import type { all } from "./All"; + +type AllLanguages = (typeof all)[number]; + +export type LanguageDisplayName< + Language extends TargetLanguage = AllLanguages, +> = Language["displayName"]; +export type LanguageName = + Language["names"][number]; + +export type LanguageDisplayNameMap = { + [Language in AllLanguages as LanguageDisplayName]: Language; +}; +export type LanguageNameMap = { + [Language in AllLanguages as LanguageName]: Language; +}; diff --git a/packages/quicktype-core/src/rewrites/CombineClasses.ts b/packages/quicktype-core/src/rewrites/CombineClasses.ts index 1f350644e..5c9562a85 100644 --- a/packages/quicktype-core/src/rewrites/CombineClasses.ts +++ b/packages/quicktype-core/src/rewrites/CombineClasses.ts @@ -1,27 +1,44 @@ -import { ClassType, Type, ClassProperty, setOperationCasesEqual } from "../Type"; -import { nonNullTypeCases, combineTypeAttributesOfTypes } from "../TypeUtils"; - -import { GraphRewriteBuilder } from "../GraphRewriting"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import type { RunContext } from "../Run"; import { assert, panic } from "../support/Support"; -import { TypeGraph, TypeRef } from "../TypeGraph"; +import { + type ClassProperty, + ClassType, + type Type, + setOperationCasesEqual, +} from "../Type/Type"; +import type { TypeGraph } from "../Type/TypeGraph"; +import type { TypeRef } from "../Type/TypeRef"; +import { + combineTypeAttributesOfTypes, + nonNullTypeCases, +} from "../Type/TypeUtils"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { RunContext } from "../Run"; const REQUIRED_OVERLAP = 3 / 4; -type Clique = { +interface Clique { members: ClassType[]; prototypes: ClassType[]; -}; +} // FIXME: Allow some type combinations to unify, like different enums, // enums with strings, integers with doubles, maps with objects of // the correct type. -function typeSetsCanBeCombined(s1: Iterable, s2: Iterable): boolean { - return setOperationCasesEqual(s1, s2, true, (a, b) => a.structurallyCompatible(b, true)); +function typeSetsCanBeCombined( + s1: Iterable, + s2: Iterable, +): boolean { + return setOperationCasesEqual(s1, s2, true, (a, b) => + a.structurallyCompatible(b, true), + ); } -function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boolean): boolean { +function canBeCombined( + c1: ClassType, + c2: ClassType, + onlyWithSameProperties: boolean, +): boolean { const p1 = c1.getProperties(); const p2 = c2.getProperties(); if (onlyWithSameProperties) { @@ -29,7 +46,10 @@ function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boo return false; } } else { - if (p1.size < p2.size * REQUIRED_OVERLAP || p2.size < p1.size * REQUIRED_OVERLAP) { + if ( + p1.size < p2.size * REQUIRED_OVERLAP || + p2.size < p1.size * REQUIRED_OVERLAP + ) { return false; } } @@ -63,29 +83,41 @@ function canBeCombined(c1: ClassType, c2: ClassType, onlyWithSameProperties: boo if (faults > maxFaults) break; } } + if (faults > maxFaults) return false; for (const name of commonProperties) { - let ts = smaller.get(name); - let tl = larger.get(name); + const ts = smaller.get(name); + const tl = larger.get(name); if (ts === undefined || tl === undefined) { return panic(`Both classes should have property ${name}`); } + const tsCases = nonNullTypeCases(ts.type); const tlCases = nonNullTypeCases(tl.type); - if (tsCases.size > 0 && tlCases.size > 0 && !typeSetsCanBeCombined(tsCases, tlCases)) { + if ( + tsCases.size > 0 && + tlCases.size > 0 && + !typeSetsCanBeCombined(tsCases, tlCases) + ) { return false; } } + return true; } -function tryAddToClique(c: ClassType, clique: Clique, onlyWithSameProperties: boolean): boolean { +function tryAddToClique( + c: ClassType, + clique: Clique, + onlyWithSameProperties: boolean, +): boolean { for (const prototype of clique.prototypes) { if (prototype.structurallyCompatible(c)) { clique.members.push(c); return true; } } + for (const prototype of clique.prototypes) { if (canBeCombined(prototype, c, onlyWithSameProperties)) { clique.prototypes.push(c); @@ -93,16 +125,19 @@ function tryAddToClique(c: ClassType, clique: Clique, onlyWithSameProperties: bo return true; } } + return false; } function findSimilarityCliques( graph: TypeGraph, onlyWithSameProperties: boolean, - includeFixedClasses: boolean + includeFixedClasses: boolean, ): ClassType[][] { - const classCandidates = Array.from(graph.allNamedTypesSeparated().objects).filter( - o => o instanceof ClassType && (includeFixedClasses || !o.isFixed) + const classCandidates = Array.from( + graph.allNamedTypesSeparated().objects, + ).filter( + (o) => o instanceof ClassType && (includeFixedClasses || !o.isFixed), ) as ClassType[]; const cliques: Clique[] = []; @@ -114,6 +149,7 @@ function findSimilarityCliques( break; } } + if (cliqueIndex === undefined) { // New clique cliqueIndex = cliques.length; @@ -128,7 +164,9 @@ function findSimilarityCliques( cliques[cliqueIndex] = tmp; } - return cliques.map(clique => clique.members).filter(cl => cl.length > 1); + return cliques + .map((clique) => clique.members) + .filter((cl) => cl.length > 1); } export function combineClasses( @@ -137,16 +175,16 @@ export function combineClasses( alphabetizeProperties: boolean, conflateNumbers: boolean, onlyWithSameProperties: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { const cliques = ctx.time(" find similarity cliques", () => - findSimilarityCliques(graph, onlyWithSameProperties, false) + findSimilarityCliques(graph, onlyWithSameProperties, false), ); function makeCliqueClass( clique: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { assert(clique.size > 0, "Clique can't be empty"); const attributes = combineTypeAttributesOfTypes("union", clique); @@ -156,7 +194,7 @@ export function combineClasses( builder, unionBuilderForUnification(builder, false, false, conflateNumbers), conflateNumbers, - forwardingRef + forwardingRef, ); } @@ -166,6 +204,6 @@ export function combineClasses( alphabetizeProperties, cliques, debugPrintReconstitution, - makeCliqueClass + makeCliqueClass, ); } diff --git a/packages/quicktype-core/src/rewrites/ExpandStrings.ts b/packages/quicktype-core/src/rewrites/ExpandStrings.ts index 9cb886d9e..47aab269a 100644 --- a/packages/quicktype-core/src/rewrites/ExpandStrings.ts +++ b/packages/quicktype-core/src/rewrites/ExpandStrings.ts @@ -1,22 +1,23 @@ import { + areEqual, iterableFirst, - mapFilter, - iterableSome, iterableReduce, - setUnion, + iterableSome, + mapFilter, setIntersect, setIsSuperset, - areEqual + setUnion, } from "collection-utils"; -import { PrimitiveType } from "../Type"; -import { stringTypesForType } from "../TypeUtils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { GraphRewriteBuilder } from "../GraphRewriting"; -import { assert, defined } from "../support/Support"; -import { emptyTypeAttributes } from "../attributes/TypeAttributes"; import { StringTypes } from "../attributes/StringTypes"; -import { RunContext } from "../Run"; +import { emptyTypeAttributes } from "../attributes/TypeAttributes"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import type { RunContext } from "../Run"; +import { assert, defined } from "../support/Support"; +import type { PrimitiveType } from "../Type/Type"; +import type { TypeGraph } from "../Type/TypeGraph"; +import type { TypeRef } from "../Type/TypeRef"; +import { stringTypesForType } from "../Type/TypeUtils"; const MIN_LENGTH_FOR_ENUM = 10; @@ -25,21 +26,25 @@ const REQUIRED_OVERLAP = 3 / 4; export type EnumInference = "none" | "all" | "infer"; -type EnumInfo = { +interface EnumInfo { cases: ReadonlySet; numValues: number; -}; +} function isOwnEnum({ numValues, cases }: EnumInfo): boolean { - return numValues >= MIN_LENGTH_FOR_ENUM && cases.size < Math.sqrt(numValues); + return ( + numValues >= MIN_LENGTH_FOR_ENUM && cases.size < Math.sqrt(numValues) + ); } function enumCasesOverlap( newCases: ReadonlySet, existingCases: ReadonlySet, - newAreSubordinate: boolean + newAreSubordinate: boolean, ): boolean { - const smaller = newAreSubordinate ? newCases.size : Math.min(newCases.size, existingCases.size); + const smaller = newAreSubordinate + ? newCases.size + : Math.min(newCases.size, existingCases.size); const overlap = setIntersect(newCases, existingCases).size; return overlap >= smaller * REQUIRED_OVERLAP; } @@ -48,15 +53,22 @@ function isAlwaysEmptyString(cases: string[]): boolean { return cases.length === 1 && cases[0] === ""; } -export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: EnumInference): TypeGraph { +export function expandStrings( + ctx: RunContext, + graph: TypeGraph, + inference: EnumInference, +): TypeGraph { const stringTypeMapping = ctx.stringTypeMapping; const allStrings = Array.from(graph.allTypesUnordered()).filter( - t => t.kind === "string" && stringTypesForType(t as PrimitiveType).isRestricted + (t) => + t.kind === "string" && + stringTypesForType(t as PrimitiveType).isRestricted, ) as PrimitiveType[]; function makeEnumInfo(t: PrimitiveType): EnumInfo | undefined { const stringTypes = stringTypesForType(t); - const mappedStringTypes = stringTypes.applyStringTypeMapping(stringTypeMapping); + const mappedStringTypes = + stringTypes.applyStringTypeMapping(stringTypeMapping); if (!mappedStringTypes.isRestricted) return undefined; const cases = defined(mappedStringTypes.cases); @@ -68,7 +80,10 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum const keys = Array.from(cases.keys()); if (isAlwaysEmptyString(keys)) return undefined; - const someCaseIsNotNumber = iterableSome(keys, key => /^(\-|\+)?[0-9]+(\.[0-9]+)?$/.test(key) === false); + const someCaseIsNotNumber = iterableSome( + keys, + (key) => /^[-+]?[0-9]+(\.[0-9]+)?$/.test(key) === false, + ); if (!someCaseIsNotNumber) return undefined; } @@ -76,7 +91,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum } const enumInfos = new Map(); - const enumSets: ReadonlySet[] = []; + const enumSets: Array> = []; if (inference !== "none") { for (const t of allStrings) { @@ -85,8 +100,15 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum enumInfos.set(t, enumInfo); } - function findOverlap(newCases: ReadonlySet, newAreSubordinate: boolean): number { - return enumSets.findIndex(s => enumCasesOverlap(newCases, s, newAreSubordinate)); + // FIXME: refactor this + // eslint-disable-next-line no-inner-declarations + function findOverlap( + newCases: ReadonlySet, + newAreSubordinate: boolean, + ): number { + return enumSets.findIndex((s) => + enumCasesOverlap(newCases, s, newAreSubordinate), + ); } // First, make case sets for all the enums that stand on their own. If @@ -117,6 +139,7 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum // Remove the ones we're done with. enumInfos.delete(t); } + if (inference === "all") { assert(enumInfos.size === 0); } @@ -141,16 +164,24 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum function replaceString( group: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { assert(group.size === 1); const t = defined(iterableFirst(group)); const stringTypes = stringTypesForType(t); - const attributes = mapFilter(t.getAttributes(), a => a !== stringTypes); - const mappedStringTypes = stringTypes.applyStringTypeMapping(stringTypeMapping); + const attributes = mapFilter( + t.getAttributes(), + (a) => a !== stringTypes, + ); + const mappedStringTypes = + stringTypes.applyStringTypeMapping(stringTypeMapping); if (!mappedStringTypes.isRestricted) { - return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); + return builder.getStringType( + attributes, + StringTypes.unrestricted, + forwardingRef, + ); } const setMatches = inference === "all" ? areEqual : setIsSuperset; @@ -159,17 +190,26 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum const cases = defined(mappedStringTypes.cases); if (cases.size > 0) { const keys = new Set(cases.keys()); - const fullCases = enumSets.find(s => setMatches(s, keys)); - if (inference !== "none" && !isAlwaysEmptyString(Array.from(keys)) && fullCases !== undefined) { + const fullCases = enumSets.find((s) => setMatches(s, keys)); + if ( + inference !== "none" && + !isAlwaysEmptyString(Array.from(keys)) && + fullCases !== undefined + ) { types.push(builder.getEnumType(emptyTypeAttributes, fullCases)); } else { - return builder.getStringType(attributes, StringTypes.unrestricted, forwardingRef); + return builder.getStringType( + attributes, + StringTypes.unrestricted, + forwardingRef, + ); } } + const transformations = mappedStringTypes.transformations; // FIXME: This is probably wrong, or at least overly conservative. This is for the case // where some attributes are identity ones, i.e. where we can't merge the primitive types, - // like it happens in the line after the `if`. The case where this occured was with URI + // like it happens in the line after the `if`. The case where this occurred was with URI // attributes: we had two separate string types with different URI attributes, but because // both are rewritten via `getPrimitiveType` below without any attributes, they end up // being the same string type. @@ -177,7 +217,12 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum const kind = defined(iterableFirst(transformations)); return builder.getPrimitiveType(kind, attributes, forwardingRef); } - types.push(...Array.from(transformations).map(k => builder.getPrimitiveType(k))); + + types.push( + ...Array.from(transformations).map((k) => + builder.getPrimitiveType(k), + ), + ); assert(types.length > 0, "We got an empty string type"); return builder.getUnionType(attributes, new Set(types), forwardingRef); } @@ -186,8 +231,8 @@ export function expandStrings(ctx: RunContext, graph: TypeGraph, inference: Enum "expand strings", stringTypeMapping, false, - allStrings.map(t => [t]), + allStrings.map((t) => [t]), ctx.debugPrintReconstitution, - replaceString + replaceString, ); } diff --git a/packages/quicktype-core/src/rewrites/FlattenStrings.ts b/packages/quicktype-core/src/rewrites/FlattenStrings.ts index b700073f5..077ba2de1 100644 --- a/packages/quicktype-core/src/rewrites/FlattenStrings.ts +++ b/packages/quicktype-core/src/rewrites/FlattenStrings.ts @@ -1,12 +1,16 @@ import { iterableFirst } from "collection-utils"; -import { PrimitiveType, UnionType, Type } from "../Type"; -import { stringTypesForType, combineTypeAttributesOfTypes } from "../TypeUtils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; -import { assert, defined } from "../support/Support"; import { combineTypeAttributes } from "../attributes/TypeAttributes"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import { assert, defined } from "../support/Support"; +import type { PrimitiveType, Type, UnionType } from "../Type/Type"; +import type { StringTypeMapping } from "../Type/TypeBuilderUtils"; +import type { TypeGraph } from "../Type/TypeGraph"; +import type { TypeRef } from "../Type/TypeRef"; +import { + combineTypeAttributesOfTypes, + stringTypesForType, +} from "../Type/TypeUtils"; // A union needs replacing if it contains more than one string type, one of them being // a basic string type. @@ -17,7 +21,7 @@ function unionNeedsReplacing(u: UnionType): ReadonlySet | undefined { if (stringType === undefined) return undefined; assert( !stringTypesForType(stringType as PrimitiveType).isRestricted, - "We must only flatten strings if we have no restriced strings" + "We must only flatten strings if we have no restriced strings", ); return stringMembers; } @@ -26,43 +30,52 @@ function unionNeedsReplacing(u: UnionType): ReadonlySet | undefined { function replaceUnion( group: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { assert(group.size === 1); const u = defined(iterableFirst(group)); const stringMembers = defined(unionNeedsReplacing(u)); - const stringAttributes = combineTypeAttributesOfTypes("union", stringMembers); + const stringAttributes = combineTypeAttributesOfTypes( + "union", + stringMembers, + ); const types: TypeRef[] = []; for (const t of u.members) { if (stringMembers.has(t)) continue; types.push(builder.reconstituteType(t)); } + if (types.length === 0) { return builder.getStringType( combineTypeAttributes("union", stringAttributes, u.getAttributes()), undefined, - forwardingRef + forwardingRef, ); } + types.push(builder.getStringType(stringAttributes, undefined)); - return builder.getUnionType(u.getAttributes(), new Set(types), forwardingRef); + return builder.getUnionType( + u.getAttributes(), + new Set(types), + forwardingRef, + ); } export function flattenStrings( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { const allUnions = graph.allNamedTypesSeparated().unions; const unionsToReplace = Array.from(allUnions) .filter(unionNeedsReplacing) - .map(t => [t]); + .map((t) => [t]); return graph.rewrite( "flatten strings", stringTypeMapping, false, unionsToReplace, debugPrintReconstitution, - replaceUnion + replaceUnion, ); } diff --git a/packages/quicktype-core/src/rewrites/FlattenUnions.ts b/packages/quicktype-core/src/rewrites/FlattenUnions.ts index a88dca2e8..73e0df28a 100644 --- a/packages/quicktype-core/src/rewrites/FlattenUnions.ts +++ b/packages/quicktype-core/src/rewrites/FlattenUnions.ts @@ -1,43 +1,73 @@ -import { setFilter, iterableSome } from "collection-utils"; +import { iterableSome, setFilter } from "collection-utils"; -import { TypeGraph, TypeRef, derefTypeRef } from "../TypeGraph"; -import { Type, UnionType, IntersectionType } from "../Type"; -import { makeGroupsToFlatten } from "../TypeUtils"; -import { assert } from "../support/Support"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; -import { unifyTypes, UnifyUnionBuilder } from "../UnifyClasses"; -import { messageAssert } from "../Messages"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import { messageAssert } from "../Messages"; +import { assert } from "../support/Support"; +import { IntersectionType, type Type, UnionType } from "../Type/Type"; +import type { StringTypeMapping } from "../Type/TypeBuilderUtils"; +import type { TypeGraph } from "../Type/TypeGraph"; +import { type TypeRef, derefTypeRef } from "../Type/TypeRef"; +import { makeGroupsToFlatten } from "../Type/TypeUtils"; +import { UnifyUnionBuilder, unifyTypes } from "../UnifyClasses"; export function flattenUnions( graph: TypeGraph, stringTypeMapping: StringTypeMapping, conflateNumbers: boolean, makeObjectTypes: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): [TypeGraph, boolean] { let needsRepeat = false; - function replace(types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { - const unionBuilder = new UnifyUnionBuilder(builder, makeObjectTypes, true, trefs => { - assert(trefs.length > 0, "Must have at least one type to build union"); - trefs = trefs.map(tref => builder.reconstituteType(derefTypeRef(tref, graph))); - if (trefs.length === 1) { - return trefs[0]; - } - needsRepeat = true; - return builder.getUnionType(emptyTypeAttributes, new Set(trefs)); - }); - return unifyTypes(types, emptyTypeAttributes, builder, unionBuilder, conflateNumbers, forwardingRef); + function replace( + types: ReadonlySet, + builder: GraphRewriteBuilder, + forwardingRef: TypeRef, + ): TypeRef { + const unionBuilder = new UnifyUnionBuilder( + builder, + makeObjectTypes, + true, + (trefs) => { + assert( + trefs.length > 0, + "Must have at least one type to build union", + ); + trefs = trefs.map((tref) => + builder.reconstituteType(derefTypeRef(tref, graph)), + ); + if (trefs.length === 1) { + return trefs[0]; + } + + needsRepeat = true; + return builder.getUnionType( + emptyTypeAttributes, + new Set(trefs), + ); + }, + ); + return unifyTypes( + types, + emptyTypeAttributes, + builder, + unionBuilder, + conflateNumbers, + forwardingRef, + ); } - const allUnions = setFilter(graph.allTypesUnordered(), t => t instanceof UnionType) as Set; - const nonCanonicalUnions = setFilter(allUnions, u => !u.isCanonical); + const allUnions = setFilter( + graph.allTypesUnordered(), + (t) => t instanceof UnionType, + ) as Set; + const nonCanonicalUnions = setFilter(allUnions, (u) => !u.isCanonical); let foundIntersection = false; - const groups = makeGroupsToFlatten(nonCanonicalUnions, members => { + const groups = makeGroupsToFlatten(nonCanonicalUnions, (members) => { messageAssert(members.size > 0, "IRNoEmptyUnions", {}); - if (!iterableSome(members, m => m instanceof IntersectionType)) return true; + if (!iterableSome(members, (m) => m instanceof IntersectionType)) + return true; // FIXME: This is stupid. `flattenUnions` returns true when no more union // flattening is necessary, but `resolveIntersections` can introduce new @@ -49,7 +79,14 @@ export function flattenUnions( foundIntersection = true; return false; }); - graph = graph.rewrite("flatten unions", stringTypeMapping, false, groups, debugPrintReconstitution, replace); + graph = graph.rewrite( + "flatten unions", + stringTypeMapping, + false, + groups, + debugPrintReconstitution, + replace, + ); // console.log(`flattened ${nonCanonicalUnions.size} of ${unions.size} unions`); return [graph, !needsRepeat && !foundIntersection]; diff --git a/packages/quicktype-core/src/rewrites/InferMaps.ts b/packages/quicktype-core/src/rewrites/InferMaps.ts index 9190b043b..db81aefb1 100644 --- a/packages/quicktype-core/src/rewrites/InferMaps.ts +++ b/packages/quicktype-core/src/rewrites/InferMaps.ts @@ -1,13 +1,20 @@ -import { iterableFirst, iterableEvery, setMap } from "collection-utils"; +import { iterableEvery, iterableFirst, setMap } from "collection-utils"; -import { Type, ClassType, setOperationCasesEqual, ClassProperty, isPrimitiveStringTypeKind } from "../Type"; -import { removeNullFromType } from "../TypeUtils"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import { type MarkovChain, evaluate, load } from "../MarkovChain"; import { defined, panic } from "../support/Support"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; +import { + type ClassProperty, + ClassType, + type Type, + isPrimitiveStringTypeKind, + setOperationCasesEqual, +} from "../Type"; +import type { StringTypeMapping } from "../Type/TypeBuilderUtils"; +import type { TypeGraph } from "../Type/TypeGraph"; +import type { TypeRef } from "../Type/TypeRef"; +import { removeNullFromType } from "../Type/TypeUtils"; import { unifyTypes, unionBuilderForUnification } from "../UnifyClasses"; -import { MarkovChain, load, evaluate } from "../MarkovChain"; const mapSizeThreshold = 20; const stringMapSizeThreshold = 50; @@ -18,10 +25,13 @@ function nameProbability(name: string): number { if (markovChain === undefined) { markovChain = load(); } + return evaluate(markovChain, name); } -function shouldBeMap(properties: ReadonlyMap): ReadonlySet | undefined { +function shouldBeMap( + properties: ReadonlyMap, +): ReadonlySet | undefined { // Only classes with a certain number of properties are inferred // as maps. const numProperties = properties.size; @@ -29,15 +39,20 @@ function shouldBeMap(properties: ReadonlyMap): ReadonlySe // If all property names are digit-only, we always make a map, no // questions asked. - if (iterableEvery(properties.keys(), n => /^[0-9]+$/.test(n))) { - return setMap(properties.values(), cp => cp.type); + if (iterableEvery(properties.keys(), (n) => /^[0-9]+$/.test(n))) { + return setMap(properties.values(), (cp) => cp.type); } // If all properties are strings or null then an object must have at least // `stringMapSizeThreshold` to qualify as a map. if ( numProperties < stringMapSizeThreshold && - iterableEvery(properties.values(), cp => isPrimitiveStringTypeKind(cp.type.kind) || cp.type.kind === "null") + iterableEvery( + properties.values(), + (cp) => + isPrimitiveStringTypeKind(cp.type.kind) || + cp.type.kind === "null", + ) ) { return undefined; } @@ -62,7 +77,9 @@ function shouldBeMap(properties: ReadonlyMap): ReadonlySe // trigger-happy. const exponent = 5; const scale = Math.pow(22, exponent); - const limit = Math.pow(numProperties + 2, exponent) / scale + (0.0025 - Math.pow(3, exponent) / scale); + const limit = + Math.pow(numProperties + 2, exponent) / scale + + (0.0025 - Math.pow(3, exponent) / scale); if (probability > limit) return undefined; } @@ -86,7 +103,14 @@ function shouldBeMap(properties: ReadonlyMap): ReadonlySe if (firstNonNullCases !== undefined) { // The set of non-null cases for all other properties must // be the the same, otherwise we won't infer a map. - if (!setOperationCasesEqual(nn, firstNonNullCases, true, (a, b) => a.structurallyCompatible(b, true))) { + if ( + !setOperationCasesEqual( + nn, + firstNonNullCases, + true, + (a, b) => a.structurallyCompatible(b, true), + ) + ) { canBeMap = false; break; } @@ -94,11 +118,14 @@ function shouldBeMap(properties: ReadonlyMap): ReadonlySe firstNonNullCases = nn; } } + allCases.add(p.type); } + if (!canBeMap) { return undefined; } + return allCases; } @@ -106,19 +133,21 @@ export function inferMaps( graph: TypeGraph, stringTypeMapping: StringTypeMapping, conflateNumbers: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { function replaceClass( setOfOneClass: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { const c = defined(iterableFirst(setOfOneClass)); const properties = c.getProperties(); const shouldBe = shouldBeMap(properties); if (shouldBe === undefined) { - return panic(`We shouldn't be replacing class ${c.getCombinedName()} with a map`); + return panic( + `We shouldn't be replacing class ${c.getCombinedName()} with a map`, + ); } // Now reconstitute all the types in the new graph. TypeGraphs are @@ -133,14 +162,21 @@ export function inferMaps( shouldBe, c.getAttributes(), builder, - unionBuilderForUnification(builder, false, false, conflateNumbers), - conflateNumbers + unionBuilderForUnification( + builder, + false, + false, + conflateNumbers, + ), + conflateNumbers, ), - forwardingRef + forwardingRef, ); } - const classesToReplace = Array.from(graph.allNamedTypesSeparated().objects).filter(o => { + const classesToReplace = Array.from( + graph.allNamedTypesSeparated().objects, + ).filter((o) => { if (!(o instanceof ClassType)) return false; return !o.isFixed && shouldBeMap(o.getProperties()) !== undefined; }) as ClassType[]; @@ -148,8 +184,8 @@ export function inferMaps( "infer maps", stringTypeMapping, false, - classesToReplace.map(c => [c]), + classesToReplace.map((c) => [c]), debugPrintReconstitution, - replaceClass + replaceClass, ); } diff --git a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts index a9245fe38..d1aadc06d 100644 --- a/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts +++ b/packages/quicktype-core/src/rewrites/ReplaceObjectType.ts @@ -1,23 +1,24 @@ -import { setFilter, iterableFirst, mapMap, setMap } from "collection-utils"; +import { iterableFirst, mapMap, setFilter, setMap } from "collection-utils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping } from "../TypeBuilder"; -import { GraphRewriteBuilder } from "../GraphRewriting"; -import { ObjectType, ClassProperty } from "../Type"; -import { defined } from "../support/Support"; import { emptyTypeAttributes } from "../attributes/TypeAttributes"; +import type { GraphRewriteBuilder } from "../GraphRewriting"; +import { defined } from "../support/Support"; +import type { ClassProperty, ObjectType } from "../Type/Type"; +import type { StringTypeMapping } from "../Type/TypeBuilderUtils"; +import type { TypeGraph } from "../Type/TypeGraph"; +import type { TypeRef } from "../Type/TypeRef"; export function replaceObjectType( graph: TypeGraph, stringTypeMapping: StringTypeMapping, _conflateNumbers: boolean, leaveFullObjects: boolean, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): TypeGraph { function replace( setOfOneType: ReadonlySet, builder: GraphRewriteBuilder, - forwardingRef: TypeRef + forwardingRef: TypeRef, ): TypeRef { const o = defined(iterableFirst(setOfOneType)); const attributes = o.getAttributes(); @@ -25,13 +26,21 @@ export function replaceObjectType( const additionalProperties = o.getAdditionalProperties(); function reconstituteProperties(): ReadonlyMap { - return mapMap(properties, cp => - builder.makeClassProperty(builder.reconstituteTypeRef(cp.typeRef), cp.isOptional) + return mapMap(properties, (cp) => + builder.makeClassProperty( + builder.reconstituteTypeRef(cp.typeRef), + cp.isOptional, + ), ); } function makeClass(): TypeRef { - return builder.getUniqueClassType(attributes, true, reconstituteProperties(), forwardingRef); + return builder.getUniqueClassType( + attributes, + true, + reconstituteProperties(), + forwardingRef, + ); } function reconstituteAdditionalProperties(): TypeRef { @@ -43,7 +52,11 @@ export function replaceObjectType( } if (properties.size === 0) { - return builder.getMapType(attributes, reconstituteAdditionalProperties(), forwardingRef); + return builder.getMapType( + attributes, + reconstituteAdditionalProperties(), + forwardingRef, + ); } if (additionalProperties.kind === "any") { @@ -53,11 +66,20 @@ export function replaceObjectType( } // FIXME: Warn that we're losing class semantics. - const propertyTypes = setMap(properties.values(), cp => cp.type).add(additionalProperties); - let union = builder.lookupTypeRefs(Array.from(propertyTypes).map(t => t.typeRef)); + const propertyTypes = setMap(properties.values(), (cp) => cp.type).add( + additionalProperties, + ); + let union = builder.lookupTypeRefs( + Array.from(propertyTypes).map((t) => t.typeRef), + ); if (union === undefined) { - const reconstitutedTypes = setMap(propertyTypes, t => builder.reconstituteType(t)); - union = builder.getUniqueUnionType(emptyTypeAttributes, new Set(reconstitutedTypes)); + const reconstitutedTypes = setMap(propertyTypes, (t) => + builder.reconstituteType(t), + ); + union = builder.getUniqueUnionType( + emptyTypeAttributes, + new Set(reconstitutedTypes), + ); // This is the direct unification alternative. Weirdly enough, it is a tiny // bit slower. It gives the same results. @@ -75,10 +97,25 @@ export function replaceObjectType( return builder.getMapType(attributes, union, forwardingRef); } - const allObjectTypes = setFilter(graph.allTypesUnordered(), t => t.kind === "object") as Set; + const allObjectTypes = setFilter( + graph.allTypesUnordered(), + (t) => t.kind === "object", + ) as Set; const objectTypesToReplace = leaveFullObjects - ? setFilter(allObjectTypes, o => o.getProperties().size === 0 || o.getAdditionalProperties() === undefined) + ? setFilter( + allObjectTypes, + (o) => + o.getProperties().size === 0 || + o.getAdditionalProperties() === undefined, + ) : allObjectTypes; - const groups = Array.from(objectTypesToReplace).map(t => [t]); - return graph.rewrite("replace object type", stringTypeMapping, false, groups, debugPrintReconstitution, replace); + const groups = Array.from(objectTypesToReplace).map((t) => [t]); + return graph.rewrite( + "replace object type", + stringTypeMapping, + false, + groups, + debugPrintReconstitution, + replace, + ); } diff --git a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts index c68159828..cf59817ec 100644 --- a/packages/quicktype-core/src/rewrites/ResolveIntersections.ts +++ b/packages/quicktype-core/src/rewrites/ResolveIntersections.ts @@ -1,64 +1,90 @@ +/* eslint-disable @typescript-eslint/brace-style */ import { - iterableFirst, iterableEvery, - setFilter, + iterableFind, + iterableFirst, + mapMap, mapMapEntries, mapMergeWithInto, - mapMap, mapUpdateInto, - setMap, - iterableFind, + setFilter, setIntersect, - setUnionInto + setMap, + setUnionInto, } from "collection-utils"; -import { TypeGraph, TypeRef } from "../TypeGraph"; -import { StringTypeMapping, TypeBuilder } from "../TypeBuilder"; -import { GraphRewriteBuilder, TypeLookerUp } from "../GraphRewriting"; -import { UnionTypeProvider, UnionBuilder, TypeAttributeMap } from "../UnionBuilder"; import { + type TypeAttributes, + combineTypeAttributes, + emptyTypeAttributes, + makeTypeAttributesInferred, +} from "../attributes/TypeAttributes"; +import type { GraphRewriteBuilder, TypeLookerUp } from "../GraphRewriting"; +import { assert, defined, mustNotHappen, panic } from "../support/Support"; +import { + ArrayType, + GenericClassProperty, IntersectionType, - Type, + ObjectType, + type PrimitiveTypeKind, + type Type, + type TypeKind, UnionType, - PrimitiveTypeKind, - ArrayType, - isPrimitiveTypeKind, isNumberTypeKind, - GenericClassProperty, - TypeKind, - ObjectType + isPrimitiveTypeKind, } from "../Type"; -import { setOperationMembersRecursively, matchTypeExhaustive, makeGroupsToFlatten } from "../TypeUtils"; -import { assert, defined, panic, mustNotHappen } from "../support/Support"; +import type { TypeBuilder } from "../Type/TypeBuilder"; +import type { StringTypeMapping } from "../Type/TypeBuilderUtils"; +import type { TypeGraph } from "../Type/TypeGraph"; +import type { TypeRef } from "../Type/TypeRef"; import { - combineTypeAttributes, - TypeAttributes, - emptyTypeAttributes, - makeTypeAttributesInferred -} from "../attributes/TypeAttributes"; + makeGroupsToFlatten, + matchTypeExhaustive, + setOperationMembersRecursively, +} from "../Type/TypeUtils"; +import { + type TypeAttributeMap, + UnionBuilder, + type UnionTypeProvider, +} from "../UnionBuilder"; function canResolve(t: IntersectionType): boolean { const members = setOperationMembersRecursively(t, undefined)[0]; if (members.size <= 1) return true; - return iterableEvery(members, m => !(m instanceof UnionType) || m.isCanonical); + return iterableEvery( + members, + (m) => !(m instanceof UnionType) || m.isCanonical, + ); } -function attributesForTypes(types: ReadonlySet): TypeAttributeMap { - return mapMapEntries(types.entries(), t => [t.kind, t.getAttributes()] as [T, TypeAttributes]); +function attributesForTypes( + types: ReadonlySet, +): TypeAttributeMap { + return mapMapEntries( + types.entries(), + (t) => [t.kind, t.getAttributes()] as [T, TypeAttributes], + ); } type PropertyMap = Map>>; class IntersectionAccumulator - implements UnionTypeProvider, [PropertyMap, ReadonlySet | undefined] | undefined> + implements + UnionTypeProvider< + ReadonlySet, + [PropertyMap, ReadonlySet | undefined] | undefined + > { private _primitiveTypes: Set | undefined; - private readonly _primitiveAttributes: TypeAttributeMap = new Map(); + + private readonly _primitiveAttributes: TypeAttributeMap = + new Map(); // * undefined: We haven't seen any types yet. // * Set: All types we've seen can be arrays. // * false: At least one of the types seen can't be an array. private _arrayItemTypes: Set | undefined | false; + private _arrayAttributes: TypeAttributes = emptyTypeAttributes; // We start out with all object types allowed, which means @@ -70,27 +96,40 @@ class IntersectionAccumulator // undefined, no object types are allowed, in which case // _additionalPropertyTypes must also be undefined; private _objectProperties: PropertyMap | undefined = new Map(); + private _objectAttributes: TypeAttributes = emptyTypeAttributes; + private _additionalPropertyTypes: Set | undefined = new Set(); private _lostTypeAttributes = false; private updatePrimitiveTypes(members: Iterable): void { - const types = setFilter(members, t => isPrimitiveTypeKind(t.kind)); + const types = setFilter(members, (t) => isPrimitiveTypeKind(t.kind)); const attributes = attributesForTypes(types); - mapMergeWithInto(this._primitiveAttributes, (a, b) => combineTypeAttributes("intersect", a, b), attributes); + mapMergeWithInto( + this._primitiveAttributes, + (a, b) => combineTypeAttributes("intersect", a, b), + attributes, + ); - const kinds = setMap(types, t => t.kind) as ReadonlySet; + const kinds = setMap( + types, + (t) => t.kind, + ) as ReadonlySet; if (this._primitiveTypes === undefined) { this._primitiveTypes = new Set(kinds); return; } const haveNumber = - iterableFind(this._primitiveTypes, isNumberTypeKind) !== undefined && + iterableFind(this._primitiveTypes, isNumberTypeKind) !== + undefined && iterableFind(kinds, isNumberTypeKind) !== undefined; this._primitiveTypes = setIntersect(this._primitiveTypes, kinds); - if (haveNumber && iterableFind(this._primitiveTypes, isNumberTypeKind) === undefined) { + if ( + haveNumber && + iterableFind(this._primitiveTypes, isNumberTypeKind) === undefined + ) { // One set has integer, the other has double. The intersection // of that is integer. this._primitiveTypes = this._primitiveTypes.add("integer"); @@ -98,13 +137,20 @@ class IntersectionAccumulator } private updateArrayItemTypes(members: Iterable): void { - const maybeArray = iterableFind(members, t => t instanceof ArrayType) as ArrayType | undefined; + const maybeArray = iterableFind( + members, + (t) => t instanceof ArrayType, + ) as ArrayType | undefined; if (maybeArray === undefined) { this._arrayItemTypes = false; return; } - this._arrayAttributes = combineTypeAttributes("intersect", this._arrayAttributes, maybeArray.getAttributes()); + this._arrayAttributes = combineTypeAttributes( + "intersect", + this._arrayAttributes, + maybeArray.getAttributes(), + ); if (this._arrayItemTypes === undefined) { this._arrayItemTypes = new Set(); @@ -114,7 +160,10 @@ class IntersectionAccumulator } private updateObjectProperties(members: Iterable): void { - const maybeObject = iterableFind(members, t => t instanceof ObjectType) as ObjectType | undefined; + const maybeObject = iterableFind( + members, + (t) => t instanceof ObjectType, + ) as ObjectType | undefined; if (maybeObject === undefined) { this._objectProperties = undefined; this._additionalPropertyTypes = undefined; @@ -124,9 +173,10 @@ class IntersectionAccumulator this._objectAttributes = combineTypeAttributes( "intersect", this._objectAttributes, - maybeObject.getAttributes() + maybeObject.getAttributes(), ); - const objectAdditionalProperties = maybeObject.getAdditionalProperties(); + const objectAdditionalProperties = + maybeObject.getAdditionalProperties(); if (this._objectProperties === undefined) { assert(this._additionalPropertyTypes === undefined); @@ -135,7 +185,7 @@ class IntersectionAccumulator const allPropertyNames = setUnionInto( new Set(this._objectProperties.keys()), - maybeObject.getProperties().keys() + maybeObject.getProperties().keys(), ); for (const name of allPropertyNames) { const existing = defined(this._objectProperties).get(name); @@ -144,31 +194,48 @@ class IntersectionAccumulator if (existing !== undefined && newProperty !== undefined) { const cp = new GenericClassProperty( existing.typeData.add(newProperty.type), - existing.isOptional && newProperty.isOptional + existing.isOptional && newProperty.isOptional, ); defined(this._objectProperties).set(name, cp); - } else if (existing !== undefined && objectAdditionalProperties !== undefined) { + } else if ( + existing !== undefined && + objectAdditionalProperties !== undefined + ) { const cp = new GenericClassProperty( existing.typeData.add(objectAdditionalProperties), - existing.isOptional + existing.isOptional, ); defined(this._objectProperties).set(name, cp); } else if (existing !== undefined) { defined(this._objectProperties).delete(name); - } else if (newProperty !== undefined && this._additionalPropertyTypes !== undefined) { + } else if ( + newProperty !== undefined && + this._additionalPropertyTypes !== undefined + ) { // FIXME: This is potentially slow - const types = new Set(this._additionalPropertyTypes).add(newProperty.type); - defined(this._objectProperties).set(name, new GenericClassProperty(types, newProperty.isOptional)); + const types = new Set(this._additionalPropertyTypes).add( + newProperty.type, + ); + defined(this._objectProperties).set( + name, + new GenericClassProperty(types, newProperty.isOptional), + ); } else if (newProperty !== undefined) { defined(this._objectProperties).delete(name); } else { - return mustNotHappen(); + mustNotHappen(); } } - if (this._additionalPropertyTypes !== undefined && objectAdditionalProperties !== undefined) { + if ( + this._additionalPropertyTypes !== undefined && + objectAdditionalProperties !== undefined + ) { this._additionalPropertyTypes.add(objectAdditionalProperties); - } else if (this._additionalPropertyTypes !== undefined || objectAdditionalProperties !== undefined) { + } else if ( + this._additionalPropertyTypes !== undefined || + objectAdditionalProperties !== undefined + ) { this._additionalPropertyTypes = undefined; this._lostTypeAttributes = true; } @@ -180,46 +247,64 @@ class IntersectionAccumulator this.updateObjectProperties(members); } - addType(t: Type): TypeAttributes { + public addType(t: Type): TypeAttributes { let attributes = t.getAttributes(); - matchTypeExhaustive( + matchTypeExhaustive( t, - _noneType => { + (_noneType) => { return panic("There shouldn't be a none type"); }, - _anyType => { - return panic("The any type should have been filtered out in setOperationMembersRecursively"); + (_anyType) => { + return panic( + "The any type should have been filtered out in setOperationMembersRecursively", + ); }, - nullType => this.addUnionSet([nullType]), - boolType => this.addUnionSet([boolType]), - integerType => this.addUnionSet([integerType]), - doubleType => this.addUnionSet([doubleType]), - stringType => this.addUnionSet([stringType]), - arrayType => this.addUnionSet([arrayType]), - _classType => panic("We should never see class types in intersections"), - _mapType => panic("We should never see map types in intersections"), - objectType => this.addUnionSet([objectType]), - _enumType => panic("We should never see enum types in intersections"), - unionType => { + (nullType) => this.addUnionSet([nullType]), + (boolType) => this.addUnionSet([boolType]), + (integerType) => this.addUnionSet([integerType]), + (doubleType) => this.addUnionSet([doubleType]), + (stringType) => this.addUnionSet([stringType]), + (arrayType) => this.addUnionSet([arrayType]), + (_classType) => + panic("We should never see class types in intersections"), + (_mapType) => + panic("We should never see map types in intersections"), + (objectType) => this.addUnionSet([objectType]), + (_enumType) => + panic("We should never see enum types in intersections"), + (unionType) => { attributes = combineTypeAttributes( "intersect", - [attributes].concat(Array.from(unionType.members).map(m => m.getAttributes())) + [attributes].concat( + Array.from(unionType.members).map((m) => + m.getAttributes(), + ), + ), ); this.addUnionSet(unionType.members); }, - transformedStringType => this.addUnionSet([transformedStringType]) + (transformedStringType) => + this.addUnionSet([transformedStringType]), ); return makeTypeAttributesInferred(attributes); } - get arrayData(): ReadonlySet { - if (this._arrayItemTypes === undefined || this._arrayItemTypes === false) { - return panic("This should not be called if the type can't be an array"); + public get arrayData(): ReadonlySet { + if ( + this._arrayItemTypes === undefined || + this._arrayItemTypes === false + ) { + return panic( + "This should not be called if the type can't be an array", + ); } + return this._arrayItemTypes; } - get objectData(): [PropertyMap, ReadonlySet | undefined] | undefined { + public get objectData(): + | [PropertyMap, ReadonlySet | undefined] + | undefined { if (this._objectProperties === undefined) { assert(this._additionalPropertyTypes === undefined); return undefined; @@ -228,24 +313,36 @@ class IntersectionAccumulator return [this._objectProperties, this._additionalPropertyTypes]; } - get enumCases(): ReadonlySet { + public get enumCases(): ReadonlySet { return panic("We don't support enums in intersections"); } - getMemberKinds(): TypeAttributeMap { - const kinds: TypeAttributeMap = mapMap(defined(this._primitiveTypes).entries(), k => - defined(this._primitiveAttributes.get(k)) + public getMemberKinds(): TypeAttributeMap { + const kinds: TypeAttributeMap = mapMap( + defined(this._primitiveTypes).entries(), + (k) => defined(this._primitiveAttributes.get(k)), ); const maybeDoubleAttributes = this._primitiveAttributes.get("double"); // If double was eliminated, add its attributes to integer - if (maybeDoubleAttributes !== undefined && !kinds.has("double") && kinds.has("integer")) { + if ( + maybeDoubleAttributes !== undefined && + !kinds.has("double") && + kinds.has("integer") + ) { // FIXME: How can this ever happen??? Where do we "eliminate" double? - mapUpdateInto(kinds, "integer", a => { - return combineTypeAttributes("intersect", defined(a), maybeDoubleAttributes); + mapUpdateInto(kinds, "integer", (a) => { + return combineTypeAttributes( + "intersect", + defined(a), + maybeDoubleAttributes, + ); }); } - if (this._arrayItemTypes !== undefined && this._arrayItemTypes !== false) { + if ( + this._arrayItemTypes !== undefined && + this._arrayItemTypes !== false + ) { kinds.set("array", this._arrayAttributes); } else if (this._arrayAttributes.size > 0) { this._lostTypeAttributes = true; @@ -260,7 +357,7 @@ class IntersectionAccumulator return kinds; } - get lostTypeAttributes(): boolean { + public get lostTypeAttributes(): boolean { return this._lostTypeAttributes; } } @@ -272,8 +369,13 @@ class IntersectionUnionBuilder extends UnionBuilder< > { private _createdNewIntersections = false; - private makeIntersection(members: ReadonlySet, attributes: TypeAttributes): TypeRef { - const reconstitutedMembers = setMap(members, t => this.typeBuilder.reconstituteTypeRef(t.typeRef)); + private makeIntersection( + members: ReadonlySet, + attributes: TypeAttributes, + ): TypeRef { + const reconstitutedMembers = setMap(members, (t) => + this.typeBuilder.reconstituteTypeRef(t.typeRef), + ); const first = defined(iterableFirst(reconstitutedMembers)); if (reconstitutedMembers.size === 1) { @@ -282,41 +384,61 @@ class IntersectionUnionBuilder extends UnionBuilder< } this._createdNewIntersections = true; - return this.typeBuilder.getUniqueIntersectionType(attributes, reconstitutedMembers); + return this.typeBuilder.getUniqueIntersectionType( + attributes, + reconstitutedMembers, + ); } - get createdNewIntersections(): boolean { + public get createdNewIntersections(): boolean { return this._createdNewIntersections; } protected makeObject( maybeData: [PropertyMap, ReadonlySet | undefined] | undefined, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { if (maybeData === undefined) { - return panic("Either properties or additional properties must be given to make an object type"); + return panic( + "Either properties or additional properties must be given to make an object type", + ); } const [propertyTypes, maybeAdditionalProperties] = maybeData; - const properties = mapMap(propertyTypes, cp => - this.typeBuilder.makeClassProperty(this.makeIntersection(cp.typeData, emptyTypeAttributes), cp.isOptional) + const properties = mapMap(propertyTypes, (cp) => + this.typeBuilder.makeClassProperty( + this.makeIntersection(cp.typeData, emptyTypeAttributes), + cp.isOptional, + ), ); const additionalProperties = maybeAdditionalProperties === undefined ? undefined - : this.makeIntersection(maybeAdditionalProperties, emptyTypeAttributes); - return this.typeBuilder.getUniqueObjectType(typeAttributes, properties, additionalProperties, forwardingRef); + : this.makeIntersection( + maybeAdditionalProperties, + emptyTypeAttributes, + ); + return this.typeBuilder.getUniqueObjectType( + typeAttributes, + properties, + additionalProperties, + forwardingRef, + ); } protected makeArray( arrays: ReadonlySet, typeAttributes: TypeAttributes, - forwardingRef: TypeRef | undefined + forwardingRef: TypeRef | undefined, ): TypeRef { // FIXME: attributes const itemsType = this.makeIntersection(arrays, emptyTypeAttributes); - const tref = this.typeBuilder.getArrayType(typeAttributes, itemsType, forwardingRef); + const tref = this.typeBuilder.getArrayType( + typeAttributes, + itemsType, + forwardingRef, + ); return tref; } } @@ -324,50 +446,88 @@ class IntersectionUnionBuilder extends UnionBuilder< export function resolveIntersections( graph: TypeGraph, stringTypeMapping: StringTypeMapping, - debugPrintReconstitution: boolean + debugPrintReconstitution: boolean, ): [TypeGraph, boolean] { let needsRepeat = false; - function replace(types: ReadonlySet, builder: GraphRewriteBuilder, forwardingRef: TypeRef): TypeRef { - const intersections = setFilter(types, t => t instanceof IntersectionType) as Set; - const [members, intersectionAttributes] = setOperationMembersRecursively( - Array.from(intersections), - "intersect" - ); + function replace( + types: ReadonlySet, + builder: GraphRewriteBuilder, + forwardingRef: TypeRef, + ): TypeRef { + const intersections = setFilter( + types, + (t) => t instanceof IntersectionType, + ) as Set; + const [members, intersectionAttributes] = + setOperationMembersRecursively( + Array.from(intersections), + "intersect", + ); if (members.size === 0) { - const t = builder.getPrimitiveType("any", intersectionAttributes, forwardingRef); + const t = builder.getPrimitiveType( + "any", + intersectionAttributes, + forwardingRef, + ); return t; } + if (members.size === 1) { - return builder.reconstituteType(defined(iterableFirst(members)), intersectionAttributes, forwardingRef); + return builder.reconstituteType( + defined(iterableFirst(members)), + intersectionAttributes, + forwardingRef, + ); } const accumulator = new IntersectionAccumulator(); const extraAttributes = makeTypeAttributesInferred( combineTypeAttributes( "intersect", - Array.from(members).map(t => accumulator.addType(t)) - ) + Array.from(members).map((t) => accumulator.addType(t)), + ), + ); + const attributes = combineTypeAttributes( + "intersect", + intersectionAttributes, + extraAttributes, ); - const attributes = combineTypeAttributes("intersect", intersectionAttributes, extraAttributes); const unionBuilder = new IntersectionUnionBuilder(builder); - const tref = unionBuilder.buildUnion(accumulator, true, attributes, forwardingRef); + const tref = unionBuilder.buildUnion( + accumulator, + true, + attributes, + forwardingRef, + ); if (unionBuilder.createdNewIntersections) { needsRepeat = true; } + return tref; } + // FIXME: We need to handle intersections that resolve to the same set of types. // See for example the intersections-nested.schema example. const allIntersections = setFilter( graph.allTypesUnordered(), - t => t instanceof IntersectionType + (t) => t instanceof IntersectionType, ) as Set; const resolvableIntersections = setFilter(allIntersections, canResolve); const groups = makeGroupsToFlatten(resolvableIntersections, undefined); - graph = graph.rewrite("resolve intersections", stringTypeMapping, false, groups, debugPrintReconstitution, replace); + graph = graph.rewrite( + "resolve intersections", + stringTypeMapping, + false, + groups, + debugPrintReconstitution, + replace, + ); // console.log(`resolved ${resolvableIntersections.size} of ${intersections.size} intersections`); - return [graph, !needsRepeat && allIntersections.size === resolvableIntersections.size]; + return [ + graph, + !needsRepeat && allIntersections.size === resolvableIntersections.size, + ]; } diff --git a/packages/quicktype-core/src/support/Acronyms.const.ts b/packages/quicktype-core/src/support/Acronyms.const.ts new file mode 100644 index 000000000..231542582 --- /dev/null +++ b/packages/quicktype-core/src/support/Acronyms.const.ts @@ -0,0 +1,1097 @@ +export const acronyms = [ + "aaa", + "aabb", + "aac", + "aal", + "aalc", + "aarp", + "abac", + "abcl", + "abi", + "abm", + "abr", + "ac", + "acd", + "ack", + "acl", + "acm", + "acme", + "acp", + "acpi", + "acr", + "adb", + "adc", + "adccp", + "ado", + "adsl", + "adt", + "ae", + "aes", + "af", + "afp", + "agp", + "ai", + "aix", + "alac", + "algol", + "alsa", + "alu", + "amd", + "amoled", + "amqp", + "amr", + "ann", + "ansi", + "aop", + "apci", + "api", + "apic", + "apipa", + "apl", + "apr", + "arin", + "aros", + "arp", + "arpa", + "arpanet", + "ascii", + "aset", + "asg", + "asic", + "asimo", + "aslr", + "asm", + "asmp", + "asp", + "asr", + "assp", + "ast", + "ata", + "atag", + "atapi", + "atm", + "av", + "avc", + "avi", + "awfl", + "awk", + "awt", + "bal", + "bam", + "bbp", + "bbs", + "bcd", + "bcnf", + "beep", + "ber", + "bfd", + "bfs", + "bft", + "bgp", + "bi", + "binac", + "bios", + "bjt", + "bmp", + "bnc", + "boinc", + "bom", + "bootp", + "bpdu", + "bpel", + "bpl", + "bpm", + "brm", + "brms", + "brr", + "brs", + "bsa", + "bsb", + "bsd", + "bss", + "bt", + "bw", + "byod", + "ca", + "cad", + "cae", + "cai", + "caid", + "captcha", + "caq", + "cd", + "cde", + "cdfs", + "cdma", + "cdn", + "cdp", + "cdsa", + "cert", + "ces", + "cf", + "cfd", + "cfg", + "cg", + "cga", + "cgi", + "cgt", + "chs", + "cidr", + "cifs", + "cim", + "cio", + "cir", + "cisc", + "cjk", + "cjkv", + "cli", + "clr", + "cm", + "cmdb", + "cmmi", + "cmo", + "cmos", + "cms", + "cn", + "cnc", + "cng", + "cnr", + "cobol", + "com", + "corba", + "cots", + "cpa", + "cpan", + "cpri", + "cps", + "cpu", + "cr", + "cran", + "crc", + "crlf", + "crm", + "crs", + "crt", + "crud", + "cs", + "cse", + "csi", + "csm", + "csp", + "csrf", + "css", + "csv", + "ct", + "ctan", + "ctcp", + "ctfe", + "cti", + "ctl", + "ctm", + "cts", + "ctss", + "cua", + "cvs", + "dac", + "dal", + "dao", + "dap", + "darpa", + "dat", + "db", + "dba", + "dbcs", + "dbms", + "dcc", + "dcca", + "dccp", + "dcl", + "dcmi", + "dcom", + "dcs", + "dd", + "dde", + "ddi", + "ddl", + "ddr", + "dec", + "des", + "dfa", + "dfd", + "dfs", + "dgd", + "dhcp", + "dhtml", + "dif", + "dimm", + "din", + "dip", + "dism", + "divx", + "dkim", + "dl", + "dll", + "dlna", + "dlp", + "dma", + "dmca", + "dmi", + "dml", + "dmr", + "dmz", + "dn", + "dnd", + "dns", + "doa", + "docsis", + "dom", + "dos", + "dp", + "dpc", + "dpi", + "dpmi", + "dpms", + "dr", + "dram", + "dri", + "drm", + "dsa", + "dsdl", + "dsdm", + "dsl", + "dslam", + "dsn", + "dsp", + "dsssl", + "dtd", + "dte", + "dtp", + "dtr", + "dvd", + "dvi", + "dvr", + "dw", + "eai", + "eap", + "eas", + "ebcdic", + "ebml", + "ecc", + "ecma", + "ecn", + "ecos", + "ecrs", + "eda", + "edi", + "edo", + "edsac", + "edvac", + "eeprom", + "eff", + "efi", + "efm", + "efs", + "ega", + "egp", + "eide", + "eigrp", + "eisa", + "elf", + "emacs", + "ems", + "eniac", + "eod", + "eof", + "eol", + "eom", + "eos", + "eprom", + "erd", + "erm", + "erp", + "esb", + "escon", + "esd", + "esr", + "etl", + "etw", + "euc", + "eula", + "ewmh", + "ext", + "fap", + "faq", + "fasm", + "fbdimm", + "fcb", + "fcs", + "fdc", + "fdd", + "fddi", + "fdm", + "fdma", + "fds", + "fec", + "femb", + "fet", + "fhs", + "ficon", + "fifo", + "fips", + "fl", + "flac", + "flops", + "fmc", + "fmo", + "foldoc", + "fosdem", + "fosi", + "foss", + "fp", + "fpga", + "fps", + "fpu", + "fqdn", + "fru", + "fs", + "fsb", + "fsf", + "fsm", + "ftp", + "ftta", + "fttc", + "ftth", + "fttp", + "fud", + "fvek", + "fws", + "fxp", + "fyi", + "gb", + "gcc", + "gcj", + "gcr", + "gdb", + "gdi", + "geran", + "gfdl", + "gif", + "gigo", + "gimps", + "gis", + "gml", + "gnu", + "goms", + "gpasm", + "gpfs", + "gpg", + "gpgpu", + "gpib", + "gpl", + "gprs", + "gpt", + "gpu", + "gsm", + "gui", + "guid", + "gwt", + "gyr", + "hal", + "hasp", + "hba", + "hci", + "hcl", + "hd", + "hdd", + "hdl", + "hdmi", + "hf", + "hfs", + "hhd", + "hid", + "hig", + "hird", + "hlasm", + "hls", + "hma", + "hp", + "hpc", + "hpfs", + "hsdpa", + "hsm", + "ht", + "htc", + "htm", + "html", + "http", + "https", + "htx", + "hurd", + "hvd", + "iana", + "ibm", + "ic", + "icann", + "ich", + "icmp", + "icp", + "ics", + "ict", + "id", + "ide", + "idf", + "idl", + "ids", + "iec", + "ieee", + "ietf", + "ifl", + "igmp", + "igrp", + "ihv", + "iiop", + "iis", + "ike", + "il", + "im", + "imap", + "ime", + "infosec", + "ip", + "ipam", + "ipc", + "ipl", + "ipmi", + "ipo", + "ipp", + "ips", + "iptv", + "ipx", + "ir", + "irc", + "iri", + "irp", + "irq", + "isa", + "isam", + "isatap", + "isc", + "isdn", + "iso", + "isp", + "ispf", + "isr", + "isv", + "itil", + "itl", + "itu", + "ivcr", + "ivrs", + "jaxb", + "jaxp", + "jbod", + "jce", + "jcl", + "jcp", + "jdbc", + "jdk", + "jds", + "jee", + "jes", + "jfc", + "jfet", + "jfs", + "jini", + "jit", + "jme", + "jms", + "jmx", + "jndi", + "jni", + "jnz", + "jpeg", + "jre", + "js", + "jse", + "json", + "jsp", + "jtag", + "jvm", + "kb", + "kde", + "km", + "krl", + "kvm", + "lacp", + "lan", + "lb", + "lba", + "lcd", + "lcos", + "lcr", + "ldap", + "le", + "led", + "lf", + "lfs", + "lga", + "lgpl", + "lib", + "lif", + "lifo", + "lilo", + "lisp", + "lkml", + "lm", + "loc", + "lpc", + "lpi", + "lpt", + "lru", + "lsb", + "lsi", + "lte", + "ltl", + "ltr", + "lun", + "lv", + "lvd", + "lvm", + "lzw", + "mac", + "manet", + "mapi", + "mb", + "mbcs", + "mbd", + "mbr", + "mca", + "mcad", + "mcas", + "mcdba", + "mcdst", + "mcitp", + "mcm", + "mcp", + "mcpc", + "mcpd", + "mcsa", + "mcsd", + "mcse", + "mct", + "mcts", + "mda", + "mdf", + "mdi", + "mf", + "mfc", + "mfm", + "mgcp", + "mib", + "micr", + "midi", + "mimd", + "mime", + "mimo", + "minix", + "mips", + "mis", + "misd", + "mit", + "mmc", + "mmds", + "mmf", + "mmi", + "mmio", + "mmorpg", + "mmu", + "mmx", + "mng", + "mom", + "mos", + "mosfet", + "motd", + "mous", + "mov", + "mpaa", + "mpeg", + "mpl", + "mpls", + "mpu", + "ms", + "msa", + "msb", + "msdn", + "msi", + "msn", + "mt", + "mta", + "mtbf", + "mtu", + "mua", + "mvc", + "mvp", + "mvs", + "mwc", + "mx", + "mxf", + "nack", + "nak", + "nas", + "nasm", + "ncp", + "ncq", + "ncsa", + "ndis", + "ndps", + "nds", + "nep", + "nfa", + "nfc", + "nfs", + "ngl", + "ngscb", + "ni", + "nic", + "nim", + "nio", + "nist", + "nlp", + "nls", + "nmi", + "nntp", + "noc", + "nop", + "nos", + "np", + "npl", + "nptl", + "npu", + "ns", + "nsa", + "nsi", + "nspr", + "nss", + "nt", + "ntfs", + "ntlm", + "ntp", + "numa", + "nurbs", + "nvr", + "nvram", + "oat", + "obsai", + "odbc", + "oem", + "oes", + "ofdm", + "oftc", + "oid", + "olap", + "ole", + "oled", + "olpc", + "oltp", + "omf", + "omg", + "omr", + "oo", + "ooe", + "oom", + "oop", + "ootb", + "opml", + "orb", + "orm", + "os", + "oscon", + "osdn", + "osi", + "ospf", + "oss", + "ostg", + "oui", + "pap", + "parc", + "pata", + "pbs", + "pc", + "pcb", + "pci", + "pcl", + "pcm", + "pcmcia", + "pcre", + "pd", + "pda", + "pdf", + "pdh", + "pdp", + "pe", + "perl", + "pfa", + "pg", + "pga", + "pgo", + "pgp", + "php", + "pid", + "pim", + "pio", + "pkcs", + "pki", + "plc", + "pld", + "plt", + "pmm", + "png", + "pnrp", + "poid", + "pojo", + "posix", + "ppc", + "ppi", + "ppp", + "pptp", + "pr", + "ps", + "psa", + "psm", + "psu", + "psvi", + "pv", + "pvg", + "pvr", + "pxe", + "pxi", + "qa", + "qdr", + "qfp", + "qotd", + "qsop", + "qtam", + "racf", + "rad", + "raid", + "raii", + "rait", + "ram", + "rarp", + "ras", + "rc", + "rcs", + "rd", + "rdbms", + "rdc", + "rdf", + "rdm", + "rdos", + "rdp", + "rds", + "refal", + "rest", + "rf", + "rfc", + "rfi", + "rfid", + "rgb", + "rgba", + "rhel", + "rhl", + "ria", + "riaa", + "rip", + "rir", + "risc", + "rje", + "rle", + "rll", + "rmi", + "rms", + "rom", + "romb", + "rpc", + "rpg", + "rpm", + "rras", + "rsa", + "rsi", + "rss", + "rtai", + "rtc", + "rte", + "rtems", + "rtl", + "rtos", + "rtp", + "rts", + "rtsp", + "rtti", + "rwd", + "san", + "sas", + "sata", + "sax", + "sbod", + "sbu", + "scada", + "scid", + "scm", + "scp", + "scpc", + "scpi", + "scsa", + "scsi", + "sctp", + "sd", + "sddl", + "sdh", + "sdi", + "sdio", + "sdk", + "sdl", + "sdn", + "sdp", + "sdr", + "sdram", + "sdsl", + "se", + "sec", + "sei", + "seo", + "sftp", + "sgi", + "sgml", + "sgr", + "sha", + "shdsl", + "sigcat", + "siggraph", + "simd", + "simm", + "sip", + "sisd", + "siso", + "sles", + "sli", + "slm", + "sloc", + "sma", + "smb", + "smbios", + "sme", + "smf", + "smil", + "smp", + "smps", + "sms", + "smt", + "smtp", + "sna", + "snmp", + "sntp", + "soa", + "soe", + "soho", + "soi", + "sopa", + "sp", + "spa", + "sparc", + "spf", + "spi", + "spm", + "spmd", + "sql", + "sram", + "ssa", + "ssd", + "ssdp", + "sse", + "ssh", + "ssi", + "ssid", + "ssl", + "ssp", + "ssse", + "sssp", + "sstp", + "sus", + "suse", + "svc", + "svd", + "svg", + "svga", + "swf", + "swt", + "tao", + "tapi", + "tasm", + "tb", + "tcp", + "tcu", + "tdma", + "tft", + "tftp", + "ti", + "tla", + "tld", + "tls", + "tlv", + "tnc", + "tpf", + "tpm", + "troff", + "tron", + "trsdos", + "tso", + "tsp", + "tsr", + "tta", + "ttf", + "ttl", + "tts", + "tty", + "tucows", + "twain", + "uaag", + "uac", + "uart", + "uat", + "ucs", + "uddi", + "udma", + "udp", + "uefi", + "uhf", + "ui", + "ul", + "ula", + "uma", + "umb", + "uml", + "umpc", + "umts", + "unc", + "univac", + "ups", + "uri", + "url", + "usb", + "usr", + "utc", + "utf", + "utp", + "utran", + "uucp", + "uuid", + "uun", + "uvc", + "uwp", + "ux", + "vax", + "vb", + "vba", + "vbs", + "vcpi", + "vdm", + "vdsl", + "vesa", + "vfat", + "vfs", + "vg", + "vga", + "vhf", + "vlan", + "vlb", + "vlf", + "vliw", + "vlsi", + "vlsm", + "vm", + "vmm", + "vnc", + "vod", + "vpn", + "vpu", + "vr", + "vram", + "vrml", + "vsam", + "vsat", + "vt", + "vtam", + "vtl", + "wafs", + "wai", + "wais", + "wan", + "wap", + "wasm", + "wbem", + "wcag", + "wcf", + "wdm", + "wep", + "wfi", + "wins", + "wlan", + "wma", + "wmi", + "wmv", + "wns", + "wol", + "wor", + "wora", + "wpa", + "wpad", + "wpan", + "wpf", + "wsdl", + "wsfl", + "wusb", + "wwan", + "wwdc", + "wwid", + "wwn", + "www", + "wysiwyg", + "wzc", + "xag", + "xaml", + "xcbl", + "xdm", + "xdmcp", + "xhtml", + "xilp", + "xml", + "xmms", + "xmpp", + "xms", + "xns", + "xp", + "xpcom", + "xpi", + "xpidl", + "xps", + "xsd", + "xsl", + "xslt", + "xss", + "xtf", + "xul", + "xvga", + "yaaf", + "yacc", + "yaml", + "zcav", + "zcs", + "zif", + "zifs", + "zisc", + "zma", + "zoi", + "zope", + "zpl", +] as const; diff --git a/packages/quicktype-core/src/support/Acronyms.ts b/packages/quicktype-core/src/support/Acronyms.ts index 21460b0cf..7c6ca0437 100644 --- a/packages/quicktype-core/src/support/Acronyms.ts +++ b/packages/quicktype-core/src/support/Acronyms.ts @@ -1,1133 +1,41 @@ import { EnumOption } from "../RendererOptions"; -import { allUpperWordStyle, firstUpperWordStyle, originalWord, allLowerWordStyle } from "./Strings"; -export const acronyms: string[] = [ - "aaa", - "aabb", - "aac", - "aal", - "aalc", - "aarp", - "abac", - "abcl", - "abi", - "abm", - "abr", - "ac", - "acd", - "ack", - "acl", - "acm", - "acme", - "acp", - "acpi", - "acr", - "adb", - "adc", - "adccp", - "ado", - "adsl", - "adt", - "ae", - "aes", - "af", - "afp", - "agp", - "ai", - "aix", - "alac", - "algol", - "alsa", - "alu", - "amd", - "amoled", - "amqp", - "amr", - "ann", - "ansi", - "aop", - "apci", - "api", - "apic", - "apipa", - "apl", - "apr", - "arin", - "aros", - "arp", - "arpa", - "arpanet", - "ascii", - "aset", - "asg", - "asic", - "asimo", - "aslr", - "asm", - "asmp", - "asp", - "asr", - "assp", - "ast", - "ata", - "atag", - "atapi", - "atm", - "av", - "avc", - "avi", - "awfl", - "awk", - "awt", - "bal", - "bam", - "bbp", - "bbs", - "bcd", - "bcnf", - "beep", - "ber", - "bfd", - "bfs", - "bft", - "bgp", - "bi", - "binac", - "bios", - "bjt", - "bmp", - "bnc", - "boinc", - "bom", - "bootp", - "bpdu", - "bpel", - "bpl", - "bpm", - "brm", - "brms", - "brr", - "brs", - "bsa", - "bsb", - "bsd", - "bss", - "bt", - "bw", - "byod", - "ca", - "cad", - "cae", - "cai", - "caid", - "captcha", - "caq", - "cd", - "cde", - "cdfs", - "cdma", - "cdn", - "cdp", - "cdsa", - "cert", - "ces", - "cf", - "cfd", - "cfg", - "cg", - "cga", - "cgi", - "cgt", - "chs", - "cidr", - "cifs", - "cim", - "cio", - "cir", - "cisc", - "cjk", - "cjkv", - "cli", - "clr", - "cm", - "cmdb", - "cmmi", - "cmo", - "cmos", - "cms", - "cn", - "cnc", - "cng", - "cnr", - "cobol", - "com", - "corba", - "cots", - "cpa", - "cpan", - "cpri", - "cps", - "cpu", - "cr", - "cran", - "crc", - "crlf", - "crm", - "crs", - "crt", - "crud", - "cs", - "cse", - "csi", - "csm", - "csp", - "csrf", - "css", - "csv", - "ct", - "ctan", - "ctcp", - "ctfe", - "cti", - "ctl", - "ctm", - "cts", - "ctss", - "cua", - "cvs", - "dac", - "dal", - "dao", - "dap", - "darpa", - "dat", - "db", - "dba", - "dbcs", - "dbms", - "dcc", - "dcca", - "dccp", - "dcl", - "dcmi", - "dcom", - "dcs", - "dd", - "dde", - "ddi", - "ddl", - "ddr", - "dec", - "des", - "dfa", - "dfd", - "dfs", - "dgd", - "dhcp", - "dhtml", - "dif", - "dimm", - "din", - "dip", - "dism", - "divx", - "dkim", - "dl", - "dll", - "dlna", - "dlp", - "dma", - "dmca", - "dmi", - "dml", - "dmr", - "dmz", - "dn", - "dnd", - "dns", - "doa", - "docsis", - "dom", - "dos", - "dp", - "dpc", - "dpi", - "dpmi", - "dpms", - "dr", - "dram", - "dri", - "drm", - "dsa", - "dsdl", - "dsdm", - "dsl", - "dslam", - "dsn", - "dsp", - "dsssl", - "dtd", - "dte", - "dtp", - "dtr", - "dvd", - "dvi", - "dvr", - "dw", - "eai", - "eap", - "eas", - "ebcdic", - "ebml", - "ecc", - "ecma", - "ecn", - "ecos", - "ecrs", - "eda", - "edi", - "edo", - "edsac", - "edvac", - "eeprom", - "eff", - "efi", - "efm", - "efs", - "ega", - "egp", - "eide", - "eigrp", - "eisa", - "elf", - "emacs", - "ems", - "eniac", - "eod", - "eof", - "eol", - "eom", - "eos", - "eprom", - "erd", - "erm", - "erp", - "esb", - "escon", - "esd", - "esr", - "etl", - "etw", - "euc", - "eula", - "ewmh", - "ext", - "fap", - "faq", - "fasm", - "fbdimm", - "fcb", - "fcs", - "fdc", - "fdd", - "fddi", - "fdm", - "fdma", - "fds", - "fec", - "femb", - "fet", - "fhs", - "ficon", - "fifo", - "fips", - "fl", - "flac", - "flops", - "fmc", - "fmo", - "foldoc", - "fosdem", - "fosi", - "foss", - "fp", - "fpga", - "fps", - "fpu", - "fqdn", - "fru", - "fs", - "fsb", - "fsf", - "fsm", - "ftp", - "ftta", - "fttc", - "ftth", - "fttp", - "fud", - "fvek", - "fws", - "fxp", - "fyi", - "gb", - "gcc", - "gcj", - "gcr", - "gdb", - "gdi", - "geran", - "gfdl", - "gif", - "gigo", - "gimps", - "gis", - "gml", - "gnu", - "goms", - "gpasm", - "gpfs", - "gpg", - "gpgpu", - "gpib", - "gpl", - "gprs", - "gpt", - "gpu", - "gsm", - "gui", - "guid", - "gwt", - "gyr", - "hal", - "hasp", - "hba", - "hci", - "hcl", - "hd", - "hdd", - "hdl", - "hdmi", - "hf", - "hfs", - "hhd", - "hid", - "hig", - "hird", - "hlasm", - "hls", - "hma", - "hp", - "hpc", - "hpfs", - "hsdpa", - "hsm", - "ht", - "htc", - "htm", - "html", - "http", - "https", - "htx", - "hurd", - "hvd", - "iana", - "ibm", - "ic", - "icann", - "ich", - "icmp", - "icp", - "ics", - "ict", - "id", - "ide", - "idf", - "idl", - "ids", - "iec", - "ieee", - "ietf", - "ifl", - "igmp", - "igrp", - "ihv", - "iiop", - "iis", - "ike", - "il", - "im", - "imap", - "ime", - "infosec", - "ip", - "ipam", - "ipc", - "ipl", - "ipmi", - "ipo", - "ipp", - "ips", - "iptv", - "ipx", - "ir", - "irc", - "iri", - "irp", - "irq", - "isa", - "isam", - "isatap", - "isc", - "isdn", - "iso", - "isp", - "ispf", - "isr", - "isv", - "itil", - "itl", - "itu", - "ivcr", - "ivrs", - "jaxb", - "jaxp", - "jbod", - "jce", - "jcl", - "jcp", - "jdbc", - "jdk", - "jds", - "jee", - "jes", - "jfc", - "jfet", - "jfs", - "jini", - "jit", - "jme", - "jms", - "jmx", - "jndi", - "jni", - "jnz", - "jpeg", - "jre", - "js", - "jse", - "json", - "jsp", - "jtag", - "jvm", - "kb", - "kde", - "km", - "krl", - "kvm", - "lacp", - "lan", - "lb", - "lba", - "lcd", - "lcos", - "lcr", - "ldap", - "le", - "led", - "lf", - "lfs", - "lga", - "lgpl", - "lib", - "lif", - "lifo", - "lilo", - "lisp", - "lkml", - "lm", - "loc", - "lpc", - "lpi", - "lpt", - "lru", - "lsb", - "lsi", - "lte", - "ltl", - "ltr", - "lun", - "lv", - "lvd", - "lvm", - "lzw", - "mac", - "manet", - "mapi", - "mb", - "mbcs", - "mbd", - "mbr", - "mca", - "mcad", - "mcas", - "mcdba", - "mcdst", - "mcitp", - "mcm", - "mcp", - "mcpc", - "mcpd", - "mcsa", - "mcsd", - "mcse", - "mct", - "mcts", - "mda", - "mdf", - "mdi", - "mf", - "mfc", - "mfm", - "mgcp", - "mib", - "micr", - "midi", - "mimd", - "mime", - "mimo", - "minix", - "mips", - "mis", - "misd", - "mit", - "mmc", - "mmds", - "mmf", - "mmi", - "mmio", - "mmorpg", - "mmu", - "mmx", - "mng", - "mom", - "mos", - "mosfet", - "motd", - "mous", - "mov", - "mpaa", - "mpeg", - "mpl", - "mpls", - "mpu", - "ms", - "msa", - "msb", - "msdn", - "msi", - "msn", - "mt", - "mta", - "mtbf", - "mtu", - "mua", - "mvc", - "mvp", - "mvs", - "mwc", - "mx", - "mxf", - "nack", - "nak", - "nas", - "nasm", - "ncp", - "ncq", - "ncsa", - "ndis", - "ndps", - "nds", - "nep", - "nfa", - "nfc", - "nfs", - "ngl", - "ngscb", - "ni", - "nic", - "nim", - "nio", - "nist", - "nlp", - "nls", - "nmi", - "nntp", - "noc", - "nop", - "nos", - "np", - "npl", - "nptl", - "npu", - "ns", - "nsa", - "nsi", - "nspr", - "nss", - "nt", - "ntfs", - "ntlm", - "ntp", - "numa", - "nurbs", - "nvr", - "nvram", - "oat", - "obsai", - "odbc", - "oem", - "oes", - "ofdm", - "oftc", - "oid", - "olap", - "ole", - "oled", - "olpc", - "oltp", - "omf", - "omg", - "omr", - "oo", - "ooe", - "oom", - "oop", - "ootb", - "opml", - "orb", - "orm", - "os", - "oscon", - "osdn", - "osi", - "ospf", - "oss", - "ostg", - "oui", - "pap", - "parc", - "pata", - "pbs", - "pc", - "pcb", - "pci", - "pcl", - "pcm", - "pcmcia", - "pcre", - "pd", - "pda", - "pdf", - "pdh", - "pdp", - "pe", - "perl", - "pfa", - "pg", - "pga", - "pgo", - "pgp", - "php", - "pid", - "pim", - "pio", - "pkcs", - "pki", - "plc", - "pld", - "plt", - "pmm", - "png", - "pnrp", - "poid", - "pojo", - "posix", - "ppc", - "ppi", - "ppp", - "pptp", - "pr", - "ps", - "psa", - "psm", - "psu", - "psvi", - "pv", - "pvg", - "pvr", - "pxe", - "pxi", - "qa", - "qdr", - "qfp", - "qotd", - "qsop", - "qtam", - "racf", - "rad", - "raid", - "raii", - "rait", - "ram", - "rarp", - "ras", - "rc", - "rcs", - "rd", - "rdbms", - "rdc", - "rdf", - "rdm", - "rdos", - "rdp", - "rds", - "refal", - "rest", - "rf", - "rfc", - "rfi", - "rfid", - "rgb", - "rgba", - "rhel", - "rhl", - "ria", - "riaa", - "rip", - "rir", - "risc", - "rje", - "rle", - "rll", - "rmi", - "rms", - "rom", - "romb", - "rpc", - "rpg", - "rpm", - "rras", - "rsa", - "rsi", - "rss", - "rtai", - "rtc", - "rte", - "rtems", - "rtl", - "rtos", - "rtp", - "rts", - "rtsp", - "rtti", - "rwd", - "san", - "sas", - "sata", - "sax", - "sbod", - "sbu", - "scada", - "scid", - "scm", - "scp", - "scpc", - "scpi", - "scsa", - "scsi", - "sctp", - "sd", - "sddl", - "sdh", - "sdi", - "sdio", - "sdk", - "sdl", - "sdn", - "sdp", - "sdr", - "sdram", - "sdsl", - "se", - "sec", - "sei", - "seo", - "sftp", - "sgi", - "sgml", - "sgr", - "sha", - "shdsl", - "sigcat", - "siggraph", - "simd", - "simm", - "sip", - "sisd", - "siso", - "sles", - "sli", - "slm", - "sloc", - "sma", - "smb", - "smbios", - "sme", - "smf", - "smil", - "smp", - "smps", - "sms", - "smt", - "smtp", - "sna", - "snmp", - "sntp", - "soa", - "soe", - "soho", - "soi", - "sopa", - "sp", - "spa", - "sparc", - "spf", - "spi", - "spm", - "spmd", - "sql", - "sram", - "ssa", - "ssd", - "ssdp", - "sse", - "ssh", - "ssi", - "ssid", - "ssl", - "ssp", - "ssse", - "sssp", - "sstp", - "sus", - "suse", - "svc", - "svd", - "svg", - "svga", - "swf", - "swt", - "tao", - "tapi", - "tasm", - "tb", - "tcp", - "tcu", - "tdma", - "tft", - "tftp", - "ti", - "tla", - "tld", - "tls", - "tlv", - "tnc", - "tpf", - "tpm", - "troff", - "tron", - "trsdos", - "tso", - "tsp", - "tsr", - "tta", - "ttf", - "ttl", - "tts", - "tty", - "tucows", - "twain", - "uaag", - "uac", - "uart", - "uat", - "ucs", - "uddi", - "udma", - "udp", - "uefi", - "uhf", - "ui", - "ul", - "ula", - "uma", - "umb", - "uml", - "umpc", - "umts", - "unc", - "univac", - "ups", - "uri", - "url", - "usb", - "usr", - "utc", - "utf", - "utp", - "utran", - "uucp", - "uuid", - "uun", - "uvc", - "uwp", - "ux", - "vax", - "vb", - "vba", - "vbs", - "vcpi", - "vdm", - "vdsl", - "vesa", - "vfat", - "vfs", - "vg", - "vga", - "vhf", - "vlan", - "vlb", - "vlf", - "vliw", - "vlsi", - "vlsm", - "vm", - "vmm", - "vnc", - "vod", - "vpn", - "vpu", - "vr", - "vram", - "vrml", - "vsam", - "vsat", - "vt", - "vtam", - "vtl", - "wafs", - "wai", - "wais", - "wan", - "wap", - "wasm", - "wbem", - "wcag", - "wcf", - "wdm", - "wep", - "wfi", - "wins", - "wlan", - "wma", - "wmi", - "wmv", - "wns", - "wol", - "wor", - "wora", - "wpa", - "wpad", - "wpan", - "wpf", - "wsdl", - "wsfl", - "wusb", - "wwan", - "wwdc", - "wwid", - "wwn", - "www", - "wysiwyg", - "wzc", - "xag", - "xaml", - "xcbl", - "xdm", - "xdmcp", - "xhtml", - "xilp", - "xml", - "xmms", - "xmpp", - "xms", - "xns", - "xp", - "xpcom", - "xpi", - "xpidl", - "xps", - "xsd", - "xsl", - "xslt", - "xss", - "xtf", - "xul", - "xvga", - "yaaf", - "yacc", - "yaml", - "zcav", - "zcs", - "zif", - "zifs", - "zisc", - "zma", - "zoi", - "zope", - "zpl" -]; +import { + allLowerWordStyle, + allUpperWordStyle, + firstUpperWordStyle, + originalWord, +} from "./Strings"; export enum AcronymStyleOptions { - Pascal = "pascal", Camel = "camel", + Lower = "lowerCase", Original = "original", - Lower = "lowerCase" + Pascal = "pascal", } -export const acronymOption = function (defaultOption: AcronymStyleOptions) { - return new EnumOption( +export const acronymOption = (defaultOption: AcronymStyleOptions) => new EnumOption( "acronym-style", "Acronym naming style", - [ - [AcronymStyleOptions.Original, AcronymStyleOptions.Original], - [AcronymStyleOptions.Pascal, AcronymStyleOptions.Pascal], - [AcronymStyleOptions.Camel, AcronymStyleOptions.Camel], - [AcronymStyleOptions.Lower, AcronymStyleOptions.Lower] - ], + { + [AcronymStyleOptions.Original]: AcronymStyleOptions.Original, + [AcronymStyleOptions.Pascal]: AcronymStyleOptions.Pascal, + [AcronymStyleOptions.Camel]: AcronymStyleOptions.Camel, + [AcronymStyleOptions.Lower]: AcronymStyleOptions.Lower, + } as const, defaultOption, - "secondary" + "secondary", ); -}; -export function acronymStyle(style: AcronymStyleOptions): (s: string) => string { - const options: { [key: string]: (s: string) => string } = { - [AcronymStyleOptions.Pascal]: allUpperWordStyle, - [AcronymStyleOptions.Camel]: firstUpperWordStyle, - [AcronymStyleOptions.Original]: originalWord, - [AcronymStyleOptions.Lower]: allLowerWordStyle - }; +const options = { + [AcronymStyleOptions.Pascal]: allUpperWordStyle, + [AcronymStyleOptions.Camel]: firstUpperWordStyle, + [AcronymStyleOptions.Original]: originalWord, + [AcronymStyleOptions.Lower]: allLowerWordStyle, +} as const; +export function acronymStyle( + style: AcronymStyle, +): (typeof options)[AcronymStyle] { return options[style]; } diff --git a/packages/quicktype-core/src/support/Chance.ts b/packages/quicktype-core/src/support/Chance.ts index 5a368d7e8..f4c553c5f 100644 --- a/packages/quicktype-core/src/support/Chance.ts +++ b/packages/quicktype-core/src/support/Chance.ts @@ -1,3 +1,4 @@ +/* eslint-disable */ // Mersenne Twister from https://gist.github.com/banksean/300494 /* A C-program for MT19937, with initialization improved 2002/1/26. @@ -34,20 +35,26 @@ email: m-mat @ math.sci.hiroshima-u.ac.jp (remove space) */ class MersenneTwister { - private N: number; - private M: number; - private MATRIX_A: number; - private UPPER_MASK: number; - private LOWER_MASK: number; + private readonly N: number; + + private readonly M: number; + + private readonly MATRIX_A: number; + + private readonly UPPER_MASK: number; + + private readonly LOWER_MASK: number; private mt: number[]; + private mti: number; - constructor(seed: number) { + public constructor(seed: number) { if (seed === undefined) { // kept random number same size as time used previously to ensure no unexpected results downstream seed = Math.floor(Math.random() * Math.pow(10, 13)); } + /* Period parameters */ this.N = 624; this.M = 397; @@ -67,7 +74,9 @@ class MersenneTwister { for (this.mti = 1; this.mti < this.N; this.mti++) { s = this.mt[this.mti - 1] ^ (this.mt[this.mti - 1] >>> 30); this.mt[this.mti] = - ((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + (s & 0x0000ffff) * 1812433253 + this.mti; + ((((s & 0xffff0000) >>> 16) * 1812433253) << 16) + + (s & 0x0000ffff) * 1812433253 + + this.mti; /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */ /* In the previous versions, MSBs of the seed affect */ /* only MSBs of the array mt[]. */ @@ -80,7 +89,7 @@ class MersenneTwister { /* generates a random number on [0,0xffffffff]-interval */ private genrand_int32() { let y; - let mag01 = new Array(0x0, this.MATRIX_A); + const mag01 = [0x0, this.MATRIX_A]; /* mag01[x] = x * MATRIX_A for x=0,1 */ if (this.mti >= this.N) { @@ -91,16 +100,29 @@ class MersenneTwister { /* if init_genrand() has not been called, */ this.init_genrand(5489); /* a default initial seed is used */ } + for (kk = 0; kk < this.N - this.M; kk++) { - y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); + y = + (this.mt[kk] & this.UPPER_MASK) | + (this.mt[kk + 1] & this.LOWER_MASK); this.mt[kk] = this.mt[kk + this.M] ^ (y >>> 1) ^ mag01[y & 0x1]; } + for (; kk < this.N - 1; kk++) { - y = (this.mt[kk] & this.UPPER_MASK) | (this.mt[kk + 1] & this.LOWER_MASK); - this.mt[kk] = this.mt[kk + (this.M - this.N)] ^ (y >>> 1) ^ mag01[y & 0x1]; + y = + (this.mt[kk] & this.UPPER_MASK) | + (this.mt[kk + 1] & this.LOWER_MASK); + this.mt[kk] = + this.mt[kk + (this.M - this.N)] ^ + (y >>> 1) ^ + mag01[y & 0x1]; } - y = (this.mt[this.N - 1] & this.UPPER_MASK) | (this.mt[0] & this.LOWER_MASK); - this.mt[this.N - 1] = this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; + + y = + (this.mt[this.N - 1] & this.UPPER_MASK) | + (this.mt[0] & this.LOWER_MASK); + this.mt[this.N - 1] = + this.mt[this.M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; this.mti = 0; } @@ -125,9 +147,9 @@ class MersenneTwister { // https://github.com/chancejs/chancejs export class Chance { - private mt: MersenneTwister; + private readonly mt: MersenneTwister; - constructor(readonly seed: number) { + public constructor(readonly seed: number) { // If no generator function was provided, use our MT this.mt = new MersenneTwister(this.seed); } @@ -147,8 +169,10 @@ export class Chance { * @returns {Number} a single random integer number * @throws {RangeError} min cannot be greater than max */ - integer(options: { min: number; max: number }): number { - return Math.floor(this.random() * (options.max - options.min + 1) + options.min); + integer(options: { max: number; min: number }): number { + return Math.floor( + this.random() * (options.max - options.min + 1) + options.min, + ); } /** @@ -170,12 +194,21 @@ export class Chance { if (arr.length === 0) { throw new RangeError("Chance: Cannot pick() from an empty array"); } + return arr[this.natural({ max: arr.length - 1 })]; } animal(): string { // if user does not put in any animal type, will return a random animal regardless - const animalTypeArray = ["desert", "forest", "ocean", "zoo", "farm", "pet", "grassland"]; + const animalTypeArray = [ + "desert", + "forest", + "ocean", + "zoo", + "farm", + "pet", + "grassland", + ]; return this.pick(animals[this.pick(animalTypeArray)]); } @@ -479,7 +512,7 @@ const animals: { [kind: string]: string[] } = { "Yellow Tube Sponge", "Yellowfin Tuna", "Zebrashark", - "Zooplankton" + "Zooplankton", ], // list of desert, grassland, and forest animals comes from http://www.skyenimals.com/ desert: [ @@ -572,7 +605,7 @@ const animals: { [kind: string]: string[] } = { "Vulture", "Waxwing", "Xerus", - "Zebra" + "Zebra", ], grassland: [ "Aardvark", @@ -715,7 +748,7 @@ const animals: { [kind: string]: string[] } = { "Thornbill", "Thrush", "Toad", - "Tortoise" + "Tortoise", ], forest: [ "Agouti", @@ -911,7 +944,7 @@ const animals: { [kind: string]: string[] } = { "Wolf", "Wombat", "Woodchuck", - "Woodpecker" + "Woodpecker", ], // list of farm animals comes from https://www.buzzle.com/articles/farm-animals-list.html farm: [ @@ -942,7 +975,7 @@ const animals: { [kind: string]: string[] } = { "Silkworm", "Turkey", "Yak", - "Zebu" + "Zebu", ], // list of pet animals comes from https://www.dogbreedinfo.com/pets/pet.htm pet: [ @@ -988,7 +1021,7 @@ const animals: { [kind: string]: string[] } = { "Sugar Gliders", "Tarantula", "Turkeys", - "Turtles" + "Turtles", ], // list of zoo animals comes from https://bronxzoo.com/animals zoo: [ @@ -1058,8 +1091,8 @@ const animals: { [kind: string]: string[] } = { "Tufted Puffin", "White Cheeked Gibbon", "White-throated Bee Eater", - "Zebra" - ] + "Zebra", + ], }; // Source: https://en.wikipedia.org/wiki/List_of_population_centers_by_latitude @@ -2160,5 +2193,5 @@ const cities: string[] = [ "Villa Las Estrellas", "Esperanza", "Rothera", - "Concordia" + "Concordia", ]; diff --git a/packages/quicktype-core/src/support/Comments.ts b/packages/quicktype-core/src/support/Comments.ts new file mode 100644 index 000000000..5437fbd0c --- /dev/null +++ b/packages/quicktype-core/src/support/Comments.ts @@ -0,0 +1,30 @@ +import type { Sourcelike } from "../Source"; + +export interface CommentOptions { + afterComment?: string; + beforeComment?: string; + firstLineStart?: string; + lineEnd?: string; + lineStart?: string; +} + +interface DescriptionBlockCommentConfig { + descriptionBlock: Sourcelike[]; +} +interface InlineCommentConfig { + lines: Sourcelike[]; +} +type CustomCommentConfig = CommentOptions & { + customLines: Sourcelike[]; +}; + +export type CommentConfig = + | DescriptionBlockCommentConfig + | InlineCommentConfig + | CustomCommentConfig; + +export type Comment = string | CommentConfig; + +export const isStringComment = (comment: Comment): comment is string => { + return typeof comment === "string"; +}; diff --git a/packages/quicktype-core/src/support/Converters.ts b/packages/quicktype-core/src/support/Converters.ts index 4231237d3..282e4e543 100644 --- a/packages/quicktype-core/src/support/Converters.ts +++ b/packages/quicktype-core/src/support/Converters.ts @@ -1,19 +1,19 @@ import { EnumOption } from "../RendererOptions"; export enum ConvertersOptions { + AllObjects = "all-objects", TopLevel = "top-level", - AllObjects = "all-objects" } export function convertersOption() { return new EnumOption( "converters", "Which converters to generate (top-level by default)", - [ - [ConvertersOptions.TopLevel, ConvertersOptions.TopLevel], - [ConvertersOptions.AllObjects, ConvertersOptions.AllObjects] - ], + { + [ConvertersOptions.TopLevel]: ConvertersOptions.TopLevel, + [ConvertersOptions.AllObjects]: ConvertersOptions.AllObjects, + } as const, ConvertersOptions.TopLevel, - "secondary" + "secondary", ); } diff --git a/packages/quicktype-core/src/support/Strings.ts b/packages/quicktype-core/src/support/Strings.ts index 8e2e91969..0c4fd2175 100644 --- a/packages/quicktype-core/src/support/Strings.ts +++ b/packages/quicktype-core/src/support/Strings.ts @@ -1,7 +1,10 @@ -import { assert, defined, panic, assertNever } from "./Support"; -import { acronyms } from "./Acronyms"; +import unicode from "unicode-properties"; + import { messageAssert } from "../Messages"; +import { acronyms } from "./Acronyms.const"; +import { assert, assertNever, defined, panic } from "./Support"; + export type NamingStyle = | "pascal" | "camel" @@ -10,11 +13,9 @@ export type NamingStyle = | "pascal-upper-acronyms" | "camel-upper-acronyms"; -import unicode from "unicode-properties"; - function computeAsciiMap(mapper: (codePoint: number) => string): { - charStringMap: string[]; charNoEscapeMap: number[]; + charStringMap: string[]; } { const charStringMap: string[] = []; const charNoEscapeMap: number[] = []; @@ -25,6 +26,7 @@ function computeAsciiMap(mapper: (codePoint: number) => string): { if (result === String.fromCharCode(i)) { noEscape = 1; } + charStringMap.push(result); charNoEscapeMap.push(noEscape); } @@ -34,20 +36,24 @@ function computeAsciiMap(mapper: (codePoint: number) => string): { type CodePointPredicate = (codePoint: number) => boolean; -function precomputedCodePointPredicate(p: CodePointPredicate): CodePointPredicate { +function precomputedCodePointPredicate( + p: CodePointPredicate, +): CodePointPredicate { const asciiResults: boolean[] = []; for (let cp = 0; cp < 128; cp++) { asciiResults.push(p(cp)); } - return function (cp: number) { - return cp < 128 ? asciiResults[cp] : p(cp); - }; + + return (cp: number) => cp < 128 ? asciiResults[cp] : p(cp); } // FIXME: This is a copy of code in src/Data/String/Util.js -export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: string) => string { +export function utf16ConcatMap( + mapper: (utf16Unit: number) => string, +): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); + // eslint-disable-next-line @typescript-eslint/naming-convention return function stringConcatMap_inner(s: string): string { let cs: string[] | null = null; let start = 0; @@ -67,6 +73,7 @@ export function utf16ConcatMap(mapper: (utf16Unit: number) => string): (s: strin start = i + 1; } + i++; } @@ -86,9 +93,12 @@ function isLowSurrogate(cc: number): boolean { return cc >= 0xdc00 && cc <= 0xdfff; } -export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: string) => string { +export function utf32ConcatMap( + mapper: (codePoint: number) => string, +): (s: string) => string { const { charStringMap, charNoEscapeMap } = computeAsciiMap(mapper); + // eslint-disable-next-line @typescript-eslint/naming-convention return function stringConcatMap_inner(s: string): string { let cs: string[] | null = null; let start = 0; @@ -103,7 +113,11 @@ export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: strin const highSurrogate = cc; i++; const lowSurrogate = s.charCodeAt(i); - messageAssert(isLowSurrogate(lowSurrogate), "MiscUnicodeHighSurrogateWithoutLowSurrogate", {}); + messageAssert( + isLowSurrogate(lowSurrogate), + "MiscUnicodeHighSurrogateWithoutLowSurrogate", + {}, + ); const highBits = highSurrogate - 0xd800; const lowBits = lowSurrogate - 0xdc00; cc = 0x10000 + lowBits + (highBits << 10); @@ -118,6 +132,7 @@ export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: strin start = i + 1; } + i++; } @@ -129,12 +144,18 @@ export function utf32ConcatMap(mapper: (codePoint: number) => string): (s: strin }; } -export function utf16LegalizeCharacters(isLegal: (utf16Unit: number) => boolean): (s: string) => string { - return utf16ConcatMap(u => (isLegal(u) ? String.fromCharCode(u) : "")); +export function utf16LegalizeCharacters( + isLegal: (utf16Unit: number) => boolean, +): (s: string) => string { + return utf16ConcatMap((u) => (isLegal(u) ? String.fromCharCode(u) : "")); } -export function legalizeCharacters(isLegal: (codePoint: number) => boolean): (s: string) => string { - return utf32ConcatMap(u => (u <= 0xffff && isLegal(u) ? String.fromCharCode(u) : "")); +export function legalizeCharacters( + isLegal: (codePoint: number) => boolean, +): (s: string) => string { + return utf32ConcatMap((u) => + u <= 0xffff && isLegal(u) ? String.fromCharCode(u) : "", + ); } export function repeatString(s: string, n: number): string { @@ -149,16 +170,18 @@ export function repeatString(s: string, n: number): string { if (n % 2 !== 0) { result += s; } + n = Math.floor(n / 2); if (n > 0) { s += s; } } while (n > 0); + return result; } export function intToHex(i: number, width: number): string { - let str = i.toString(16); + const str = i.toString(16); if (str.length >= width) return str; return repeatString("0", width - str.length) + str; } @@ -173,7 +196,7 @@ export function standardUnicodeHexEscape(codePoint: number): string { export function escapeNonPrintableMapper( printablePredicate: (codePoint: number) => boolean, - escaper: (codePoint: number) => string + escaper: (codePoint: number) => string, ): (u: number) => string { function mapper(u: number): string { switch (u) { @@ -189,45 +212,49 @@ export function escapeNonPrintableMapper( if (printablePredicate(u)) { return String.fromCharCode(u); } + return escaper(u); } } + return mapper; } -export const utf16StringEscape = utf16ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape)); -export const stringEscape = utf32ConcatMap(escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape)); +export const utf16StringEscape = utf16ConcatMap( + escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape), +); +export const stringEscape = utf32ConcatMap( + escapeNonPrintableMapper(isPrintable, standardUnicodeHexEscape), +); export function isPrintable(codePoint: number): boolean { if (codePoint > 0xffff) return false; const category = unicode.getCategory(codePoint); - return ( - [ - "Mc", - "No", - "Sk", - "Me", - "Nd", - "Po", - "Lt", - "Pc", - "Sm", - "Zs", - "Lu", - "Pd", - "So", - "Pe", - "Pf", - "Ps", - "Sc", - "Ll", - "Lm", - "Pi", - "Nl", - "Mn", - "Lo" - ].indexOf(category) >= 0 - ); + return [ + "Mc", + "No", + "Sk", + "Me", + "Nd", + "Po", + "Lt", + "Pc", + "Sm", + "Zs", + "Lu", + "Pd", + "So", + "Pe", + "Pf", + "Ps", + "Sc", + "Ll", + "Lm", + "Pi", + "Nl", + "Mn", + "Lo", + ].includes(category); } export function isAscii(codePoint: number): boolean { @@ -237,17 +264,17 @@ export function isAscii(codePoint: number): boolean { export function isLetter(codePoint: number): boolean { const category = unicode.getCategory(codePoint); // FIXME: Include Letter, modifier (Lm)? - return ["Lu", "Ll", "Lt", "Lo"].indexOf(category) >= 0; + return ["Lu", "Ll", "Lt", "Lo"].includes(category); } export function isDigit(codePoint: number): boolean { const category = unicode.getCategory(codePoint); - return ["Nd"].indexOf(category) >= 0; + return ["Nd"].includes(category); } export function isNumeric(codePoint: number): boolean { const category = unicode.getCategory(codePoint); - return ["No", "Nd", "Nl"].indexOf(category) >= 0; + return ["No", "Nd", "Nl"].includes(category); } export function isLetterOrDigit(codePoint: number): boolean { @@ -273,6 +300,7 @@ export function trimEnd(str: string): string { if (!unicode.isWhiteSpace(str.charCodeAt(i))) break; firstWS = i; } + if (firstWS === l) return str; return str.slice(0, firstWS); } @@ -283,11 +311,11 @@ function modifyFirstChar(f: (c: string) => string, s: string): string { } export function capitalize(str: string): string { - return modifyFirstChar(c => c.toUpperCase(), str); + return modifyFirstChar((c) => c.toUpperCase(), str); } export function decapitalize(str: string): string { - return modifyFirstChar(c => c.toLowerCase(), str); + return modifyFirstChar((c) => c.toLowerCase(), str); } const wordSeparatorRegex = /[-_. ]+/; @@ -309,7 +337,7 @@ export function snakeCase(str: string): string { export function startWithLetter( isAllowedStart: (codePoint: number) => boolean, // FIXME: technically, this operates on UTF16 units upper: boolean, - str: string + str: string, ): string { const modify = upper ? capitalize : decapitalize; if (str === "") return modify("empty"); @@ -319,21 +347,29 @@ export function startWithLetter( const knownAcronyms = new Set(acronyms); -export type WordInName = { - word: string; +export interface WordInName { isAcronym: boolean; -}; + word: string; +} const fastIsWordCharacter = precomputedCodePointPredicate(isWordCharacter); -const fastIsNonWordCharacter = precomputedCodePointPredicate(cp => !isWordCharacter(cp)); -const fastIsLowerCase = precomputedCodePointPredicate(cp => unicode.isLowerCase(cp)); -export const fastIsUpperCase = precomputedCodePointPredicate(cp => unicode.isUpperCase(cp)); -const fastNonLetter = precomputedCodePointPredicate(cp => !unicode.isLowerCase(cp) && !unicode.isUpperCase(cp)); +const fastIsNonWordCharacter = precomputedCodePointPredicate( + (cp) => !isWordCharacter(cp), +); +const fastIsLowerCase = precomputedCodePointPredicate((cp) => + unicode.isLowerCase(cp), +); +export const fastIsUpperCase = precomputedCodePointPredicate((cp) => + unicode.isUpperCase(cp), +); +const fastNonLetter = precomputedCodePointPredicate( + (cp) => !unicode.isLowerCase(cp) && !unicode.isUpperCase(cp), +); const fastIsDigit = precomputedCodePointPredicate(isDigit); export function splitIntoWords(s: string): WordInName[] { // [start, end, allUpper] - const intervals: [number, number, boolean][] = []; + const intervals: Array<[number, number, boolean]> = []; let intervalStart: number | undefined = undefined; const len = s.length; let i = 0; @@ -342,6 +378,7 @@ export function splitIntoWords(s: string): WordInName[] { function atEnd(): boolean { return i >= len; } + function currentCodePoint(): number { return defined(s.codePointAt(i)); } @@ -358,21 +395,28 @@ export function splitIntoWords(s: string): WordInName[] { function skipNonWord(): void { skipWhile(fastIsNonWordCharacter); } + function skipLowerCase(): void { skipWhile(fastIsLowerCase); } + function skipUpperCase(): void { skipWhile(fastIsUpperCase); } + function skipNonLetter(): void { skipWhile(fastNonLetter); } + function skipDigits(): void { skipWhile(fastIsDigit); } function startInterval(): void { - assert(intervalStart === undefined, "Interval started before last one was committed"); + assert( + intervalStart === undefined, + "Interval started before last one was committed", + ); intervalStart = i; } @@ -380,6 +424,7 @@ export function splitIntoWords(s: string): WordInName[] { if (intervalStart === undefined) { return panic("Tried to commit interval without starting one"); } + assert(i > intervalStart, "Interval must be non-empty"); // FIXME: This is a hack to avoid splitting up surrogates. We shouldn't // look at surrogates individually in the first place. When we @@ -389,7 +434,10 @@ export function splitIntoWords(s: string): WordInName[] { if (!atEnd() && isLowSurrogate(currentCodePoint())) { i += 1; } - const allUpper = lastLowerCaseIndex === undefined || lastLowerCaseIndex < intervalStart; + + const allUpper = + lastLowerCaseIndex === undefined || + lastLowerCaseIndex < intervalStart; intervals.push([intervalStart, i, allUpper]); intervalStart = undefined; } @@ -398,6 +446,7 @@ export function splitIntoWords(s: string): WordInName[] { if (intervalStart === undefined) { return panic("Tried to get interval length without starting one"); } + return i - intervalStart; } @@ -425,6 +474,7 @@ export function splitIntoWords(s: string): WordInName[] { if (fastIsWordCharacter(currentCodePoint())) { i -= 1; } + commitInterval(); } } else { @@ -436,9 +486,12 @@ export function splitIntoWords(s: string): WordInName[] { const words: WordInName[] = []; for (const [start, end, allUpper] of intervals) { const word = s.slice(start, end); - const isAcronym = (lastLowerCaseIndex !== undefined && allUpper) || knownAcronyms.has(word.toLowerCase()); + const isAcronym = + (lastLowerCaseIndex !== undefined && allUpper) || + knownAcronyms.has(word.toLowerCase() as (typeof acronyms)[number]); words.push({ word, isAcronym }); } + return words; } @@ -476,7 +529,7 @@ export function combineWords( firstWordAcronymStyle: WordStyle, restAcronymStyle: WordStyle, separator: string, - isStartCharacter: (codePoint: number) => boolean + isStartCharacter: (codePoint: number) => boolean, ): string { const legalizedWords: WordInName[] = []; for (const w of words) { @@ -487,7 +540,10 @@ export function combineWords( if (legalizedWords.length === 0) { const validEmpty = removeInvalidCharacters("empty"); - assert(validEmpty.length > 0, 'Word "empty" is invalid in target language'); + assert( + validEmpty.length > 0, + 'Word "empty" is invalid in target language', + ); legalizedWords.push({ word: validEmpty, isAcronym: false }); } @@ -498,11 +554,14 @@ export function combineWords( let restWords: WordInName[]; if (!isStartCharacter(defined(styledFirstWord.codePointAt(0)))) { const validThe = removeInvalidCharacters("the"); - assert(validThe.length > 0, 'Word "the" is invalid in the target language'); + assert( + validThe.length > 0, + 'Word "the" is invalid in the target language', + ); const styledThe = styleWord(firstWordStyle, validThe); assert( isStartCharacter(defined(styledThe.codePointAt(0))), - 'The first character of styling "the" is not a start character' + 'The first character of styling "the" is not a start character', ); styledWords.push(styledThe); restWords = legalizedWords; @@ -527,7 +586,7 @@ export function addPrefixIfNecessary(prefix: string, name: string): string { export function makeNameStyle( namingStyle: NamingStyle, legalizeName: (name: string) => string, - prefix?: string + prefix?: string, ): (rawName: string) => string { let separator: string; let firstWordStyle: WordStyle; @@ -542,7 +601,10 @@ export function makeNameStyle( namingStyle === "camel-upper-acronyms" ) { separator = ""; - if (namingStyle === "pascal-upper-acronyms" || namingStyle === "camel-upper-acronyms") { + if ( + namingStyle === "pascal-upper-acronyms" || + namingStyle === "camel-upper-acronyms" + ) { restWordStyle = firstUpperWordStyle; restAcronymStyle = allUpperWordStyle; } else { @@ -551,6 +613,7 @@ export function makeNameStyle( } else { separator = "_"; } + switch (namingStyle) { case "pascal": case "pascal-upper-acronyms": @@ -561,10 +624,18 @@ export function makeNameStyle( firstWordStyle = firstWordAcronymStyle = allLowerWordStyle; break; case "underscore": - firstWordStyle = restWordStyle = firstWordAcronymStyle = restAcronymStyle = allLowerWordStyle; + firstWordStyle = + restWordStyle = + firstWordAcronymStyle = + restAcronymStyle = + allLowerWordStyle; break; case "upper-underscore": - firstWordStyle = restWordStyle = firstWordAcronymStyle = restAcronymStyle = allUpperWordStyle; + firstWordStyle = + restWordStyle = + firstWordAcronymStyle = + restAcronymStyle = + allUpperWordStyle; break; default: return assertNever(namingStyle); @@ -581,7 +652,7 @@ export function makeNameStyle( firstWordAcronymStyle, restAcronymStyle, separator, - isLetterOrUnderscore + isLetterOrUnderscore, ); if (prefix !== undefined) { diff --git a/packages/quicktype-core/src/support/Support.ts b/packages/quicktype-core/src/support/Support.ts index 810219df8..d81fa26fe 100644 --- a/packages/quicktype-core/src/support/Support.ts +++ b/packages/quicktype-core/src/support/Support.ts @@ -1,44 +1,76 @@ import { Base64 } from "js-base64"; import * as pako from "pako"; -import { messageError } from "../Messages"; import * as YAML from "yaml"; -export type StringMap = { [name: string]: any }; +import type { JSONSchema } from "../input/JSONSchemaStore"; +import { messageError } from "../Messages"; -export function isStringMap(x: any): x is StringMap; -export function isStringMap(x: any, checkValue: (v: any) => v is T): x is { [name: string]: T }; -export function isStringMap(x: any, checkValue?: (v: any) => v is T): boolean { +export interface StringMap { + [name: string]: any; +} + +export function isStringMap(x: unknown): x is StringMap; +export function isStringMap( + x: unknown, + checkValue: (v: unknown) => v is T, +): x is { [name: string]: T }; +export function isStringMap( + x: unknown, + checkValue?: (v: unknown) => v is T, +): boolean { if (typeof x !== "object" || Array.isArray(x) || x === null) { return false; } + if (checkValue !== undefined) { for (const k of Object.getOwnPropertyNames(x)) { - const v = x[k]; + const v = x[k as keyof typeof x]; if (!checkValue(v)) { return false; } } } + return true; } -export function checkString(x: any): x is string { +export function checkString(x: unknown): x is string { return typeof x === "string"; } -export function checkStringMap(x: any): StringMap; -export function checkStringMap(x: any, checkValue: (v: any) => v is T): { [name: string]: T }; -export function checkStringMap(x: any, checkValue?: (v: any) => v is T): StringMap { - if (isStringMap(x, checkValue as any)) return x; +export function checkStringMap(x: unknown): StringMap; +export function checkStringMap( + x: unknown, + checkValue: (v: unknown) => v is T, +): { [name: string]: T }; +export function checkStringMap( + x: unknown, + checkValue?: (v: unknown) => v is T, +): StringMap { + if (checkValue && isStringMap(x, checkValue)) { + return x; + } + + if (isStringMap(x)) { + return x; + } + return panic(`Value must be an object, but is ${x}`); } -export function checkArray(x: any): any[]; -export function checkArray(x: any, checkItem: (v: any) => v is T): T[]; -export function checkArray(x: any, checkItem?: (v: any) => v is T): T[] { +export function checkArray(x: unknown): unknown[]; +export function checkArray( + x: unknown, + checkItem: (v: unknown) => v is T, +): T[]; +export function checkArray( + x: unknown, + checkItem?: (v: unknown) => v is T, +): T[] { if (!Array.isArray(x)) { return panic(`Value must be an array, but is ${x}`); } + if (checkItem !== undefined) { for (const v of x) { if (!checkItem(v)) { @@ -46,6 +78,7 @@ export function checkArray(x: any, checkItem?: (v: any) => v is T): T[] { } } } + return x; } @@ -60,7 +93,7 @@ export function nonNull(x: T | null): T { } export function assertNever(x: never): never { - return messageError("InternalError", { message: `Unexpected object ${x as any}` }); + return messageError("InternalError", { message: `Unexpected object ${x}` }); } export function assert(condition: boolean, message = "Assertion failed"): void { @@ -82,6 +115,7 @@ export function repeated(n: number, value: T): T[] { for (let i = 0; i < n; i++) { arr.push(value); } + return arr; } @@ -90,14 +124,16 @@ export function repeatedCall(n: number, producer: () => T): T[] { for (let i = 0; i < n; i++) { arr.push(producer()); } + return arr; } -export function errorMessage(e: any): string { +export function errorMessage(e: unknown): string { if (e instanceof Error) { return e.message; } - return e.toString(); + + return (e as { toString: () => string }).toString(); } export function inflateBase64(encoded: string): string { @@ -105,12 +141,17 @@ export function inflateBase64(encoded: string): string { return pako.inflate(bytes, { to: "string" }); } -export function parseJSON(text: string, description: string, address = ""): any { +export function parseJSON( + text: string, + description: string, + address = "", +): JSONSchema | undefined { try { // https://gist.github.com/pbakondy/f5045eff725193dad9c7 if (text.charCodeAt(0) === 0xfeff) { text = text.slice(1); } + return YAML.parse(text); } catch (e) { let message: string; @@ -121,7 +162,11 @@ export function parseJSON(text: string, description: string, address = ", +): number[] { const result: number[] = []; for (const k of Object.keys(e)) { const v = e[k]; @@ -137,5 +185,6 @@ export function numberEnumValues(e: { [key: string]: any }): number[] { result.push(v); } } + return result; } diff --git a/packages/quicktype-core/src/types.ts b/packages/quicktype-core/src/types.ts new file mode 100644 index 000000000..e692e2b8d --- /dev/null +++ b/packages/quicktype-core/src/types.ts @@ -0,0 +1,2 @@ +export * from "./language/types"; +export * from "./language/options.types"; diff --git a/packages/quicktype-graphql-input/package.json b/packages/quicktype-graphql-input/package.json index ae4b23648..6a95cf3dd 100644 --- a/packages/quicktype-graphql-input/package.json +++ b/packages/quicktype-graphql-input/package.json @@ -8,8 +8,7 @@ "repository": "https://github.com/quicktype/quicktype", "scripts": { "clean": "rm -rf dist node_modules *~", - "build": "tsc", - "tslint": "tslint --project ." + "build": "tsc" }, "dependencies": { "quicktype-core": "file:../quicktype-core", @@ -17,12 +16,9 @@ "graphql": "^0.11.7" }, "devDependencies": { - "@types/node": "18.14.0", + "@types/node": "~22.14.0", "@types/graphql": "^0.11.7", - "typescript": "4.9.5", - "tslint": "^6.1.3" + "typescript": "~5.8.3" }, - "files": [ - "dist" - ] + "files": ["dist"] } diff --git a/packages/quicktype-graphql-input/src/GraphQLSchema.ts b/packages/quicktype-graphql-input/src/GraphQLSchema.ts index 5f8d570b9..77e762f75 100644 --- a/packages/quicktype-graphql-input/src/GraphQLSchema.ts +++ b/packages/quicktype-graphql-input/src/GraphQLSchema.ts @@ -1,4 +1,4 @@ -/* tslint:disable */ +/* eslint-disable */ // This file was automatically generated and should not be edited. // A Directive can be adjacent to many parts of the GraphQL language, a __DirectiveLocation describes one such possible adjacencies. @@ -20,7 +20,7 @@ export enum __DirectiveLocation { ENUM = "ENUM", // Location adjacent to an enum definition. ENUM_VALUE = "ENUM_VALUE", // Location adjacent to an enum value definition. INPUT_OBJECT = "INPUT_OBJECT", // Location adjacent to an input object type definition. - INPUT_FIELD_DEFINITION = "INPUT_FIELD_DEFINITION" // Location adjacent to an input object field definition. + INPUT_FIELD_DEFINITION = "INPUT_FIELD_DEFINITION", // Location adjacent to an input object field definition. } // An enum describing what kind of type a given `__Type` is. @@ -32,7 +32,7 @@ export enum TypeKind { ENUM = "ENUM", // Indicates this type is an enum. `enumValues` is a valid field. INPUT_OBJECT = "INPUT_OBJECT", // Indicates this type is an input object. `inputFields` is a valid field. LIST = "LIST", // Indicates this type is a list. `ofType` is a valid field. - NON_NULL = "NON_NULL" // Indicates this type is a non-null. `ofType` is a valid field. + NON_NULL = "NON_NULL", // Indicates this type is a non-null. `ofType` is a valid field. } export type GraphQLSchema = { diff --git a/packages/quicktype-graphql-input/src/index.ts b/packages/quicktype-graphql-input/src/index.ts index bd3cc0feb..7bce8160c 100644 --- a/packages/quicktype-graphql-input/src/index.ts +++ b/packages/quicktype-graphql-input/src/index.ts @@ -1,86 +1,94 @@ -/* tslint:disable:strict-boolean-expressions */ - -import { +import { iterableFirst, mapFromObject, setMap } from "collection-utils"; +import * as graphql from "graphql/language"; +import type { + DirectiveNode, DocumentNode, - SelectionSetNode, - SelectionNode, - OperationDefinitionNode, + FieldNode, FragmentDefinitionNode, - DirectiveNode, - FieldNode + OperationDefinitionNode, + SelectionNode, + SelectionSetNode, } from "graphql/language/ast"; -import * as graphql from "graphql/language"; -import { setMap, iterableFirst, mapFromObject } from "collection-utils"; - import { + type ClassProperty, + type Input, + type RunContext, + StringTypes, + type TypeAttributes, + type TypeBuilder, + TypeNames, + type TypeRef, UnionType, - ClassProperty, - removeNullFromUnion, assertNever, - panic, - TypeBuilder, - TypeRef, - TypeNames, + derefTypeRef, + emptyTypeAttributes, makeNamesTypeAttributes, - namesTypeAttributeKind, messageAssert, - TypeAttributes, - emptyTypeAttributes, - StringTypes, - Input, - derefTypeRef, - RunContext + namesTypeAttributeKind, + panic, + removeNullFromUnion, } from "quicktype-core"; -import { TypeKind, GraphQLSchema } from "./GraphQLSchema"; +import { type GraphQLSchema, TypeKind } from "./GraphQLSchema"; interface GQLType { - kind: TypeKind; - name?: string; description?: string; - ofType?: GQLType; + enumValues?: EnumValue[]; fields?: Field[]; + inputFields?: InputValue[]; interfaces?: GQLType[]; + kind: TypeKind; + name?: string; + ofType?: GQLType; possibleTypes?: GQLType[]; - inputFields?: InputValue[]; - enumValues?: EnumValue[]; } interface EnumValue { - name: string; description?: string; + name: string; } interface Field { - name: string; + args: InputValue[]; description?: string; + name: string; type: GQLType; - args: InputValue[]; } interface InputValue { - name: string; + defaultValue?: string; description?: string; + name: string; type: GQLType; - defaultValue?: string; } function getField(t: GQLType, name: string): Field { - if (!t.fields) return panic(`Required field ${name} in type ${t.name} which doesn't have fields.`); + if (!t.fields) + return panic( + `Required field ${name} in type ${t.name} which doesn't have fields.`, + ); for (const f of t.fields) { if (f.name === name) { return f; } } + return panic(`Required field ${name} not defined on type ${t.name}.`); } -function makeNames(name: string, fieldName: string | null, containingTypeName: string | null): TypeAttributes { +function makeNames( + name: string, + fieldName: string | null, + containingTypeName: string | null, +): TypeAttributes { const alternatives: string[] = []; if (fieldName) alternatives.push(fieldName); if (containingTypeName) alternatives.push(`${containingTypeName}_${name}`); - if (fieldName && containingTypeName) alternatives.push(`${containingTypeName}_${fieldName}`); - return namesTypeAttributeKind.makeAttributes(TypeNames.make(new Set([name]), new Set(alternatives), false)); + if (fieldName && containingTypeName) + alternatives.push(`${containingTypeName}_${fieldName}`); + return namesTypeAttributeKind.makeAttributes( + TypeNames.make(new Set([name]), new Set(alternatives), false), + ); } function makeNullable( @@ -88,16 +96,25 @@ function makeNullable( tref: TypeRef, name: string, fieldName: string | null, - containingTypeName: string + containingTypeName: string, ): TypeRef { const typeNames = makeNames(name, fieldName, containingTypeName); const t = derefTypeRef(tref, builder.typeGraph); if (!(t instanceof UnionType)) { - return builder.getUnionType(typeNames, new Set([tref, builder.getPrimitiveType("null")])); + return builder.getUnionType( + typeNames, + new Set([tref, builder.getPrimitiveType("null")]), + ); } + const [maybeNull, nonNulls] = removeNullFromUnion(t); if (maybeNull) return tref; - return builder.getUnionType(typeNames, setMap(nonNulls, nn => nn.typeRef).add(builder.getPrimitiveType("null"))); + return builder.getUnionType( + typeNames, + setMap(nonNulls, (nn) => nn.typeRef).add( + builder.getPrimitiveType("null"), + ), + ); } // This is really not the way to do this, but it's easy and works. By default @@ -111,15 +128,17 @@ function removeNull(builder: TypeBuilder, tref: TypeRef): TypeRef { if (!(t instanceof UnionType)) { return tref; } + const nonNulls = removeNullFromUnion(t)[1]; const first = iterableFirst(nonNulls); if (first) { if (nonNulls.size === 1) return first.typeRef; return builder.getUnionType( t.getAttributes(), - setMap(nonNulls, nn => nn.typeRef) + setMap(nonNulls, (nn) => nn.typeRef), ); } + return panic("Trying to remove null results in empty union."); } @@ -133,7 +152,10 @@ function makeScalar(builder: TypeBuilder, ft: GQLType): TypeRef { return builder.getPrimitiveType("double"); default: // FIXME: support ID specifically? - return builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted); + return builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ); } } @@ -143,34 +165,44 @@ function hasOptionalDirectives(directives?: DirectiveNode[]): boolean { const name = d.name.value; if (name === "include" || name === "skip") return true; } + return false; } interface Selection { - selection: SelectionNode; inType: GQLType; optional: boolean; + selection: SelectionNode; } -function expandSelectionSet(selectionSet: SelectionSetNode, inType: GQLType, optional: boolean): Selection[] { +function expandSelectionSet( + selectionSet: SelectionSetNode, + inType: GQLType, + optional: boolean, +): Selection[] { return selectionSet.selections .reverse() - .map(s => ({ selection: s, inType, optional: optional || hasOptionalDirectives(s.directives) })); + .map((s) => ({ + selection: s, + inType, + optional: optional || hasOptionalDirectives(s.directives), + })); } interface GQLSchema { - readonly types: { [name: string]: GQLType }; - readonly queryType: GQLType; readonly mutationType?: GQLType; + readonly queryType: GQLType; + readonly types: { [name: string]: GQLType }; } class GQLQuery { private readonly _schema: GQLSchema; + private readonly _fragments: { [name: string]: FragmentDefinitionNode }; - readonly queries: ReadonlyArray; + public readonly queries: readonly OperationDefinitionNode[]; - constructor(schema: GQLSchema, queryString: string) { + public constructor(schema: GQLSchema, queryString: string) { this._schema = schema; this._fragments = {}; @@ -185,15 +217,16 @@ class GQLQuery { this._fragments[def.name.value] = def; } } + messageAssert(queries.length >= 1, "GraphQLNoQueriesDefined", {}); this.queries = queries; } - private makeIRTypeFromFieldNode = ( + private readonly makeIRTypeFromFieldNode = ( builder: TypeBuilder, fieldNode: FieldNode, fieldType: GQLType, - containingTypeName: string + containingTypeName: string, ): TypeRef => { let optional = hasOptionalDirectives(fieldNode.directives); let result: TypeRef; @@ -208,6 +241,7 @@ class GQLQuery { if (!fieldNode.selectionSet) { return panic("No selection set on object or interface"); } + return makeNullable( builder, this.makeIRTypeFromSelectionSet( @@ -215,17 +249,18 @@ class GQLQuery { fieldNode.selectionSet, fieldType, fieldNode.name.value, - containingTypeName + containingTypeName, ), fieldNode.name.value, null, - containingTypeName + containingTypeName, ); case TypeKind.ENUM: if (!fieldType.enumValues) { return panic("Enum type doesn't have values"); } - const values = fieldType.enumValues.map(ev => ev.name); + + const values = fieldType.enumValues.map((ev) => ev.name); let name: string; let fieldName: string | null; if (fieldType.name) { @@ -235,8 +270,12 @@ class GQLQuery { name = fieldNode.name.value; fieldName = null; } + optional = true; - result = builder.getEnumType(makeNames(name, fieldName, containingTypeName), new Set(values)); + result = builder.getEnumType( + makeNames(name, fieldName, containingTypeName), + new Set(values), + ); break; case TypeKind.INPUT_OBJECT: // FIXME: Support input objects @@ -245,55 +284,81 @@ class GQLQuery { if (!fieldType.ofType) { return panic("No type for list"); } + optional = true; result = builder.getArrayType( emptyTypeAttributes, - this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName) + this.makeIRTypeFromFieldNode( + builder, + fieldNode, + fieldType.ofType, + containingTypeName, + ), ); break; case TypeKind.NON_NULL: if (!fieldType.ofType) { return panic("No type for non-null"); } + result = removeNull( builder, - this.makeIRTypeFromFieldNode(builder, fieldNode, fieldType.ofType, containingTypeName) + this.makeIRTypeFromFieldNode( + builder, + fieldNode, + fieldType.ofType, + containingTypeName, + ), ); break; default: return assertNever(fieldType.kind); } + if (optional) { - result = makeNullable(builder, result, fieldNode.name.value, null, containingTypeName); + result = makeNullable( + builder, + result, + fieldNode.name.value, + null, + containingTypeName, + ); } + return result; }; - private getFragment = (name: string): FragmentDefinitionNode => { + private readonly getFragment = (name: string): FragmentDefinitionNode => { const fragment = this._fragments[name]; if (!fragment) return panic(`Fragment ${name} is not defined.`); return fragment; }; - private makeIRTypeFromSelectionSet = ( + private readonly makeIRTypeFromSelectionSet = ( builder: TypeBuilder, selectionSet: SelectionSetNode, gqlType: GQLType, containingFieldName: string | null, containingTypeName: string | null, - overrideName?: string + overrideName?: string, ): TypeRef => { if ( gqlType.kind !== TypeKind.OBJECT && gqlType.kind !== TypeKind.INTERFACE && gqlType.kind !== TypeKind.UNION ) { - return panic("Type for selection set is not object, interface, or union."); + return panic( + "Type for selection set is not object, interface, or union.", + ); } + if (!gqlType.name) { - return panic("Object, interface, or union type doesn't have a name."); + return panic( + "Object, interface, or union type doesn't have a name.", + ); } - const nameOrOverride = overrideName || gqlType.name; + + const nameOrOverride = overrideName ?? gqlType.name; const properties = new Map(); let selections = expandSelectionSet(selectionSet, gqlType, false); for (;;) { @@ -303,38 +368,70 @@ class GQLQuery { switch (selection.kind) { case "Field": const fieldName = selection.name.value; - const givenName = selection.alias ? selection.alias.value : fieldName; + const givenName = selection.alias + ? selection.alias.value + : fieldName; const field = getField(inType, fieldName); - let fieldType = this.makeIRTypeFromFieldNode(builder, selection, field.type, nameOrOverride); - properties.set(givenName, builder.makeClassProperty(fieldType, optional)); + const fieldType = this.makeIRTypeFromFieldNode( + builder, + selection, + field.type, + nameOrOverride, + ); + properties.set( + givenName, + builder.makeClassProperty(fieldType, optional), + ); break; case "FragmentSpread": { const fragment = this.getFragment(selection.name.value); - const fragmentType = this._schema.types[fragment.typeCondition.name.value]; - const fragmentOptional = optional || fragmentType.name !== inType.name; - const expanded = expandSelectionSet(fragment.selectionSet, fragmentType, fragmentOptional); + const fragmentType = + this._schema.types[fragment.typeCondition.name.value]; + const fragmentOptional = + optional || fragmentType.name !== inType.name; + const expanded = expandSelectionSet( + fragment.selectionSet, + fragmentType, + fragmentOptional, + ); selections = selections.concat(expanded); break; } + case "InlineFragment": { // FIXME: support type conditions with discriminated unions const fragmentType = selection.typeCondition ? this._schema.types[selection.typeCondition.name.value] : inType; const fragmentOptional = - optional || fragmentType.name !== inType.name || hasOptionalDirectives(selection.directives); - const expanded = expandSelectionSet(selection.selectionSet, fragmentType, fragmentOptional); + optional || + fragmentType.name !== inType.name || + hasOptionalDirectives(selection.directives); + const expanded = expandSelectionSet( + selection.selectionSet, + fragmentType, + fragmentOptional, + ); selections = selections.concat(expanded); break; } + default: assertNever(selection); } } - return builder.getClassType(makeNames(nameOrOverride, containingFieldName, containingTypeName), properties); + + return builder.getClassType( + makeNames(nameOrOverride, containingFieldName, containingTypeName), + properties, + ); }; - makeType(builder: TypeBuilder, query: OperationDefinitionNode, queryName: string): TypeRef { + public makeType( + builder: TypeBuilder, + query: OperationDefinitionNode, + queryName: string, + ): TypeRef { if (query.operation === "query") { return this.makeIRTypeFromSelectionSet( builder, @@ -342,7 +439,7 @@ class GQLQuery { this._schema.queryType, null, queryName, - "data" + "data", ); } @@ -357,7 +454,7 @@ class GQLQuery { this._schema.mutationType, null, queryName, - "data" + "data", ); } @@ -366,13 +463,14 @@ class GQLQuery { } class GQLSchemaFromJSON implements GQLSchema { - readonly types: { [name: string]: GQLType } = {}; - // @ts-ignore: The constructor can return early, but only by throwing. - readonly queryType: GQLType; - // @ts-ignore: The constructor can return early, but only by throwing. - readonly mutationType?: GQLType; + public readonly types: { [name: string]: GQLType } = {}; - constructor(json: any) { + // @ts-expect-error: The constructor can return early, but only by throwing. + public readonly queryType: GQLType; + + public readonly mutationType?: GQLType; + + public constructor(json: { data: GraphQLSchema }) { const schema: GraphQLSchema = json.data; if (schema.__schema.queryType.name === null) { @@ -381,8 +479,13 @@ class GQLSchemaFromJSON implements GQLSchema { for (const t of schema.__schema.types as GQLType[]) { if (!t.name) return panic("No top-level type name given"); - this.types[t.name] = { kind: t.kind, name: t.name, description: t.description }; + this.types[t.name] = { + kind: t.kind, + name: t.name, + description: t.description, + }; } + for (const t of schema.__schema.types) { if (!t.name) return panic("This cannot happen"); const type = this.types[t.name]; @@ -394,6 +497,7 @@ class GQLSchemaFromJSON implements GQLSchema { if (queryType === undefined) { return panic("Query type not found."); } + // console.log(`query type ${queryType.name} is ${queryType.kind}`); this.queryType = queryType; @@ -413,58 +517,67 @@ class GQLSchemaFromJSON implements GQLSchema { this.mutationType = mutationType; } - private addTypeFields = (target: GQLType, source: GQLType): void => { + private readonly addTypeFields = ( + target: GQLType, + source: GQLType, + ): void => { if (source.fields) { - target.fields = source.fields.map(f => { + target.fields = source.fields.map((f) => { return { name: f.name, description: f.description, type: this.makeType(f.type), - args: f.args.map(this.makeInputValue) + args: f.args.map(this.makeInputValue), }; }); // console.log(`${target.name} has ${target.fields.length} fields`); } + if (source.interfaces) { target.interfaces = source.interfaces.map(this.makeType); // console.log(`${target.name} has ${target.interfaces.length} interfaces`); } + if (source.possibleTypes) { target.possibleTypes = source.possibleTypes.map(this.makeType); // console.log(`${target.name} has ${target.possibleTypes.length} possibleTypes`); } + if (source.inputFields) { target.inputFields = source.inputFields.map(this.makeInputValue); // console.log(`${target.name} has ${target.inputFields.length} inputFields`); } + if (source.enumValues) { - target.enumValues = source.enumValues.map(ev => { + target.enumValues = source.enumValues.map((ev) => { return { name: ev.name, description: ev.description }; }); // console.log(`${target.name} has ${target.enumValues.length} enumValues`); } }; - private makeInputValue = (iv: InputValue): InputValue => { + private readonly makeInputValue = (iv: InputValue): InputValue => { return { name: iv.name, description: iv.description, type: this.makeType(iv.type), - defaultValue: iv.defaultValue + defaultValue: iv.defaultValue, }; }; - private makeType = (t: GQLType): GQLType => { + private readonly makeType = (t: GQLType): GQLType => { if (t.name) { const namedType = this.types[t.name]; if (!namedType) return panic(`Type ${t.name} not found`); return namedType; } - if (!t.ofType) return panic(`Type of kind ${t.kind} has neither name nor ofType`); + + if (!t.ofType) + return panic(`Type of kind ${t.kind} has neither name nor ofType`); const type: GQLType = { kind: t.kind, description: t.description, - ofType: this.makeType(t.ofType) + ofType: this.makeType(t.ofType), }; this.addTypeFields(type, t); return type; @@ -474,8 +587,8 @@ class GQLSchemaFromJSON implements GQLSchema { function makeGraphQLQueryTypes( topLevelName: string, builder: TypeBuilder, - json: any, - queryString: string + json: { data: GraphQLSchema }, + queryString: string, ): Map { const schema = new GQLSchemaFromJSON(json); const query = new GQLQuery(schema, queryString); @@ -485,73 +598,110 @@ function makeGraphQLQueryTypes( if (types.has(queryName)) { return panic(`Duplicate query name ${queryName}`); } + const dataType = query.makeType(builder, odn, queryName); const dataOrNullType = builder.getUnionType( emptyTypeAttributes, - new Set([dataType, builder.getPrimitiveType("null")]) + new Set([dataType, builder.getPrimitiveType("null")]), ); const errorType = builder.getClassType( - namesTypeAttributeKind.makeAttributes(TypeNames.make(new Set(["error"]), new Set(["graphQLError"]), false)), + namesTypeAttributeKind.makeAttributes( + TypeNames.make( + new Set(["error"]), + new Set(["graphQLError"]), + false, + ), + ), mapFromObject({ message: builder.makeClassProperty( - builder.getStringType(emptyTypeAttributes, StringTypes.unrestricted), - false - ) - }) + builder.getStringType( + emptyTypeAttributes, + StringTypes.unrestricted, + ), + false, + ), + }), ); const errorArray = builder.getArrayType( namesTypeAttributeKind.makeAttributes( - TypeNames.make(new Set(["errors"]), new Set(["graphQLErrors"]), false) + TypeNames.make( + new Set(["errors"]), + new Set(["graphQLErrors"]), + false, + ), ), - errorType + errorType, ); const t = builder.getClassType( makeNamesTypeAttributes(queryName, false), mapFromObject({ data: builder.makeClassProperty(dataOrNullType, false), - errors: builder.makeClassProperty(errorArray, true) - }) + errors: builder.makeClassProperty(errorArray, true), + }), ); types.set(queryName, t); } + return types; } -export type GraphQLSourceData = { name: string; schema: any; query: string }; +export interface GraphQLSourceData { + name: string; + query: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + schema: any; +} -type GraphQLTopLevel = { schema: any; query: string }; +interface GraphQLTopLevel { + query: string; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + schema: any; +} export class GraphQLInput implements Input { - readonly kind: string = "graphql"; - readonly needIR: boolean = true; - readonly needSchemaProcessing: boolean = false; + public readonly kind: string = "graphql"; + + public readonly needIR: boolean = true; + + public readonly needSchemaProcessing: boolean = false; private readonly _topLevels: Map = new Map(); - async addSource(source: GraphQLSourceData): Promise { + public async addSource(source: GraphQLSourceData): Promise { this.addSourceSync(source); } - addSourceSync(source: GraphQLSourceData): void { + public addSourceSync(source: GraphQLSourceData): void { this._topLevels.set(source.name, { schema: source.schema, - query: source.query + query: source.query, }); } - singleStringSchemaSource(): undefined { + public singleStringSchemaSource(): undefined { return undefined; } - async addTypes(ctx: RunContext, typeBuilder: TypeBuilder): Promise { - return this.addTypesSync(ctx, typeBuilder); + public async addTypes( + ctx: RunContext, + typeBuilder: TypeBuilder, + ): Promise { + this.addTypesSync(ctx, typeBuilder); } - addTypesSync(_ctx: RunContext, typeBuilder: TypeBuilder): void { + public addTypesSync(_ctx: RunContext, typeBuilder: TypeBuilder): void { for (const [name, { schema, query }] of this._topLevels) { - const newTopLevels = makeGraphQLQueryTypes(name, typeBuilder, schema, query); + const newTopLevels = makeGraphQLQueryTypes( + name, + typeBuilder, + schema, + query, + ); for (const [actualName, t] of newTopLevels) { - typeBuilder.addTopLevel(this._topLevels.size === 1 ? name : actualName, t); + typeBuilder.addTopLevel( + this._topLevels.size === 1 ? name : actualName, + t, + ); } } } diff --git a/packages/quicktype-typescript-input/package.json b/packages/quicktype-typescript-input/package.json index 9926b394e..ee5b0442a 100644 --- a/packages/quicktype-typescript-input/package.json +++ b/packages/quicktype-typescript-input/package.json @@ -8,8 +8,7 @@ "repository": "https://github.com/quicktype/quicktype", "scripts": { "clean": "rm -rf dist node_modules *~", - "build": "tsc", - "tslint": "tslint --project ." + "build": "tsc" }, "dependencies": { "quicktype-core": "file:../quicktype-core", @@ -17,10 +16,7 @@ "@mark.probst/typescript-json-schema": "0.55.0" }, "devDependencies": { - "@types/node": "18.14.0", - "tslint": "^6.1.3" + "@types/node": "~22.14.0" }, - "files": [ - "dist" - ] + "files": ["dist"] } diff --git a/packages/quicktype-typescript-input/src/index.ts b/packages/quicktype-typescript-input/src/index.ts index 145cc50e1..6cf0cc424 100644 --- a/packages/quicktype-typescript-input/src/index.ts +++ b/packages/quicktype-typescript-input/src/index.ts @@ -1,13 +1,19 @@ +import { + type PartialArgs, + generateSchema, +} from "@mark.probst/typescript-json-schema"; +import { + type JSONSchemaSourceData, + defined, + messageError, +} from "quicktype-core"; import * as ts from "typescript"; -import { PartialArgs, generateSchema } from "@mark.probst/typescript-json-schema"; - -import { defined, JSONSchemaSourceData, messageError } from "quicktype-core"; const settings: PartialArgs = { required: true, titles: true, topRef: true, - noExtraProps: true + noExtraProps: true, }; const compilerOptions: ts.CompilerOptions = { @@ -18,25 +24,57 @@ const compilerOptions: ts.CompilerOptions = { module: ts.ModuleKind.CommonJS, strictNullChecks: true, typeRoots: [], - rootDir: "." + rootDir: ".", }; -// FIXME: We're stringifying and then parsing this schema again. Just pass around +// FIXME: We're stringifying and then parsing this schema again. Just pass around // the schema directly. -export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchemaSourceData { +export function schemaForTypeScriptSources( + sourceFileNames: string[], +): JSONSchemaSourceData { const program = ts.createProgram(sourceFileNames, compilerOptions); const diagnostics = ts.getPreEmitDiagnostics(program); - const error = diagnostics.find(d => d.category === ts.DiagnosticCategory.Error); + const error = diagnostics.find( + (d) => d.category === ts.DiagnosticCategory.Error, + ); if (error !== undefined) { return messageError("TypeScriptCompilerError", { - message: ts.flattenDiagnosticMessageText(error.messageText, "\n") + message: ts.flattenDiagnosticMessageText(error.messageText, "\n"), }); } + // this breaks after upgrading to TS 5+ const schema = generateSchema(program, "*", settings); const uris: string[] = []; - let topLevelName: string | undefined = undefined; - if (schema !== null && typeof schema === "object" && typeof schema.definitions === "object") { + let topLevelName = ""; + + // if there is a type that is `export default`, swap the corresponding ref + if (schema?.definitions?.default) { + const defaultDefinition = schema?.definitions?.default; + const matchingDefaultName = Object.entries( + schema?.definitions ?? {}, + ).find( + ([_name, definition]) => + (definition as Record).$ref === + "#/definitions/default", + )?.[0]; + + if (matchingDefaultName) { + topLevelName = matchingDefaultName; + (defaultDefinition as Record).title = topLevelName; + + schema.definitions[matchingDefaultName] = defaultDefinition; + schema.definitions.default = { + $ref: `#/definitions/${matchingDefaultName}`, + }; + } + } + + if ( + schema !== null && + typeof schema === "object" && + typeof schema.definitions === "object" + ) { for (const name of Object.getOwnPropertyNames(schema.definitions)) { const definition = schema.definitions[name]; if ( @@ -49,32 +87,36 @@ export function schemaForTypeScriptSources(sourceFileNames: string[]): JSONSchem } const description = definition.description as string; - const matches = description.match(/#TopLevel/); + const matches = /#TopLevel/.exec(description); if (matches === null) { continue; } const index = defined(matches.index); - definition.description = description.slice(0, index) + description.slice(index + matches[0].length); + definition.description = + description.slice(0, index) + + description.slice(index + matches[0].length); uris.push(`#/definitions/${name}`); - if (topLevelName === undefined) { + if (!topLevelName) { if (typeof definition.title === "string") { topLevelName = definition.title; } else { topLevelName = name; } - } else { - topLevelName = ""; } } } + if (uris.length === 0) { uris.push("#/definitions/"); } - if (topLevelName === undefined) { - topLevelName = ""; - } - return { schema: JSON.stringify(schema), name: topLevelName, uris, isConverted: true }; + + return { + schema: JSON.stringify(schema), + name: topLevelName, + uris, + isConverted: true, + }; } diff --git a/packages/quicktype-vscode/.gitignore b/packages/quicktype-vscode/.gitignore new file mode 100644 index 000000000..c585e1938 --- /dev/null +++ b/packages/quicktype-vscode/.gitignore @@ -0,0 +1 @@ +out \ No newline at end of file diff --git a/packages/quicktype-vscode/.vscodeignore b/packages/quicktype-vscode/.vscodeignore new file mode 100644 index 000000000..a92fd112a --- /dev/null +++ b/packages/quicktype-vscode/.vscodeignore @@ -0,0 +1,5 @@ +.vscode +node_modules +out/ +src/ +tsconfig.json \ No newline at end of file diff --git a/packages/quicktype-vscode/LICENSE b/packages/quicktype-vscode/LICENSE new file mode 100644 index 000000000..8dada3eda --- /dev/null +++ b/packages/quicktype-vscode/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright {yyyy} {name of copyright owner} + + 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. diff --git a/packages/quicktype-vscode/README.md b/packages/quicktype-vscode/README.md new file mode 100644 index 000000000..652fb05fa --- /dev/null +++ b/packages/quicktype-vscode/README.md @@ -0,0 +1,32 @@ +**Supports** `C (cJSON)`, `C#`, `C++`, `Crystal`, `Dart`, `Elm`, `Flow`, `Go`, `Haskell`, `JSON Schema`, `Java`, `JavaScript`, `JavaScript PropTypes`, `Kotlin`, `Objective-C`, `PHP`, `Pike`, `Python`, `Ruby`, `Rust`, `Scala3`, `Smithy`, `Swift`, `TypeScript`, `TypeScript Effect Schema` and `TypeScript Zod` + +- Interactively generate types and (de-)serialization code from JSON, JSON Schema, and TypeScript +- Paste JSON/JSON Schema/TypeScript as code + +![](https://raw.githubusercontent.com/quicktype/quicktype-vscode/master/media/demo-interactive.gif) + +`quicktype` infers types from sample JSON data, then outputs strongly typed models and serializers for working with that data in your desired programming language. For more explanation, read [A first look at quicktype](http://blog.quicktype.io/first-look/). + +In any JSON file, use the command "Open quicktype for JSON" to summon quicktype, which will generate types from the JSON. Invoke "Change quicktype's target language" to pick a different language. There are similar "Open quicktype" commands for JSON Schema and TypeScript. + +Another way to use quicktype is to copy JSON into the clipboard and invoke "Paste JSON as code/types": + +![](https://raw.githubusercontent.com/quicktype/quicktype-vscode/master/media/demo.gif) + +For a more powerful experience, including custom options and the ability to generate code from multiple JSON samples, try [quicktype.io](https://app.quicktype.io). + +## Installing + +This extension is available for free in the [Visual Studio Code Marketplace](https://marketplace.visualstudio.com/items/quicktype.quicktype) + +## Customization + +- `quicktype.justTypes`: Generate only types, or also produce (de)serialization code when using "Open quicktype". When using "Paste", you can pick between the commands for "types" and "code", without having to set this option. + +- `quicktype.inferMaps`, `quicktype.inferEnums`, `quicktype.inferDateTimes`, `quicktype.inferUuids`, `quicktype.inferBoolStrings`, `quicktype.inferIntegerStrings`: Tell quicktype whether it should try to infer those types from the input JSON. This is not a precise science, so sometimes the guess will be wrong, which is why you can turn them off through these options. Also, quicktype doesn't support dates, UUIDs and stringified integers/booleans in all target languages yet. + +## Contribute! + +quicktype is an open source project, and we're always happy about contributors. If you can think of a way to improve [this extension](https://github.com/quicktype/quicktype-vscode), or [quicktype](https://github.com/quicktype/quicktype), please consider contributing, especially if you know TypeScript. Code is only one way to contribute, though: we're particularly short on documentation. We'd also love to hear your feedback - come [talk to us on Slack](http://slack.quicktype.io)! + +If you find a bug, please [report it on GitHub](https://github.com/quicktype/quicktype-vscode/issues). diff --git a/packages/quicktype-vscode/media/demo-interactive.gif b/packages/quicktype-vscode/media/demo-interactive.gif new file mode 100644 index 000000000..d748f7895 Binary files /dev/null and b/packages/quicktype-vscode/media/demo-interactive.gif differ diff --git a/packages/quicktype-vscode/media/demo.gif b/packages/quicktype-vscode/media/demo.gif new file mode 100644 index 000000000..d5f8acd2f Binary files /dev/null and b/packages/quicktype-vscode/media/demo.gif differ diff --git a/packages/quicktype-vscode/media/icon.png b/packages/quicktype-vscode/media/icon.png new file mode 100644 index 000000000..942c8f4ec Binary files /dev/null and b/packages/quicktype-vscode/media/icon.png differ diff --git a/packages/quicktype-vscode/package.json b/packages/quicktype-vscode/package.json new file mode 100644 index 000000000..702830d32 --- /dev/null +++ b/packages/quicktype-vscode/package.json @@ -0,0 +1,158 @@ +{ + "name": "quicktype", + "displayName": "Paste JSON as Code", + "description": "Copy JSON, paste as Go, TypeScript, C#, C++ and more.", + "version": "23.0.122", + "publisher": "quicktype", + "icon": "media/icon.png", + "galleryBanner": { + "color": "#00212b", + "theme": "dark" + }, + "homepage": "https://quicktype.io", + "author": { + "name": "quicktype.io", + "email": "hello@quicktype.io" + }, + "bugs": { + "url": "https://github.com/quicktype/issues" + }, + "repository": { + "type": "git", + "url": "https://github.com/glideapps/quicktype" + }, + "engines": { + "vscode": "^1.87.0" + }, + "categories": ["Other"], + "keywords": ["json", "converter"], + "markdown": "github", + "main": "dist/extension.js", + "vsce": { + "dependencies": false + }, + "contributes": { + "configuration": { + "type": "object", + "title": "quicktype", + "properties": { + "quicktype.justTypes": { + "type": "boolean", + "default": true, + "description": "Produce only types; no (de-)serialization code" + }, + "quicktype.inferMaps": { + "type": "boolean", + "default": true, + "description": "Infer maps when object keys look like map keys." + }, + "quicktype.inferEnums": { + "type": "boolean", + "default": true, + "description": "Infer enums when there aren't many different string values." + }, + "quicktype.inferDateTimes": { + "type": "boolean", + "default": true, + "description": "Use date-time types for strings that look like date-times." + }, + "quicktype.inferUuids": { + "type": "boolean", + "default": true, + "description": "Use UUID types for strings that look like UUIDs." + }, + "quicktype.inferIntegerStrings": { + "type": "boolean", + "default": true, + "description": "Convert stringified integers into integers, and back." + }, + "quicktype.inferBooleanStrings": { + "type": "boolean", + "default": true, + "description": "Convert stringified booleans into booleans, and back." + } + } + }, + "commands": [ + { + "command": "quicktype.pasteJSONAsTypes", + "title": "Paste JSON as Types" + }, + { + "command": "quicktype.pasteJSONAsTypesAndSerialization", + "title": "Paste JSON as Code" + }, + { + "command": "quicktype.pasteJSONSchemaAsTypes", + "title": "Paste JSON Schema as Types" + }, + { + "command": "quicktype.pasteJSONSchemaAsTypesAndSerialization", + "title": "Paste JSON Schema as Code" + }, + { + "command": "quicktype.pasteTypeScriptAsTypesAndSerialization", + "title": "Paste TypeScript as Code" + }, + { + "command": "quicktype.openForJSON", + "title": "Open quicktype for JSON" + }, + { + "command": "quicktype.openForJSONSchema", + "title": "Open quicktype for JSON Schema" + }, + { + "command": "quicktype.openForTypeScript", + "title": "Open quicktype for TypeScript" + }, + { + "command": "quicktype.changeTargetLanguage", + "title": "Set quicktype target language" + } + ], + "keybindings": [ + { + "command": "quicktype.pasteJSONAsTypesAndSerialization", + "key": "ctrl+shift+V", + "mac": "cmd+shift+V", + "when": "editorTextFocus && editorLangId != 'markdown'" + }, + { + "command": "quicktype.pasteJSONAsTypes", + "key": "ctrl+shift+alt+V", + "mac": "cmd+shift+alt+V", + "when": "editorTextFocus" + } + ] + }, + "scripts": { + "pub": "vsce publish -p $VSCE_TOKEN", + "package": "vsce package", + "build": "tsc -p ./", + "watch": "tsc -watch -p ./", + "test": "npm run build && node ./node_modules/vscode/bin/test", + "vscode:prepublish": "npm run esbuild-base -- --minify", + "esbuild-base": "esbuild ./src/extension.ts --bundle --outfile=dist/extension.js --external:vscode --format=cjs --platform=node", + "esbuild": "npm run esbuild-base -- --sourcemap", + "esbuild-watch": "npm run esbuild-base -- --sourcemap --watch" + }, + "devDependencies": { + "@types/mocha": "^10.0.6", + "@types/node": "~22.14.0", + "@types/node-persist": "^3.1.8", + "@types/readable-stream": "^4.0.10", + "@types/vscode": "^1.87.0", + "@typescript-eslint/eslint-plugin": "^7.0.2", + "@typescript-eslint/parser": "^7.7.0", + "@vscode/test-cli": "^0.0.6", + "@vscode/test-electron": "^2.3.9", + "@vscode/vsce": "^2.25.0", + "eslint": "^8.56.0", + "typescript": "~5.8.3", + "node-persist": "^4.0.1", + "quicktype-core": "file:../quicktype-core", + "quicktype-typescript-input": "file:../quicktype-typescript-input", + "unicode-properties": "github:quicktype/unicode-properties#dist" + } +} diff --git a/packages/quicktype-vscode/quicktype-23.0.122.vsix b/packages/quicktype-vscode/quicktype-23.0.122.vsix new file mode 100644 index 000000000..fe9193ec1 Binary files /dev/null and b/packages/quicktype-vscode/quicktype-23.0.122.vsix differ diff --git a/packages/quicktype-vscode/src/extension.ts b/packages/quicktype-vscode/src/extension.ts new file mode 100644 index 000000000..cba2a3015 --- /dev/null +++ b/packages/quicktype-vscode/src/extension.ts @@ -0,0 +1,555 @@ + + +import * as path from "path"; + +import { + InputData, + JSONSchemaInput, + type Options, + type RendererOptions, + type SerializedRenderResult, + type TargetLanguage, + defaultTargetLanguages, + inferenceFlagNames, + isLanguageName, + jsonInputForTargetLanguage, + languageNamed, + quicktype, +} from "quicktype-core"; +import { schemaForTypeScriptSources } from "quicktype-typescript-input"; +// eslint-disable-next-line import/no-unresolved +import * as vscode from "vscode"; + +const configurationSection = "quicktype"; + +enum Command { + PasteJSONAsTypes = "quicktype.pasteJSONAsTypes", + PasteJSONAsTypesAndSerialization = "quicktype.pasteJSONAsTypesAndSerialization", + PasteSchemaAsTypes = "quicktype.pasteJSONSchemaAsTypes", + PasteSchemaAsTypesAndSerialization = "quicktype.pasteJSONSchemaAsTypesAndSerialization", + PasteTypeScriptAsTypesAndSerialization = "quicktype.pasteTypeScriptAsTypesAndSerialization", + OpenQuicktypeForJSON = "quicktype.openForJSON", + OpenQuicktypeForJSONSchema = "quicktype.openForJSONSchema", + OpenQuicktypeForTypeScript = "quicktype.openForTypeScript", + ChangeTargetLanguage = "quicktype.changeTargetLanguage", +} + +function jsonIsValid(json: string): boolean { + try { + JSON.parse(json); + } catch (e) { + return false; + } + + return true; +} + +async function promptTopLevelName(): Promise<{ + cancelled: boolean; + name: string; +}> { + const topLevelName = await vscode.window.showInputBox({ + prompt: "Top-level type name?", + }); + + return { + cancelled: topLevelName === undefined, + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + name: topLevelName || "TopLevel", + }; +} + +interface TargetLanguagePick { + cancelled: boolean; + lang: TargetLanguage; +} + +async function pickTargetLanguage(): Promise { + const languageChoices = defaultTargetLanguages + .map((l) => l.displayName) + .sort(); + const chosenName = await vscode.window.showQuickPick(languageChoices); + const cancelled = chosenName === undefined; + if (chosenName === undefined || !isLanguageName(chosenName)) { + return { cancelled, lang: languageNamed("typescript") }; + } + + return { cancelled, lang: languageNamed(chosenName) }; +} + +async function getTargetLanguage( + editor: vscode.TextEditor, +): Promise { + const documentLanguage = editor.document.languageId; + const languageName = isLanguageName(documentLanguage) + ? documentLanguage + : "typescript"; + const currentLanguage = languageNamed(languageName); + if (currentLanguage !== undefined) { + return { + cancelled: false, + lang: currentLanguage, + }; + } + + return await pickTargetLanguage(); +} + +type InputKind = "json" | "schema" | "typescript"; + +async function runQuicktype( + content: string, + kind: InputKind, + lang: TargetLanguage, + topLevelName: string, + forceJustTypes: boolean, + indentation: string | undefined, +): Promise { + const configuration = + vscode.workspace.getConfiguration(configurationSection); + const justTypes = forceJustTypes || configuration.justTypes; + + const rendererOptions: RendererOptions = {}; + if (justTypes) { + // FIXME: The target language should have a property to return these options. + if (lang.name === "csharp") { + (rendererOptions as RendererOptions<"csharp">).features = + "just-types"; + } else if (lang.name === "kotlin") { + (rendererOptions as RendererOptions<"kotlin">).framework = + "just-types"; + } else if ("just-types" in rendererOptions) { + rendererOptions["just-types"] = "true"; + } + } + + const inputData = new InputData(); + switch (kind) { + case "json": + await inputData.addSource( + "json", + { name: topLevelName, samples: [content] }, + () => jsonInputForTargetLanguage(lang), + ); + break; + case "schema": + await inputData.addSource( + "schema", + { name: topLevelName, schema: content }, + () => new JSONSchemaInput(undefined), + ); + break; + case "typescript": + await inputData.addSource( + "schema", + schemaForTypeScriptSources([`${topLevelName}.ts`]), + () => new JSONSchemaInput(undefined), + ); + break; + default: + throw new Error(`Unrecognized input format: ${kind}`); + } + + const options: Partial = { + lang: lang, + inputData, + rendererOptions, + indentation, + inferMaps: configuration.inferMaps, + inferEnums: configuration.inferEnums, + inferDateTimes: configuration.inferDateTimes, + inferIntegerStrings: configuration.inferIntegerStrings, + }; + for (const flag of inferenceFlagNames) { + if (typeof configuration[flag] === "boolean") { + options[flag] = configuration[flag]; + } + } + + return await quicktype(options); +} + +async function pasteAsTypes( + editor: vscode.TextEditor, + kind: InputKind, + justTypes: boolean, +): Promise { + let indentation: string; + if (editor.options.insertSpaces) { + const tabSize = editor.options.tabSize as number; + indentation = " ".repeat(tabSize); + } else { + indentation = "\t"; + } + + const language = await getTargetLanguage(editor); + if (language.cancelled) { + return; + } + + let content: string; + try { + content = await vscode.env.clipboard.readText(); + } catch (e) { + return await vscode.window.showErrorMessage( + "Could not get clipboard contents", + ); + } + + if (kind !== "typescript" && !jsonIsValid(content)) { + return await vscode.window.showErrorMessage( + "Clipboard does not contain valid JSON.", + ); + } + + let topLevelName: string; + if (kind === "typescript") { + topLevelName = "input"; + } else { + const tln = await promptTopLevelName(); + if (tln.cancelled) { + return; + } + + topLevelName = tln.name; + } + + let result: SerializedRenderResult; + try { + result = await runQuicktype( + content, + kind, + language.lang, + topLevelName, + justTypes, + indentation, + ); + } catch (e) { + // TODO Invalid JSON produces an uncatchable exception from quicktype + // Fix this so we can catch and show an error message. + if (typeof e === "string") { + return await vscode.window.showErrorMessage(e); + } + } + + // @ts-expect-error + const text = result.lines.join("\n"); + const selection = editor.selection; + return await editor.edit((builder) => { + if (selection.isEmpty) { + builder.insert(selection.start, text); + } else { + builder.replace( + new vscode.Range(selection.start, selection.end), + text, + ); + } + }); +} + +class CodeProvider implements vscode.TextDocumentContentProvider { + public readonly scheme: string = "quicktype"; + + public readonly uri: vscode.Uri; + + private _documentText = "{}"; + + private _targetCode = ""; + + private readonly _onDidChange = new vscode.EventEmitter(); + + private readonly _changeSubscription: vscode.Disposable; + + private readonly _onDidChangeVisibleTextEditors: vscode.Disposable; + + private readonly _onDidChangeConfiguration: vscode.Disposable; + + private _isOpen = false; + + private _timer: NodeJS.Timeout | undefined = undefined; + + public constructor( + private _inputKind: InputKind, + private readonly _targetLanguage: TargetLanguage, + private _document: vscode.TextDocument, + ) { + this.scheme = `quicktype-${this._targetLanguage.name}`; + // TODO use this.documentName instead of QuickType in uri + this.uri = vscode.Uri.parse( + `${this.scheme}:QuickType.${this._targetLanguage.extension}`, + ); + + this._changeSubscription = vscode.workspace.onDidChangeTextDocument( + (ev) => this.textDidChange(ev), + ); + this._onDidChangeVisibleTextEditors = + vscode.window.onDidChangeVisibleTextEditors((editors) => + this.visibleTextEditorsDidChange([...editors]), + ); + this._onDidChangeConfiguration = + vscode.workspace.onDidChangeConfiguration((ev) => + this.configurationDidChange(ev), + ); + } + + public dispose(): void { + this._onDidChange.dispose(); + this._changeSubscription.dispose(); + this._onDidChangeVisibleTextEditors.dispose(); + this._onDidChangeConfiguration.dispose(); + } + + public get inputKind(): InputKind { + return this._inputKind; + } + + public setInputKind(inputKind: InputKind): void { + this._inputKind = inputKind; + } + + public get document(): vscode.TextDocument { + return this._document; + } + + public get documentName(): string { + const basename = path.basename(this.document.fileName); + const extIndex = basename.lastIndexOf("."); + return extIndex === -1 ? basename : basename.substring(0, extIndex); + } + + public setDocument(document: vscode.TextDocument): void { + this._document = document; + } + + public get onDidChange(): vscode.Event { + return this._onDidChange.event; + } + + private visibleTextEditorsDidChange(editors: vscode.TextEditor[]): void { + const isOpen = editors.some( + (e) => e.document.uri.scheme === this.scheme, + ); + if (!this._isOpen && isOpen) { + void this.update(); + } + + this._isOpen = isOpen; + } + + private configurationDidChange(ev: vscode.ConfigurationChangeEvent): void { + if (ev.affectsConfiguration(configurationSection)) { + void this.update(); + } + } + + private textDidChange(ev: vscode.TextDocumentChangeEvent): void { + if (!this._isOpen) return; + + if (ev.document !== this._document) return; + + if (this._timer) { + clearTimeout(this._timer); + } + + this._timer = setTimeout(() => { + this._timer = undefined; + void this.update(); + }, 300); + } + + public async update(): Promise { + this._documentText = this._document.getText(); + + try { + const result = await runQuicktype( + this._documentText, + this._inputKind, + this._targetLanguage, + this.documentName, + false, + undefined, + ); + this._targetCode = result.lines.join("\n"); + + if (!this._isOpen) return; + + this._onDidChange.fire(this.uri); + } catch (e) { + // FIXME + } + } + + public provideTextDocumentContent( + _uri: vscode.Uri, + _token: vscode.CancellationToken, + ): vscode.ProviderResult { + this._isOpen = true; + + return this._targetCode; + } +} + +function deduceTargetLanguage(): TargetLanguage { + const documents = vscode.workspace.textDocuments; + const counts = new Map(); + for (const doc of documents) { + const name = doc.languageId; + let count = counts.get(name); + if (count === undefined) { + count = 0; + } + + count += 1; + counts.set(name, count); + } + + const sorted = Array.from(counts).sort(([_na, ca], [_nb, cb]) => cb - ca); + for (const [name] of sorted) { + if (isLanguageName(name)) { + return languageNamed(name); + } + } + + return languageNamed("typescript"); +} + +const lastTargetLanguageUsedKey = "lastTargetLanguageUsed"; + +let extensionContext: vscode.ExtensionContext | undefined = undefined; + +const codeProviders: Map = new Map(); + +let lastCodeProvider: CodeProvider | undefined = undefined; +let explicitlySetTargetLanguage: TargetLanguage | undefined = undefined; + +async function openQuicktype( + inputKind: InputKind, + targetLanguage: TargetLanguage, + document: vscode.TextDocument, +): Promise { + let codeProvider = codeProviders.get(targetLanguage.name); + if (codeProvider === undefined) { + codeProvider = new CodeProvider(inputKind, targetLanguage, document); + codeProviders.set(targetLanguage.name, codeProvider); + if (extensionContext !== undefined) { + extensionContext.subscriptions.push( + vscode.workspace.registerTextDocumentContentProvider( + codeProvider.scheme, + codeProvider, + ), + ); + } + } else { + codeProvider.setInputKind(inputKind); + codeProvider.setDocument(document); + } + + let originalEditor: vscode.TextEditor | undefined; + if (lastCodeProvider !== undefined) { + const lastDoc = lastCodeProvider.document; + originalEditor = vscode.window.visibleTextEditors.find( + (e) => e.document === lastDoc, + ); + } + + if (originalEditor === undefined) { + originalEditor = vscode.window.activeTextEditor; + } + + let column: number; + if (originalEditor?.viewColumn !== undefined) { + column = originalEditor.viewColumn + 1; + } else { + column = 0; + } + + lastCodeProvider = codeProvider; + + await codeProvider.update(); + const doc = await vscode.workspace.openTextDocument(codeProvider.uri); + return await vscode.window.showTextDocument(doc, column, true); +} + +async function openForEditor( + editor: vscode.TextEditor, + inputKind: InputKind, +): Promise { + const targetLanguage = + explicitlySetTargetLanguage ?? deduceTargetLanguage(); + await openQuicktype(inputKind, targetLanguage, editor.document); +} + +async function changeTargetLanguage(): Promise { + const pick = await pickTargetLanguage(); + if (pick.cancelled) return; + + explicitlySetTargetLanguage = pick.lang; + if (lastCodeProvider === undefined) return; + + await openQuicktype( + lastCodeProvider.inputKind, + explicitlySetTargetLanguage, + lastCodeProvider.document, + ); + + await extensionContext?.workspaceState.update( + lastTargetLanguageUsedKey, + explicitlySetTargetLanguage.name, + ); +} + +export async function activate( + context: vscode.ExtensionContext, +): Promise { + extensionContext = context; + + context.subscriptions.push( + vscode.commands.registerTextEditorCommand( + Command.PasteJSONAsTypes, + async (editor) => await pasteAsTypes(editor, "json", true), + ), + vscode.commands.registerTextEditorCommand( + Command.PasteJSONAsTypesAndSerialization, + async (editor) => await pasteAsTypes(editor, "json", false), + ), + vscode.commands.registerTextEditorCommand( + Command.PasteSchemaAsTypes, + async (editor) => await pasteAsTypes(editor, "schema", true), + ), + vscode.commands.registerTextEditorCommand( + Command.PasteSchemaAsTypesAndSerialization, + async (editor) => await pasteAsTypes(editor, "schema", false), + ), + vscode.commands.registerTextEditorCommand( + Command.PasteTypeScriptAsTypesAndSerialization, + async (editor) => await pasteAsTypes(editor, "typescript", false), + ), + vscode.commands.registerTextEditorCommand( + Command.OpenQuicktypeForJSON, + async (editor) => await openForEditor(editor, "json"), + ), + vscode.commands.registerTextEditorCommand( + Command.OpenQuicktypeForJSONSchema, + async (editor) => await openForEditor(editor, "schema"), + ), + vscode.commands.registerTextEditorCommand( + Command.OpenQuicktypeForTypeScript, + async (editor) => await openForEditor(editor, "typescript"), + ), + vscode.commands.registerCommand( + Command.ChangeTargetLanguage, + changeTargetLanguage, + ), + ); + + const maybeName = extensionContext.workspaceState.get( + lastTargetLanguageUsedKey, + ); + if (typeof maybeName === "string" && isLanguageName(maybeName)) { + explicitlySetTargetLanguage = languageNamed(maybeName); + } +} + +export function deactivate(): void { + return; +} diff --git a/packages/quicktype-vscode/tsconfig.json b/packages/quicktype-vscode/tsconfig.json new file mode 100644 index 000000000..53cccc394 --- /dev/null +++ b/packages/quicktype-vscode/tsconfig.json @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "outDir": "out", + "lib": ["es6", "esnext.asynciterable"], + "sourceMap": true, + "rootDir": ".", + "allowJs": false, + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "esModuleInterop": true + }, + "exclude": ["node_modules", ".vscode-test"] +} diff --git a/script/patch-npm-version.ts b/script/patch-npm-version.ts index 67caf4038..2cc64461d 100755 --- a/script/patch-npm-version.ts +++ b/script/patch-npm-version.ts @@ -21,12 +21,16 @@ const PUBLISHED = (() => { const CURRENT = exec(`npm version`).match(/quicktype: '(.+)'/)![1]; switch (semver.compare(CURRENT, PUBLISHED)) { case -1: - console.error(`* package.json version is ${CURRENT} but ${PUBLISHED} is published. Patching...`); + console.error( + `* package.json version is ${CURRENT} but ${PUBLISHED} is published. Patching...`, + ); exec(`npm version ${PUBLISHED} --force --no-git-tag-version`); shell.exec(`npm version patch --no-git-tag-version`); break; case 0: - console.error(`* package.json version is ${CURRENT} but ${PUBLISHED} is published. Patching...`); + console.error( + `* package.json version is ${CURRENT} but ${PUBLISHED} is published. Patching...`, + ); shell.exec(`npm version patch --no-git-tag-version`); break; default: diff --git a/script/publish.sh b/script/publish.sh index a0ec29f03..e82da152a 100755 --- a/script/publish.sh +++ b/script/publish.sh @@ -1,29 +1,44 @@ #!/usr/bin/env bash +set -e + ./script/patch-npm-version.ts VERSION=$(jq -r '.version' package.json ) npm version $VERSION --workspaces --force -# This is not great, but we need to get the dependencies to workspaces +# Publish core +pushd packages/quicktype-core +npm publish +popd + +# Publish typescript input +pushd packages/quicktype-typescript-input jq --arg version $VERSION \ - '.dependencies."quicktype-core" = $version | .dependencies."quicktype-graphql-input" = $version | .dependencies."quicktype-typescript-input" = $version' \ + '.dependencies."quicktype-core" = $version' \ package.json > package.1.json mv package.1.json package.json - npm publish +popd - +# Publish graphql input +pushd packages/quicktype-graphql-input jq --arg version $VERSION \ '.dependencies."quicktype-core" = $version' \ - packages/quicktype-typescript-input/package.json > package.1.json - -mv package.1.json packages/quicktype-typescript-input/package.json + package.json > package.1.json +mv package.1.json package.json +npm publish +popd +# Publish quicktype jq --arg version $VERSION \ - '.dependencies."quicktype-core" = $version' \ - packages/quicktype-graphql-input/package.json > package.1.json - -mv package.1.json packages/quicktype-graphql-input/package.json + '.dependencies."quicktype-core" = $version | .dependencies."quicktype-graphql-input" = $version | .dependencies."quicktype-typescript-input" = $version' \ + package.json > package.1.json +mv package.1.json package.json +npm publish + -npm publish --workspaces --if-present \ No newline at end of file +# Publish vscode extension +pushd packages/quicktype-vscode +npm run pub +popd diff --git a/script/quicktype b/script/quicktype index d970c5204..458c12a01 100755 --- a/script/quicktype +++ b/script/quicktype @@ -3,7 +3,7 @@ # This runs quicktype, ensuring dependencies are installed # and rebuilding quicktype first. # -# Use script/quickertype to skip reinstalling dependencies +# Use script/quickesttype to skip reinstalling dependencies # and rebuilding PureScript for 10s faster runs if you # are just working on TargetLanguage code in TypeScript. diff --git a/src/CompressedJSONFromStream.ts b/src/CompressedJSONFromStream.ts index 84c6ffe6f..892e35920 100644 --- a/src/CompressedJSONFromStream.ts +++ b/src/CompressedJSONFromStream.ts @@ -1,7 +1,8 @@ -import { Readable } from "readable-stream"; -import { CompressedJSON, Value } from "quicktype-core"; +import type { Readable } from "readable-stream"; import { Parser } from "stream-json"; +import { CompressedJSON, type Value } from "quicktype-core"; + const methodMap: { [name: string]: string } = { startObject: "pushObjectContext", endObject: "finishObject", @@ -14,29 +15,33 @@ const methodMap: { [name: string]: string } = { stringValue: "commitString", nullValue: "commitNull", trueValue: "handleTrueValue", - falseValue: "handleFalseValue" + falseValue: "handleFalseValue", }; export class CompressedJSONFromStream extends CompressedJSON { - async parse(readStream: Readable): Promise { + public async parse(readStream: Readable): Promise { const combo = new Parser({ packKeys: true, packStrings: true }); - combo.on("data", (item: { name: string; value: string | undefined }) => { - if (typeof methodMap[item.name] === "string") { - (this as any)[methodMap[item.name]](item.value); - } - }); + combo.on( + "data", + (item: { name: string; value: string | undefined }) => { + if (typeof methodMap[item.name] === "string") { + // @ts-expect-error FIXME: strongly type this + this[methodMap[item.name]](item.value); + } + }, + ); const promise = new Promise((resolve, reject) => { combo.on("end", () => { resolve(this.finish()); }); - combo.on("error", (err: any) => { + combo.on("error", (err: unknown) => { reject(err); }); }); readStream.setEncoding("utf8"); readStream.pipe(combo); readStream.resume(); - return promise; + return await promise; } protected handleStartNumber = (): void => { @@ -46,7 +51,7 @@ export class CompressedJSONFromStream extends CompressedJSON { protected handleNumberChunk = (s: string): void => { const ctx = this.context; - if (!ctx.currentNumberIsDouble && /[\.e]/i.test(s)) { + if (!ctx.currentNumberIsDouble && /[.e]/i.test(s)) { ctx.currentNumberIsDouble = true; } }; diff --git a/src/GraphQLIntrospection.ts b/src/GraphQLIntrospection.ts index 71106b1df..db2093a0a 100644 --- a/src/GraphQLIntrospection.ts +++ b/src/GraphQLIntrospection.ts @@ -1,28 +1,34 @@ -import { panic } from "quicktype-core"; -import { introspectionQuery } from "graphql"; import { exceptionToString } from "@glideapps/ts-necessities"; - import fetch from "cross-fetch"; +import { introspectionQuery } from "graphql"; + +import { panic } from "quicktype-core"; // https://github.com/apollographql/apollo-codegen/blob/master/src/downloadSchema.ts const defaultHeaders: { [name: string]: string } = { Accept: "application/json", - "Content-Type": "application/json" + "Content-Type": "application/json", }; const headerRegExp = /^([^:]+):\s*(.*)$/; -export async function introspectServer(url: string, method: string, headerStrings: string[]): Promise { +export async function introspectServer( + url: string, + method: string, + headerStrings: string[], +): Promise { const headers: { [name: string]: string } = {}; for (const name of Object.getOwnPropertyNames(defaultHeaders)) { headers[name] = defaultHeaders[name]; } + for (const str of headerStrings) { - const matches = str.match(headerRegExp); + const matches = headerRegExp.exec(str); if (matches === null) { return panic(`Not a valid HTTP header: "${str}"`); } + headers[matches[1]] = matches[2]; } @@ -31,21 +37,27 @@ export async function introspectServer(url: string, method: string, headerString const response = await fetch(url, { method, headers: headers, - body: JSON.stringify({ query: introspectionQuery }) + body: JSON.stringify({ query: introspectionQuery }), }); result = await response.json(); } catch (error) { - return panic(`Error while fetching introspection query result: ${exceptionToString(error)}`); + return panic( + `Error while fetching introspection query result: ${exceptionToString(error)}`, + ); } if (result.errors) { - return panic(`Errors in introspection query result: ${JSON.stringify(result.errors)}`); + return panic( + `Errors in introspection query result: ${JSON.stringify(result.errors)}`, + ); } const schemaData = result; if (!schemaData.data) { - return panic(`No introspection query result data found, server responded with: ${JSON.stringify(result)}`); + return panic( + `No introspection query result data found, server responded with: ${JSON.stringify(result)}`, + ); } return JSON.stringify(schemaData, null, 2); diff --git a/src/TypeSource.ts b/src/TypeSource.ts index cc693c4c9..ee6b2203c 100644 --- a/src/TypeSource.ts +++ b/src/TypeSource.ts @@ -1,7 +1,7 @@ -import { Readable } from "readable-stream"; +import type { Readable } from "readable-stream"; -import { JSONSourceData, JSONSchemaSourceData } from "quicktype-core"; -import { GraphQLSourceData } from "quicktype-graphql-input"; +import type { JSONSchemaSourceData, JSONSourceData } from "quicktype-core"; +import type { GraphQLSourceData } from "quicktype-graphql-input"; export interface JSONTypeSource extends JSONSourceData { kind: "json"; diff --git a/src/URLGrammar.ts b/src/URLGrammar.ts index 5280846f0..b89778992 100644 --- a/src/URLGrammar.ts +++ b/src/URLGrammar.ts @@ -1,9 +1,10 @@ -import { panic, checkStringMap, checkArray } from "quicktype-core"; +import { checkArray, checkStringMap, panic } from "quicktype-core"; -function expand(json: any): string[] { +function expand(json: unknown): string[] { if (typeof json === "string") { return [json]; } + if (Array.isArray(json)) { let result: string[] = [""]; for (const j of json) { @@ -14,11 +15,14 @@ function expand(json: any): string[] { appended.push(a + b); } } + result = appended; } + return result; } - if (Object.prototype.hasOwnProperty.call(json, "oneOf")) { + + if (typeof json === "object" && json && "oneOf" in json) { const options = checkArray(json.oneOf); const result: string[] = []; for (const j of options) { @@ -26,12 +30,16 @@ function expand(json: any): string[] { result.push(x); } } + return result; } + return panic(`Value is not a valid URL grammar: ${json}`); } -export function urlsFromURLGrammar(json: any): { [name: string]: string[] } { +export function urlsFromURLGrammar(json: unknown): { + [name: string]: string[]; +} { const topLevelMap = checkStringMap(json); const results: { [name: string]: string[] } = {}; diff --git a/src/index.ts b/src/index.ts index 943abdfb9..856542c96 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,89 +1,106 @@ #!/usr/bin/env node -import * as fs from "fs"; -import * as path from "path"; -import * as _ from "lodash"; -import { Readable } from "readable-stream"; -import { hasOwnProperty, definedMap, withDefault, mapFromObject, mapMap } from "collection-utils"; +import * as fs from "node:fs"; +import * as path from "node:path"; + import { exceptionToString } from "@glideapps/ts-necessities"; +import chalk from "chalk"; +import { + definedMap, + // biome-ignore lint/suspicious/noShadowRestrictedNames: + hasOwnProperty, + mapFromObject, + mapMap, + withDefault, +} from "collection-utils"; +import commandLineArgs from "command-line-args"; +import getUsage from "command-line-usage"; +import * as _ from "lodash"; +import type { Readable } from "readable-stream"; +import stringToStream from "string-to-stream"; +import _wordwrap from "wordwrap"; import { - Options, - RendererOptions, - getTargetLanguage, - quicktypeMultiFile, - SerializedRenderResult, - TargetLanguage, - languageNamed, + FetchingJSONSchemaStore, InputData, - JSONSchemaInput, - OptionDefinition, - defaultTargetLanguages, IssueAnnotationData, - panic, + JSONInput, + JSONSchemaInput, + type JSONSourceData, + type LanguageName, + type OptionDefinition, + type Options, + type RendererOptions, + type SerializedRenderResult, + type TargetLanguage, assert, - defined, assertNever, - parseJSON, - trainMarkovChain, - messageError, - messageAssert, - sourcesFromPostmanCollection, - inferenceFlags, - inferenceFlagNames, - splitIntoWords, capitalize, - JSONSourceData, - JSONInput, + defaultTargetLanguages, + defined, getStream, - readableFromFileOrURL, + getTargetLanguage, + inferenceFlagNames, + inferenceFlags, + isLanguageName, + languageNamed, + messageAssert, + messageError, + panic, + parseJSON, + quicktypeMultiFile, readFromFileOrURL, - FetchingJSONSchemaStore + readableFromFileOrURL, + sourcesFromPostmanCollection, + splitIntoWords, + trainMarkovChain, } from "quicktype-core"; -import { schemaForTypeScriptSources } from "quicktype-typescript-input"; import { GraphQLInput } from "quicktype-graphql-input"; +import { schemaForTypeScriptSources } from "quicktype-typescript-input"; -import { urlsFromURLGrammar } from "./URLGrammar"; -import { introspectServer } from "./GraphQLIntrospection"; -import { JSONTypeSource, TypeSource, GraphQLTypeSource, SchemaTypeSource } from "./TypeSource"; import { CompressedJSONFromStream } from "./CompressedJSONFromStream"; +import { introspectServer } from "./GraphQLIntrospection"; +import type { + GraphQLTypeSource, + JSONTypeSource, + SchemaTypeSource, + TypeSource, +} from "./TypeSource"; +import { urlsFromURLGrammar } from "./URLGrammar"; -const stringToStream = require("string-to-stream"); - -import commandLineArgs from "command-line-args"; -import getUsage from "command-line-usage"; -import chalk from "chalk"; -const wordWrap: (s: string) => string = require("wordwrap")(90); - +// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires const packageJSON = require("../package.json"); -export interface CLIOptions { - lang: string; - topLevel: string; - src: string[]; - srcUrls?: string; - srcLang: string; +const wordWrap: (s: string) => string = _wordwrap(90); + +export interface CLIOptions { + // We use this to access the inference flags + // biome-ignore lint/suspicious/noExplicitAny: + [option: string]: any; additionalSchema: string[]; - graphqlSchema?: string; + allPropertiesOptional: boolean; + alphabetizeProperties: boolean; + buildMarkovChain?: string; + debug?: string; graphqlIntrospect?: string; + graphqlSchema?: string; + help: boolean; httpHeader?: string[]; httpMethod?: string; - out?: string; - buildMarkovChain?: string; + lang: Lang; - alphabetizeProperties: boolean; - allPropertiesOptional: boolean; noRender: boolean; + out?: string; + quiet: boolean; - rendererOptions: RendererOptions; + rendererOptions: RendererOptions; - help: boolean; - quiet: boolean; - version: boolean; - debug?: string; + src: string[]; + srcLang: string; + srcUrls?: string; telemetry?: string; + topLevel: string; - // We use this to access the inference flags - [option: string]: any; + version: boolean; } const defaultDefaultTargetLanguageName = "go"; @@ -91,9 +108,13 @@ const defaultDefaultTargetLanguageName = "go"; async function sourceFromFileOrUrlArray( name: string, filesOrUrls: string[], - httpHeaders?: string[] + httpHeaders?: string[], ): Promise { - const samples = await Promise.all(filesOrUrls.map(file => readableFromFileOrURL(file, httpHeaders))); + const samples = await Promise.all( + filesOrUrls.map( + async (file) => await readableFromFileOrURL(file, httpHeaders), + ), + ); return { kind: "json", name, samples }; } @@ -102,12 +123,17 @@ function typeNameFromFilename(filename: string): string { return name.substring(0, name.lastIndexOf(".")); } -async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Promise { - async function readFilesOrURLsInDirectory(d: string): Promise { +async function samplesFromDirectory( + dataDir: string, + httpHeaders?: string[], +): Promise { + async function readFilesOrURLsInDirectory( + d: string, + ): Promise { const files = fs .readdirSync(d) - .map(x => path.join(d, x)) - .filter(x => fs.lstatSync(x).isFile()); + .map((x) => path.join(d, x)) + .filter((x) => fs.lstatSync(x).isFile()); // Each file is a (Name, JSON | URL) const sourcesInDir: TypeSource[] = []; const graphQLSources: GraphQLTypeSource[] = []; @@ -128,35 +154,53 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr sourcesInDir.push({ kind: "json", name, - samples: [await readableFromFileOrURL(fileOrUrl, httpHeaders)] + samples: [ + await readableFromFileOrURL(fileOrUrl, httpHeaders), + ], }); } else if (file.endsWith(".schema")) { sourcesInDir.push({ kind: "schema", name, - uris: [fileOrUrl] + uris: [fileOrUrl], }); } else if (file.endsWith(".gqlschema")) { - messageAssert(graphQLSchema === undefined, "DriverMoreThanOneGraphQLSchemaInDir", { - dir: dataDir - }); - graphQLSchema = await readableFromFileOrURL(fileOrUrl, httpHeaders); + messageAssert( + graphQLSchema === undefined, + "DriverMoreThanOneGraphQLSchemaInDir", + { + dir: dataDir, + }, + ); + graphQLSchema = await readableFromFileOrURL( + fileOrUrl, + httpHeaders, + ); graphQLSchemaFileName = fileOrUrl; } else if (file.endsWith(".graphql")) { graphQLSources.push({ kind: "graphql", name, schema: undefined, - query: await getStream(await readableFromFileOrURL(fileOrUrl, httpHeaders)) + query: await getStream( + await readableFromFileOrURL(fileOrUrl, httpHeaders), + ), }); } } if (graphQLSources.length > 0) { if (graphQLSchema === undefined) { - return messageError("DriverNoGraphQLSchemaInDir", { dir: dataDir }); + return messageError("DriverNoGraphQLSchemaInDir", { + dir: dataDir, + }); } - const schema = parseJSON(await getStream(graphQLSchema), "GraphQL schema", graphQLSchemaFileName); + + const schema = parseJSON( + await getStream(graphQLSchema), + "GraphQL schema", + graphQLSchemaFileName, + ); for (const source of graphQLSources) { source.schema = schema; sourcesInDir.push(source); @@ -166,8 +210,8 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr return sourcesInDir; } - const contents = fs.readdirSync(dataDir).map(x => path.join(dataDir, x)); - const directories = contents.filter(x => fs.lstatSync(x).isDirectory()); + const contents = fs.readdirSync(dataDir).map((x) => path.join(dataDir, x)); + const directories = contents.filter((x) => fs.lstatSync(x).isDirectory()); let sources = await readFilesOrURLsInDirectory(dataDir); @@ -192,12 +236,22 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr } } - if (jsonSamples.length > 0 && schemaSources.length + graphQLSources.length > 0) { - return messageError("DriverCannotMixJSONWithOtherSamples", { dir: dir }); + if ( + jsonSamples.length > 0 && + schemaSources.length + graphQLSources.length > 0 + ) { + return messageError("DriverCannotMixJSONWithOtherSamples", { + dir: dir, + }); } - const oneUnlessEmpty = (xs: any[]) => Math.sign(xs.length); - if (oneUnlessEmpty(schemaSources) + oneUnlessEmpty(graphQLSources) > 1) { + // FIXME: rewrite this to be clearer + const oneUnlessEmpty = (xs: TypeSource[]): 0 | 1 => + Math.sign(xs.length) as 0 | 1; + if ( + oneUnlessEmpty(schemaSources) + oneUnlessEmpty(graphQLSources) > + 1 + ) { return messageError("DriverCannotMixNonJSONInputs", { dir: dir }); } @@ -205,9 +259,10 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr sources.push({ kind: "json", name: path.basename(dir), - samples: jsonSamples + samples: jsonSamples, }); } + sources = sources.concat(schemaSources); sources = sources.concat(graphQLSources); } @@ -215,13 +270,17 @@ async function samplesFromDirectory(dataDir: string, httpHeaders?: string[]): Pr return sources; } -function inferLang(options: Partial, defaultLanguage: string): string { +function inferLang( + options: Partial, + defaultLanguage: LanguageName, +): string | LanguageName { // Output file extension determines the language if language is undefined if (options.out !== undefined) { - let extension = path.extname(options.out); + const extension = path.extname(options.out); if (extension === "") { return messageError("DriverNoLanguageOrExtension", {}); } + return extension.slice(1); } @@ -231,28 +290,42 @@ function inferLang(options: Partial, defaultLanguage: string): strin function inferTopLevel(options: Partial): string { // Output file name determines the top-level if undefined if (options.out !== undefined) { - let extension = path.extname(options.out); - let without = path.basename(options.out).replace(extension, ""); + const extension = path.extname(options.out); + const without = path.basename(options.out).replace(extension, ""); return without; } // Source determines the top-level if undefined if (options.src !== undefined && options.src.length === 1) { - let src = options.src[0]; - let extension = path.extname(src); - let without = path.basename(src).replace(extension, ""); + const src = options.src[0]; + const extension = path.extname(src); + const without = path.basename(src).replace(extension, ""); return without; } return "TopLevel"; } -function inferCLIOptions(opts: Partial, targetLanguage: TargetLanguage | undefined): CLIOptions { +function inferCLIOptions( + opts: Partial, + targetLanguage: TargetLanguage | undefined, +): CLIOptions { let srcLang = opts.srcLang; - if (opts.graphqlSchema !== undefined || opts.graphqlIntrospect !== undefined) { - messageAssert(srcLang === undefined || srcLang === "graphql", "DriverSourceLangMustBeGraphQL", {}); + if ( + opts.graphqlSchema !== undefined || + opts.graphqlIntrospect !== undefined + ) { + messageAssert( + srcLang === undefined || srcLang === "graphql", + "DriverSourceLangMustBeGraphQL", + {}, + ); srcLang = "graphql"; - } else if (opts.src !== undefined && opts.src.length > 0 && opts.src.every(file => _.endsWith(file, ".ts"))) { + } else if ( + opts.src !== undefined && + opts.src.length > 0 && + opts.src.every((file) => _.endsWith(file, ".ts")) + ) { srcLang = "typescript"; } else { messageAssert(srcLang !== "graphql", "DriverGraphQLSchemaNeeded", {}); @@ -263,49 +336,57 @@ function inferCLIOptions(opts: Partial, targetLanguage: TargetLangua if (targetLanguage !== undefined) { language = targetLanguage; } else { - const languageName = opts.lang !== undefined ? opts.lang : inferLang(opts, defaultDefaultTargetLanguageName); - const maybeLanguage = languageNamed(languageName); - if (maybeLanguage === undefined) { - return messageError("DriverUnknownOutputLanguage", { lang: languageName }); + const languageName = + opts.lang ?? inferLang(opts, defaultDefaultTargetLanguageName); + + if (isLanguageName(languageName)) { + language = languageNamed(languageName); + } else { + return messageError("DriverUnknownOutputLanguage", { + lang: languageName, + }); } - language = maybeLanguage; } - /* tslint:disable:strict-boolean-expressions */ const options: CLIOptions = { - src: opts.src || [], + src: opts.src ?? [], srcUrls: opts.srcUrls, srcLang: srcLang, - lang: language.displayName, - topLevel: opts.topLevel || inferTopLevel(opts), + lang: language.name as LanguageName, + topLevel: opts.topLevel ?? inferTopLevel(opts), noRender: !!opts.noRender, alphabetizeProperties: !!opts.alphabetizeProperties, allPropertiesOptional: !!opts.allPropertiesOptional, - rendererOptions: opts.rendererOptions || {}, - help: opts.help || false, - quiet: opts.quiet || false, - version: opts.version || false, + rendererOptions: opts.rendererOptions ?? {}, + help: opts.help ?? false, + quiet: opts.quiet ?? false, + version: opts.version ?? false, out: opts.out, buildMarkovChain: opts.buildMarkovChain, - additionalSchema: opts.additionalSchema || [], + additionalSchema: opts.additionalSchema ?? [], graphqlSchema: opts.graphqlSchema, graphqlIntrospect: opts.graphqlIntrospect, httpMethod: opts.httpMethod, httpHeader: opts.httpHeader, debug: opts.debug, - telemetry: opts.telemetry + telemetry: opts.telemetry, }; - /* tslint:enable */ for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); options[cliName] = !!opts[cliName]; } + return options; } -function makeLangTypeLabel(targetLanguages: TargetLanguage[]): string { - assert(targetLanguages.length > 0, "Must have at least one target language"); - return targetLanguages.map(r => _.minBy(r.names, s => s.length)).join("|"); +function makeLangTypeLabel(targetLanguages: readonly TargetLanguage[]): string { + assert( + targetLanguages.length > 0, + "Must have at least one target language", + ); + return targetLanguages + .map((r) => _.minBy(r.names, (s) => s.length)) + .join("|"); } function negatedInferenceFlagName(name: string): string { @@ -313,31 +394,36 @@ function negatedInferenceFlagName(name: string): string { if (name.startsWith(prefix)) { name = name.slice(prefix.length); } + return "no" + capitalize(name); } function dashedFromCamelCase(name: string): string { return splitIntoWords(name) - .map(w => w.word.toLowerCase()) + .map((w) => w.word.toLowerCase()) .join("-"); } -function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinition[] { +function makeOptionDefinitions( + targetLanguages: readonly TargetLanguage[], +): OptionDefinition[] { const beforeLang: OptionDefinition[] = [ { name: "out", alias: "o", - type: String, - typeLabel: `FILE`, - description: "The output file. Determines --lang and --top-level." + optionType: "string", + typeLabel: "FILE", + description: "The output file. Determines --lang and --top-level.", + kind: "cli", }, { name: "top-level", alias: "t", - type: String, + optionType: "string", typeLabel: "NAME", - description: "The name for the top level type." - } + description: "The name for the top level type.", + kind: "cli", + }, ]; const lang: OptionDefinition[] = targetLanguages.length < 2 @@ -346,137 +432,158 @@ function makeOptionDefinitions(targetLanguages: TargetLanguage[]): OptionDefinit { name: "lang", alias: "l", - type: String, + optionType: "string", typeLabel: "LANG", - description: "The target language." - } + description: "The target language.", + kind: "cli", + }, ]; const afterLang: OptionDefinition[] = [ { name: "src-lang", alias: "s", - type: String, + optionType: "string", defaultValue: undefined, typeLabel: "SRC_LANG", - description: "The source language (default is json)." + description: "The source language (default is json).", + kind: "cli", }, { name: "src", - type: String, + optionType: "string", multiple: true, - defaultOption: true, typeLabel: "FILE|URL|DIRECTORY", - description: "The file, url, or data directory to type." + description: "The file, url, or data directory to type.", + kind: "cli", + defaultOption: true, }, { name: "src-urls", - type: String, + optionType: "string", typeLabel: "FILE", - description: "Tracery grammar describing URLs to crawl." - } + description: "Tracery grammar describing URLs to crawl.", + kind: "cli", + }, ]; const inference: OptionDefinition[] = Array.from( mapMap(mapFromObject(inferenceFlags), (flag, name) => { return { name: dashedFromCamelCase(negatedInferenceFlagName(name)), - type: Boolean, - description: flag.negationDescription + "." + optionType: "boolean" as const, + description: flag.negationDescription + ".", + kind: "cli" as const, }; - }).values() + }).values(), ); const afterInference: OptionDefinition[] = [ { name: "graphql-schema", - type: String, + optionType: "string", typeLabel: "FILE", - description: "GraphQL introspection file." + description: "GraphQL introspection file.", + kind: "cli", }, { name: "graphql-introspect", - type: String, + optionType: "string", typeLabel: "URL", - description: "Introspect GraphQL schema from a server." + description: "Introspect GraphQL schema from a server.", + kind: "cli", }, { name: "http-method", - type: String, + optionType: "string", typeLabel: "METHOD", - description: "HTTP method to use for the GraphQL introspection query." + description: + "HTTP method to use for the GraphQL introspection query.", + kind: "cli", }, { name: "http-header", - type: String, + optionType: "string", multiple: true, typeLabel: "HEADER", - description: "Header(s) to attach to all HTTP requests, including the GraphQL introspection query." + description: + "Header(s) to attach to all HTTP requests, including the GraphQL introspection query.", + kind: "cli", }, { name: "additional-schema", alias: "S", - type: String, + optionType: "string", multiple: true, typeLabel: "FILE", - description: "Register the $id's of additional JSON Schema files." + description: "Register the $id's of additional JSON Schema files.", + kind: "cli", }, { name: "no-render", - type: Boolean, - description: "Don't render output." + optionType: "boolean", + description: "Don't render output.", + kind: "cli", }, { name: "alphabetize-properties", - type: Boolean, - description: "Alphabetize order of class properties." + optionType: "boolean", + description: "Alphabetize order of class properties.", + kind: "cli", }, { name: "all-properties-optional", - type: Boolean, - description: "Make all class properties optional." + optionType: "boolean", + description: "Make all class properties optional.", + kind: "cli", }, { name: "build-markov-chain", - type: String, + optionType: "string", typeLabel: "FILE", - description: "Markov chain corpus filename." + description: "Markov chain corpus filename.", + kind: "cli", }, { name: "quiet", - type: Boolean, - description: "Don't show issues in the generated code." + optionType: "boolean", + description: "Don't show issues in the generated code.", + kind: "cli", }, { name: "debug", - type: String, + optionType: "string", typeLabel: "OPTIONS or all", description: - "Comma separated debug options: print-graph, print-reconstitution, print-gather-names, print-transformations, print-schema-resolving, print-times, provenance" + "Comma separated debug options: print-graph, print-reconstitution, print-gather-names, print-transformations, print-schema-resolving, print-times, provenance", + kind: "cli", }, { name: "telemetry", - type: String, + optionType: "string", typeLabel: "enable|disable", - description: "Enable anonymous telemetry to help improve quicktype" + description: "Enable anonymous telemetry to help improve quicktype", + kind: "cli", }, { name: "help", alias: "h", - type: Boolean, - description: "Get some help." + optionType: "boolean", + description: "Get some help.", + kind: "cli", }, { name: "version", alias: "v", - type: Boolean, - description: "Display the version of quicktype" - } + optionType: "boolean", + description: "Display the version of quicktype", + kind: "cli", + }, ]; return beforeLang.concat(lang, afterLang, inference, afterInference); } interface ColumnDefinition { name: string; - width?: number; padding?: { left: string; right: string }; + width?: number; } interface TableOptions { @@ -484,52 +591,56 @@ interface TableOptions { } interface UsageSection { - header?: string; content?: string | string[]; + header?: string; + hide?: string[]; optionList?: OptionDefinition[]; tableOptions?: TableOptions; - hide?: string[]; } const tableOptionsForOptions: TableOptions = { columns: [ { name: "option", - width: 60 + width: 60, }, { name: "description", - width: 60 - } - ] + width: 60, + }, + ], }; -function makeSectionsBeforeRenderers(targetLanguages: TargetLanguage[]): UsageSection[] { - const langDisplayNames = targetLanguages.map(r => r.displayName).join(", "); +function makeSectionsBeforeRenderers( + targetLanguages: readonly TargetLanguage[], +): UsageSection[] { + const langDisplayNames = targetLanguages + .map((r) => r.displayName) + .join(", "); return [ { header: "Synopsis", content: [ `$ quicktype [${chalk.bold("--lang")} LANG] [${chalk.bold("--src-lang")} SRC_LANG] [${chalk.bold( - "--out" + "--out", )} FILE] FILE|URL ...`, "", ` LANG ... ${makeLangTypeLabel(targetLanguages)}`, "", - "SRC_LANG ... json|schema|graphql|postman|typescript" - ] + "SRC_LANG ... json|schema|graphql|postman|typescript", + ], }, { header: "Description", - content: `Given JSON sample data, quicktype outputs code for working with that data in ${langDisplayNames}.` + content: `Given JSON sample data, quicktype outputs code for working with that data in ${langDisplayNames}.`, }, { header: "Options", optionList: makeOptionDefinitions(targetLanguages), hide: ["no-render", "build-markov-chain"], - tableOptions: tableOptionsForOptions - } + tableOptions: tableOptionsForOptions, + }, ]; } @@ -540,82 +651,132 @@ const sectionsAfterRenderers: UsageSection[] = [ chalk.dim("Generate C# to parse a Bitcoin API"), "$ quicktype -o LatestBlock.cs https://blockchain.info/latestblock", "", - chalk.dim("Generate Go code from a directory of samples containing:"), + chalk.dim( + "Generate Go code from a directory of samples containing:", + ), chalk.dim( ` - Foo.json + Bar - bar-sample-1.json - bar-sample-2.json - - Baz.url` + - Baz.url`, ), "$ quicktype -l go samples", "", chalk.dim("Generate JSON Schema, then TypeScript"), "$ quicktype -o schema.json https://blockchain.info/latestblock", - "$ quicktype -o bitcoin.ts --src-lang schema schema.json" - ] + "$ quicktype -o bitcoin.ts --src-lang schema schema.json", + ], }, { - content: `Learn more at ${chalk.bold("quicktype.io")}` - } + content: `Learn more at ${chalk.bold("quicktype.io")}`, + }, ]; -export function parseCLIOptions(argv: string[], targetLanguage?: TargetLanguage): CLIOptions { +export function parseCLIOptions( + argv: string[], + targetLanguage?: TargetLanguage, +): CLIOptions { if (argv.length === 0) { return inferCLIOptions({ help: true }, targetLanguage); } - const targetLanguages = targetLanguage === undefined ? defaultTargetLanguages : [targetLanguage]; + const targetLanguages = + targetLanguage === undefined + ? defaultTargetLanguages + : [targetLanguage]; const optionDefinitions = makeOptionDefinitions(targetLanguages); // We can only fully parse the options once we know which renderer is selected, // because there are renderer-specific options. But we only know which renderer // is selected after we've parsed the options. Hence, we parse the options // twice. This is the first parse to get the renderer: - const incompleteOptions = inferCLIOptions(parseOptions(optionDefinitions, argv, true), targetLanguage); + const incompleteOptions = inferCLIOptions( + parseOptions(optionDefinitions, argv, true), + targetLanguage, + ); if (targetLanguage === undefined) { - targetLanguage = getTargetLanguage(incompleteOptions.lang); + const languageName = isLanguageName(incompleteOptions.lang) + ? incompleteOptions.lang + : "typescript"; + targetLanguage = getTargetLanguage(languageName); } - const rendererOptionDefinitions = targetLanguage.cliOptionDefinitions.actual; + + const rendererOptionDefinitions = + targetLanguage.cliOptionDefinitions.actual; // Use the global options as well as the renderer options from now on: - const allOptionDefinitions = _.concat(optionDefinitions, rendererOptionDefinitions); + const allOptionDefinitions = _.concat( + optionDefinitions, + rendererOptionDefinitions, + ); // This is the parse that counts: - return inferCLIOptions(parseOptions(allOptionDefinitions, argv, false), targetLanguage); + return inferCLIOptions( + parseOptions(allOptionDefinitions, argv, false), + targetLanguage, + ); } // Parse the options in argv and split them into global options and renderer options, // according to each option definition's `renderer` field. If `partial` is false this // will throw if it encounters an unknown option. -function parseOptions(definitions: OptionDefinition[], argv: string[], partial: boolean): Partial { - let opts: { [key: string]: any }; +function parseOptions( + definitions: OptionDefinition[], + argv: string[], + partial: boolean, +): Partial { + let opts: commandLineArgs.CommandLineOptions; try { - opts = commandLineArgs(definitions, { argv, partial }); + opts = commandLineArgs( + definitions.map((def) => ({ + ...def, + type: def.optionType === "boolean" ? Boolean : String, + })), + { argv, partial }, + ); } catch (e) { assert(!partial, "Partial option parsing should not have failed"); - return messageError("DriverCLIOptionParsingFailed", { message: exceptionToString(e) }); + return messageError("DriverCLIOptionParsingFailed", { + message: exceptionToString(e), + }); } + for (const k of Object.keys(opts)) { if (opts[k] === null) { return messageError("DriverCLIOptionParsingFailed", { - message: `Missing value for command line option "${k}"` + message: `Missing value for command line option "${k}"`, }); } } - const options: { rendererOptions: RendererOptions; [key: string]: any } = { rendererOptions: {} }; - for (const o of definitions) { - if (!hasOwnProperty(opts, o.name)) continue; - const v = opts[o.name] as string; - if (o.renderer !== undefined) options.rendererOptions[o.name] = v; - else { - const k = _.lowerFirst(o.name.split("-").map(_.upperFirst).join("")); - options[k] = v; + const options: { + [key: string]: unknown; + rendererOptions: RendererOptions; + } = { rendererOptions: {} }; + for (const optionDefinition of definitions) { + if (!hasOwnProperty(opts, optionDefinition.name)) { + continue; + } + + const optionValue = opts[optionDefinition.name] as string; + if (optionDefinition.kind !== "cli") { + ( + options.rendererOptions as Record< + typeof optionDefinition.name, + unknown + > + )[optionDefinition.name] = optionValue; + } else { + const k = _.lowerFirst( + optionDefinition.name.split("-").map(_.upperFirst).join(""), + ); + options[k] = optionValue; } } + return options; } -function usage(targetLanguages: TargetLanguage[]) { +function usage(targetLanguages: readonly TargetLanguage[]): void { const rendererSections: UsageSection[] = []; for (const language of targetLanguages) { @@ -625,107 +786,161 @@ function usage(targetLanguages: TargetLanguage[]) { rendererSections.push({ header: `Options for ${language.displayName}`, optionList: definitions, - tableOptions: tableOptionsForOptions + tableOptions: tableOptionsForOptions, }); } - const sections = _.concat(makeSectionsBeforeRenderers(targetLanguages), rendererSections, sectionsAfterRenderers); + const sections = _.concat( + makeSectionsBeforeRenderers(targetLanguages), + rendererSections, + sectionsAfterRenderers, + ); console.log(getUsage(sections)); } // Returns an array of [name, sourceURIs] pairs. -async function getSourceURIs(options: CLIOptions): Promise<[string, string[]][]> { +async function getSourceURIs( + options: CLIOptions, +): Promise> { if (options.srcUrls !== undefined) { const json = parseJSON( await readFromFileOrURL(options.srcUrls, options.httpHeader), "URL grammar", - options.srcUrls + options.srcUrls, ); const jsonMap = urlsFromURLGrammar(json); const topLevels = Object.getOwnPropertyNames(jsonMap); - return topLevels.map(name => [name, jsonMap[name]] as [string, string[]]); - } else if (options.src.length === 0) { + return topLevels.map( + (name) => [name, jsonMap[name]] as [string, string[]], + ); + } + if (options.src.length === 0) { return [[options.topLevel, ["-"]]]; - } else { - return []; } + + return []; } -async function typeSourcesForURIs(name: string, uris: string[], options: CLIOptions): Promise { +async function typeSourcesForURIs( + name: string, + uris: string[], + options: CLIOptions, +): Promise { switch (options.srcLang) { case "json": - return [await sourceFromFileOrUrlArray(name, uris, options.httpHeader)]; + return [ + await sourceFromFileOrUrlArray(name, uris, options.httpHeader), + ]; case "schema": - return uris.map(uri => ({ kind: "schema", name, uris: [uri] }) as SchemaTypeSource); + return uris.map( + (uri) => + ({ kind: "schema", name, uris: [uri] }) as SchemaTypeSource, + ); default: - return panic(`typeSourceForURIs must not be called for source language ${options.srcLang}`); + return panic( + `typeSourceForURIs must not be called for source language ${options.srcLang}`, + ); } } async function getSources(options: CLIOptions): Promise { const sourceURIs = await getSourceURIs(options); const sourceArrays = await Promise.all( - sourceURIs.map(async ([name, uris]) => await typeSourcesForURIs(name, uris, options)) + sourceURIs.map( + async ([name, uris]) => + await typeSourcesForURIs(name, uris, options), + ), ); let sources: TypeSource[] = ([] as TypeSource[]).concat(...sourceArrays); const exists = options.src.filter(fs.existsSync); - const directories = exists.filter(x => fs.lstatSync(x).isDirectory()); + const directories = exists.filter((x) => fs.lstatSync(x).isDirectory()); for (const dataDir of directories) { - sources = sources.concat(await samplesFromDirectory(dataDir, options.httpHeader)); + sources = sources.concat( + await samplesFromDirectory(dataDir, options.httpHeader), + ); } // Every src that's not a directory is assumed to be a file or URL - const filesOrUrls = options.src.filter(x => !_.includes(directories, x)); + const filesOrUrls = options.src.filter((x) => !_.includes(directories, x)); if (!_.isEmpty(filesOrUrls)) { - sources.push(...(await typeSourcesForURIs(options.topLevel, filesOrUrls, options))); + sources.push( + ...(await typeSourcesForURIs( + options.topLevel, + filesOrUrls, + options, + )), + ); } return sources; } function makeTypeScriptSource(fileNames: string[]): SchemaTypeSource { - return Object.assign({ kind: "schema" }, schemaForTypeScriptSources(fileNames)) as SchemaTypeSource; + return Object.assign( + { kind: "schema" }, + schemaForTypeScriptSources(fileNames), + ) as SchemaTypeSource; } export function jsonInputForTargetLanguage( targetLanguage: string | TargetLanguage, languages?: TargetLanguage[], - handleJSONRefs = false + handleJSONRefs = false, ): JSONInput { if (typeof targetLanguage === "string") { - targetLanguage = defined(languageNamed(targetLanguage, languages)); + const languageName = isLanguageName(targetLanguage) + ? targetLanguage + : "typescript"; + targetLanguage = defined(languageNamed(languageName, languages)); } - const compressedJSON = new CompressedJSONFromStream(targetLanguage.dateTimeRecognizer, handleJSONRefs); + + const compressedJSON = new CompressedJSONFromStream( + targetLanguage.dateTimeRecognizer, + handleJSONRefs, + ); return new JSONInput(compressedJSON); } async function makeInputData( sources: TypeSource[], targetLanguage: TargetLanguage, - additionalSchemaAddresses: ReadonlyArray, + additionalSchemaAddresses: readonly string[], handleJSONRefs: boolean, - httpHeaders?: string[] + httpHeaders?: string[], ): Promise { const inputData = new InputData(); for (const source of sources) { switch (source.kind) { case "graphql": - await inputData.addSource("graphql", source, () => new GraphQLInput()); + await inputData.addSource( + "graphql", + source, + () => new GraphQLInput(), + ); break; case "json": await inputData.addSource("json", source, () => - jsonInputForTargetLanguage(targetLanguage, undefined, handleJSONRefs) + jsonInputForTargetLanguage( + targetLanguage, + undefined, + handleJSONRefs, + ), ); break; case "schema": await inputData.addSource( "schema", source, - () => new JSONSchemaInput(new FetchingJSONSchemaStore(httpHeaders), [], additionalSchemaAddresses) + () => + new JSONSchemaInput( + new FetchingJSONSchemaStore(httpHeaders), + [], + additionalSchemaAddresses, + ), ); break; default: @@ -736,23 +951,33 @@ async function makeInputData( return inputData; } -function stringSourceDataToStreamSourceData(src: JSONSourceData): JSONSourceData { - return { name: src.name, description: src.description, samples: src.samples.map(stringToStream) }; +function stringSourceDataToStreamSourceData( + src: JSONSourceData, +): JSONSourceData { + return { + name: src.name, + description: src.description, + samples: src.samples.map( + (sample) => stringToStream(sample) as Readable, + ), + }; } export async function makeQuicktypeOptions( options: CLIOptions, - targetLanguages?: TargetLanguage[] + targetLanguages?: TargetLanguage[], ): Promise | undefined> { if (options.help) { - usage(targetLanguages === undefined ? defaultTargetLanguages : targetLanguages); + usage(targetLanguages ?? defaultTargetLanguages); return undefined; } + if (options.version) { console.log(`quicktype version ${packageJSON.version}`); console.log("Visit quicktype.io for more info."); return undefined; } + if (options.buildMarkovChain !== undefined) { const contents = fs.readFileSync(options.buildMarkovChain).toString(); const lines = contents.split("\n"); @@ -772,27 +997,31 @@ export async function makeQuicktypeOptions( schemaString = await introspectServer( options.graphqlIntrospect, withDefault(options.httpMethod, "POST"), - withDefault(options.httpHeader, []) + withDefault(options.httpHeader, []), ); if (options.graphqlSchema !== undefined) { fs.writeFileSync(options.graphqlSchema, schemaString); wroteSchemaToFile = true; } } + const numSources = options.src.length; if (numSources !== 1) { if (wroteSchemaToFile) { // We're done. return undefined; } + if (numSources === 0) { if (schemaString !== undefined) { console.log(schemaString); return undefined; } + return messageError("DriverNoGraphQLQueryGiven", {}); } } + const gqlSources: GraphQLTypeSource[] = []; for (const queryFile of options.src) { let schemaFileName: string | undefined = undefined; @@ -800,11 +1029,22 @@ export async function makeQuicktypeOptions( schemaFileName = defined(options.graphqlSchema); schemaString = fs.readFileSync(schemaFileName, "utf8"); } - const schema = parseJSON(schemaString, "GraphQL schema", schemaFileName); - const query = await getStream(await readableFromFileOrURL(queryFile, options.httpHeader)); - const name = numSources === 1 ? options.topLevel : typeNameFromFilename(queryFile); + + const schema = parseJSON( + schemaString, + "GraphQL schema", + schemaFileName, + ); + const query = await getStream( + await readableFromFileOrURL(queryFile, options.httpHeader), + ); + const name = + numSources === 1 + ? options.topLevel + : typeNameFromFilename(queryFile); gqlSources.push({ kind: "graphql", name, schema, query }); } + sources = gqlSources; break; case "json": @@ -817,29 +1057,38 @@ export async function makeQuicktypeOptions( case "postman": for (const collectionFile of options.src) { const collectionJSON = fs.readFileSync(collectionFile, "utf8"); - const { sources: postmanSources, description } = sourcesFromPostmanCollection( - collectionJSON, - collectionFile - ); + const { sources: postmanSources, description } = + sourcesFromPostmanCollection( + collectionJSON, + collectionFile, + ); for (const src of postmanSources) { sources.push( - Object.assign({ kind: "json" }, stringSourceDataToStreamSourceData(src)) as JSONTypeSource + Object.assign( + { kind: "json" }, + stringSourceDataToStreamSourceData(src), + ) as JSONTypeSource, ); } + if (postmanSources.length > 1) { fixedTopLevels = true; } + if (description !== undefined) { leadingComments = wordWrap(description).split("\n"); } } + break; default: - return messageError("DriverUnknownSourceLanguage", { lang: options.srcLang }); + return messageError("DriverUnknownSourceLanguage", { + lang: options.srcLang, + }); } - const components = definedMap(options.debug, d => d.split(",")); - const debugAll = components !== undefined && components.indexOf("all") >= 0; + const components = definedMap(options.debug, (d) => d.split(",")); + const debugAll = components?.includes("all"); let debugPrintGraph = debugAll; let checkProvenance = debugAll; let debugPrintReconstitution = debugAll; @@ -865,16 +1114,21 @@ export async function makeQuicktypeOptions( } else if (component === "provenance") { checkProvenance = true; } else if (component !== "all") { - return messageError("DriverUnknownDebugOption", { option: component }); + return messageError("DriverUnknownDebugOption", { + option: component, + }); } } } - const lang = languageNamed(options.lang, targetLanguages); - if (lang === undefined) { - return messageError("DriverUnknownOutputLanguage", { lang: options.lang }); + if (!isLanguageName(options.lang)) { + return messageError("DriverUnknownOutputLanguage", { + lang: options.lang, + }); } + const lang = languageNamed(options.lang, targetLanguages); + const quicktypeOptions: Partial = { lang, alphabetizeProperties: options.alphabetizeProperties, @@ -890,7 +1144,7 @@ export async function makeQuicktypeOptions( debugPrintGatherNames, debugPrintTransformations, debugPrintSchemaResolving, - debugPrintTimes + debugPrintTimes, }; for (const flagName of inferenceFlagNames) { const cliName = negatedInferenceFlagName(flagName); @@ -907,7 +1161,7 @@ export async function makeQuicktypeOptions( lang, options.additionalSchema, quicktypeOptions.ignoreJsonRefs !== true, - options.httpHeader + options.httpHeader, ); return quicktypeOptions; @@ -915,32 +1169,41 @@ export async function makeQuicktypeOptions( export function writeOutput( cliOptions: CLIOptions, - resultsByFilename: ReadonlyMap + resultsByFilename: ReadonlyMap, ): void { let onFirst = true; for (const [filename, { lines, annotations }] of resultsByFilename) { const output = lines.join("\n"); if (cliOptions.out !== undefined) { - fs.writeFileSync(path.join(path.dirname(cliOptions.out), filename), output); + fs.writeFileSync( + path.join(path.dirname(cliOptions.out), filename), + output, + ); } else { if (!onFirst) { process.stdout.write("\n"); } + if (resultsByFilename.size > 1) { process.stdout.write(`// ${filename}\n\n`); } + process.stdout.write(output); } + if (cliOptions.quiet) { continue; } + for (const sa of annotations) { const annotation = sa.annotation; if (!(annotation instanceof IssueAnnotationData)) continue; const lineNumber = sa.span.start.line; const humanLineNumber = lineNumber + 1; - console.error(`\nIssue in line ${humanLineNumber}: ${annotation.message}`); + console.error( + `\nIssue in line ${humanLineNumber}: ${annotation.message}`, + ); console.error(`${humanLineNumber}: ${lines[lineNumber]}`); } @@ -948,7 +1211,9 @@ export function writeOutput( } } -export async function main(args: string[] | Partial) { +export async function main( + args: string[] | Partial, +): Promise { let cliOptions: CLIOptions; if (Array.isArray(args)) { cliOptions = parseCLIOptions(args); @@ -963,9 +1228,12 @@ export async function main(args: string[] | Partial) { case "disable": break; default: - console.error(chalk.red("telemetry must be 'enable' or 'disable'")); + console.error( + chalk.red("telemetry must be 'enable' or 'disable'"), + ); return; } + if (Array.isArray(args) && args.length === 2) { // This was merely a CLI run to set telemetry and we should not proceed return; @@ -973,7 +1241,9 @@ export async function main(args: string[] | Partial) { } const quicktypeOptions = await makeQuicktypeOptions(cliOptions); - if (quicktypeOptions === undefined) return; + if (quicktypeOptions === undefined) { + return; + } const resultsByFilename = await quicktypeMultiFile(quicktypeOptions); @@ -981,12 +1251,13 @@ export async function main(args: string[] | Partial) { } if (require.main === module) { - main(process.argv.slice(2)).catch(e => { + main(process.argv.slice(2)).catch((e) => { if (e instanceof Error) { console.error(`Error: ${e.message}.`); } else { console.error(e); } + process.exit(1); }); } diff --git a/test/buildkite.ts b/test/buildkite.ts index 98c8cc12e..e0d2ac89d 100644 --- a/test/buildkite.ts +++ b/test/buildkite.ts @@ -1,48 +1,65 @@ import * as _ from "lodash"; import { exec } from "shelljs"; -import { WorkItem } from "./test"; -import { allFixtures, Fixture } from "./fixtures"; +import type { WorkItem } from "./test"; +import { allFixtures, type Fixture } from "./fixtures"; function getChangedFiles(base: string, commit: string): string[] { - let diff = exec(`git fetch -v origin ${base} && git diff --name-only origin/${base}..${commit}`).stdout; + const diff = exec( + `git fetch -v origin ${base} && git diff --name-only origin/${base}..${commit}`, + ).stdout; return diff.trim().split("\n"); } -export function affectedFixtures(changedFiles: string[] | undefined = undefined): Fixture[] { +export function affectedFixtures( + changedFiles: string[] | undefined = undefined, +): Fixture[] { if (changedFiles === undefined) { const { GITHUB_BASE_REF: base, GITHUB_SHA: commit } = process.env; - return commit === undefined ? allFixtures : affectedFixtures(getChangedFiles(base || "master", commit)); + return commit === undefined + ? allFixtures + : affectedFixtures(getChangedFiles(base || "master", commit)); } // We can ignore changes in Markdown files - changedFiles = _.reject(changedFiles, file => _.endsWith(file, ".md")); + changedFiles = _.reject(changedFiles, (file) => _.endsWith(file, ".md")); // All fixtures are dirty if any changed file is not included as a sourceFile of some fixture. - const fileDependencies = _.flatMap(allFixtures, f => f.language.sourceFiles || []); - const allFixturesDirty = _.some(changedFiles, f => !_.includes(fileDependencies, f)); + const fileDependencies = _.flatMap( + allFixtures, + (f) => f.language.sourceFiles || [], + ); + const allFixturesDirty = _.some( + changedFiles, + (f) => !_.includes(fileDependencies, f), + ); if (allFixturesDirty) return allFixtures; const dirtyFixtures = allFixtures.filter( - fixture => + (fixture) => // Fixtures that don't specify dependencies are always dirty fixture.language.sourceFiles === undefined || // Fixtures that have a changed file are dirty - _.some(changedFiles, f => _.includes(fixture.language.sourceFiles, f)) + _.some(changedFiles, (f) => + _.includes(fixture.language.sourceFiles, f), + ), ); return dirtyFixtures; } export function divideParallelJobs(workItems: WorkItem[]): WorkItem[] { - const { BUILDKITE_PARALLEL_JOB: pjob, BUILDKITE_PARALLEL_JOB_COUNT: pcount } = process.env; + const { + BUILDKITE_PARALLEL_JOB: pjob, + BUILDKITE_PARALLEL_JOB_COUNT: pcount, + } = process.env; if (pjob === undefined || pcount === undefined) return workItems; try { - const segment = Math.ceil(workItems.length / parseFloat(pcount)); - const start = parseInt(pjob, 10) * segment; + const segment = Math.ceil(workItems.length / Number.parseFloat(pcount)); + const start = Number.parseInt(pjob, 10) * segment; return workItems.slice(start, start + segment); } catch { return workItems; diff --git a/test/fixtures.ts b/test/fixtures.ts index 0f3190f08..d4eb8f2fd 100644 --- a/test/fixtures.ts +++ b/test/fixtures.ts @@ -1,7 +1,7 @@ import * as _ from "lodash"; -import * as path from "path"; -import * as fs from "fs"; -import { randomBytes } from "crypto"; +import * as path from "node:path"; +import * as fs from "node:fs"; +import { randomBytes } from "node:crypto"; import * as shell from "shelljs"; const Ajv = require("ajv"); @@ -15,16 +15,19 @@ import { inDir, quicktype, quicktypeForLanguage, - Sample, + type Sample, samplesFromSources, testsInDir, - ComparisonArgs, + type ComparisonArgs, mkdirs, - callAndExpectFailure + callAndExpectFailure, } from "./utils"; import * as languages from "./languages"; -import { RendererOptions } from "quicktype-core"; -import { mustNotHappen, defined } from "../packages/quicktype-core/dist/support/Support"; +import type { LanguageName, Option, RendererOptions } from "quicktype-core"; +import { + mustNotHappen, + defined, +} from "../packages/quicktype-core/dist/support/Support"; import { DefaultDateTimeRecognizer } from "../packages/quicktype-core/dist/DateTime"; import chalk from "chalk"; @@ -39,18 +42,31 @@ const MAX_TEST_RUNTIME_MS = 30 * 60 * 1000; * These are tests where we have stringified integers that might be serialized * back as integers, which happens in heterogenous arrays such as ["123", 456]. */ -const testsWithStringifiedIntegers = ["nst-test-suite.json", "kitchen-sink.json"]; +const testsWithStringifiedIntegers = [ + "nst-test-suite.json", + "kitchen-sink.json", +]; -function allowStringifiedIntegers(language: languages.Language, test: string): boolean { +function allowStringifiedIntegers( + language: languages.Language, + test: string, +): boolean { if (language.features.indexOf("integer-string") < 0) return false; return testsWithStringifiedIntegers.indexOf(path.basename(test)) >= 0; } function pathWithoutExtension(fullPath: string, extension: string): string { - return path.join(path.dirname(fullPath), path.basename(fullPath, extension)); + return path.join( + path.dirname(fullPath), + path.basename(fullPath, extension), + ); } -function additionalTestFiles(base: string, extension: string, features: string[] = []): string[] { +function additionalTestFiles( + base: string, + extension: string, + features: string[] = [], +): string[] { const additionalFiles: string[] = []; function tryAdd(filename: string): boolean { if (!fs.existsSync(filename)) return false; @@ -69,7 +85,10 @@ function additionalTestFiles(base: string, extension: string, features: string[] found = tryAdd(fn) || found; for (const feature of features) { - found = tryAdd(`${base}.${i.toString()}.fail.${feature}.${extension}`) || found; + found = + tryAdd( + `${base}.${i.toString()}.fail.${feature}.${extension}`, + ) || found; } found = tryAdd(`${base}.${i.toString()}.fail.${extension}`) || found; @@ -78,10 +97,17 @@ function additionalTestFiles(base: string, extension: string, features: string[] return additionalFiles; } -function runEnvForLanguage(additionalRendererOptions: RendererOptions): NodeJS.ProcessEnv { +function runEnvForLanguage( + additionalRendererOptions: RendererOptions, +): NodeJS.ProcessEnv { const newEnv = Object.assign({}, process.env); - for (const o of Object.getOwnPropertyNames(additionalRendererOptions)) { - newEnv["QUICKTYPE_" + o.toUpperCase().replace("-", "_")] = additionalRendererOptions[o].toString(); + + for (const option of Object.keys(additionalRendererOptions)) { + newEnv["QUICKTYPE_" + option.toUpperCase().replace("-", "_")] = ( + additionalRendererOptions[ + option as keyof typeof additionalRendererOptions + ] as Option + ).name; } return newEnv; } @@ -90,17 +116,20 @@ function comparisonArgs( language: languages.Language, inputFilename: string, expectedFilename: string, - additionalRendererOptions: RendererOptions + additionalRendererOptions: RendererOptions, ): ComparisonArgs { return { expectedFile: expectedFilename, given: { command: defined(language.runCommand)(inputFilename), - env: runEnvForLanguage(additionalRendererOptions) + env: runEnvForLanguage(additionalRendererOptions), }, strict: false, allowMissingNull: language.allowMissingNull, - allowStringifiedIntegers: allowStringifiedIntegers(language, expectedFilename) + allowStringifiedIntegers: allowStringifiedIntegers( + language, + expectedFilename, + ), }; } @@ -114,11 +143,11 @@ function timeEnd(message: string, suffix: string): void { const start = timeMap.get(message); const fullMessage = message + suffix; if (start === undefined) { - console.log(fullMessage + ": " + chalk.red("UNKNOWN TIMING")); + console.log(`${fullMessage}: ${chalk.red("UNKNOWN TIMING")}`); return; } const diff = Date.now() - start; - console.log(fullMessage + `: ${diff} ms`); + console.log(`${fullMessage}: ${diff} ms`); } export abstract class Fixture { @@ -134,21 +163,37 @@ export abstract class Fixture { return; } - abstract getSamples(sources: string[]): { priority: Sample[]; others: Sample[] }; + abstract getSamples(sources: string[]): { + priority: Sample[]; + others: Sample[]; + }; - abstract runWithSample(sample: Sample, index: number, total: number): Promise; + abstract runWithSample( + sample: Sample, + index: number, + total: number, + ): Promise; getRunDirectory(): string { return `test/runs/${this.name}-${randomBytes(3).toString("hex")}`; } - runMessageStart(sample: Sample, index: number, total: number, cwd: string, shouldSkip: boolean): string { - const rendererOptions = _.map(sample.additionalRendererOptions, (v, k) => `${k}: ${v}`).join(", "); + runMessageStart( + sample: Sample, + index: number, + total: number, + cwd: string, + shouldSkip: boolean, + ): string { + const rendererOptions = _.map( + sample.additionalRendererOptions, + (v, k) => `${k}: ${v}`, + ).join(", "); const messageParts = [ - `*`, + "*", chalk.dim(`[${index + 1}/${total}]`), chalk.magenta(this.name) + chalk.dim(`(${rendererOptions})`), - path.join(cwd, chalk.cyan(path.basename(sample.path))) + path.join(cwd, chalk.cyan(path.basename(sample.path))), ]; if (shouldSkip) { messageParts.push(chalk.red("SKIP")); @@ -160,7 +205,12 @@ export abstract class Fixture { runMessageEnd(message: string, numFiles: number) { const numFilesString = ` (${numFiles} files)`; - const suffix = numFiles <= 0 ? chalk.red(numFilesString) : numFiles > 1 ? chalk.green(numFilesString) : ""; + const suffix = + numFiles <= 0 + ? chalk.red(numFilesString) + : numFiles > 1 + ? chalk.green(numFilesString) + : ""; timeEnd(message, suffix); } } @@ -176,7 +226,7 @@ abstract class LanguageFixture extends Fixture { return; } - console.error(`* Setting up`, chalk.magenta(this.name), `fixture`); + console.error(`* Setting up ${chalk.magenta(this.name)} fixture`); await inDir(this.language.base, async () => { await execAsync(setupCommand); @@ -184,11 +234,14 @@ abstract class LanguageFixture extends Fixture { } abstract shouldSkipTest(sample: Sample): boolean; - abstract runQuicktype(filename: string, additionalRendererOptions: RendererOptions): Promise; + abstract runQuicktype( + filename: string, + additionalRendererOptions: RendererOptions, + ): Promise; abstract test( filename: string, additionalRendererOptions: RendererOptions, - additionalFiles: string[] + additionalFiles: string[], ): Promise; additionalFiles(_sample: Sample): string[] { @@ -199,9 +252,17 @@ abstract class LanguageFixture extends Fixture { const cwd = this.getRunDirectory(); const sampleFile = path.resolve(sample.path); const shouldSkip = this.shouldSkipTest(sample); - const additionalFiles = this.additionalFiles(sample).map(p => path.resolve(p)); + const additionalFiles = this.additionalFiles(sample).map((p) => + path.resolve(p), + ); - const message = this.runMessageStart(sample, index, total, cwd, shouldSkip); + const message = this.runMessageStart( + sample, + index, + total, + cwd, + shouldSkip, + ); if (shouldSkip) { return; @@ -215,7 +276,10 @@ abstract class LanguageFixture extends Fixture { let numFiles = -1; await inDir(cwd, async () => { - await this.runQuicktype(sampleFile, sample.additionalRendererOptions); + await this.runQuicktype( + sampleFile, + sample.additionalRendererOptions, + ); if (ONLY_OUTPUT) { return; @@ -223,8 +287,12 @@ abstract class LanguageFixture extends Fixture { try { numFiles = await timeout( - this.test(sampleFile, sample.additionalRendererOptions, additionalFiles), - MAX_TEST_RUNTIME_MS + this.test( + sampleFile, + sample.additionalRendererOptions, + additionalFiles, + ), + MAX_TEST_RUNTIME_MS, ); } catch (e) { failWith("Fixture threw an exception", { error: e, sample }); @@ -233,12 +301,16 @@ abstract class LanguageFixture extends Fixture { // FIXME: This is an ugly hack to exclude Java, which has multiple // output files. We have to support that eventually. - if (sample.saveOutput && OUTPUT_DIR !== undefined && this.language.output.indexOf("/") < 0) { + if ( + sample.saveOutput && + OUTPUT_DIR !== undefined && + this.language.output.indexOf("/") < 0 + ) { const outputDir = path.join( OUTPUT_DIR, this.language.name, path.dirname(sample.path), - path.basename(sample.path, path.extname(sample.path)) + path.basename(sample.path, path.extname(sample.path)), ); mkdirs(outputDir); shell.cp(path.join(cwd, this.language.output), outputDir); @@ -254,7 +326,10 @@ abstract class LanguageFixture extends Fixture { } class JSONFixture extends LanguageFixture { - constructor(language: languages.Language, public name: string = language.name) { + constructor( + language: languages.Language, + public name: string = language.name, + ) { super(language); } @@ -262,24 +337,48 @@ class JSONFixture extends LanguageFixture { return this.name === name || name === "json"; } - async runQuicktype(sample: string, additionalRendererOptions: RendererOptions): Promise { + async runQuicktype( + sample: string, + additionalRendererOptions: RendererOptions, + ): Promise { // FIXME: add options - await quicktypeForLanguage(this.language, sample, "json", true, additionalRendererOptions); + await quicktypeForLanguage( + this.language, + sample, + "json", + true, + additionalRendererOptions, + ); } async test( filename: string, additionalRendererOptions: RendererOptions, - _additionalFiles: string[] + _additionalFiles: string[], ): Promise { if (this.language.compileCommand) { await execAsync(this.language.compileCommand); } - if (this.language.runCommand === undefined) return 0; + if (this.language.runCommand === undefined) { + return 0; + } - compareJsonFileToJson(comparisonArgs(this.language, filename, filename, additionalRendererOptions)); + compareJsonFileToJson( + comparisonArgs( + this.language, + filename, + filename, + additionalRendererOptions, + ), + ); - if (this.language.diffViaSchema && !_.includes(this.language.skipDiffViaSchema, path.basename(filename))) { + if ( + this.language.diffViaSchema && + !_.includes( + this.language.skipDiffViaSchema, + path.basename(filename), + ) + ) { debug("* Diffing with code generated via JSON Schema"); // Make a schema await quicktype({ @@ -287,14 +386,23 @@ class JSONFixture extends LanguageFixture { lang: "schema", out: "schema.json", topLevel: this.language.topLevel, - rendererOptions: {} + rendererOptions: {}, }); // Quicktype from the schema and compare to expected code shell.mv(this.language.output, `${this.language.output}.expected`); - await quicktypeForLanguage(this.language, "schema.json", "schema", true, additionalRendererOptions); + await quicktypeForLanguage( + this.language, + "schema.json", + "schema", + true, + additionalRendererOptions, + ); // Compare fixture.output to fixture.output.expected - exec(`diff -Naur ${this.language.output}.expected ${this.language.output} > /dev/null 2>&1`, undefined); + exec( + `diff -Naur ${this.language.output}.expected ${this.language.output} > /dev/null 2>&1`, + undefined, + ); } return 1; @@ -305,10 +413,16 @@ class JSONFixture extends LanguageFixture { return true; } if (this.language.includeJSON !== undefined) { - return !_.includes(this.language.includeJSON, path.basename(sample.path)); + return !_.includes( + this.language.includeJSON, + path.basename(sample.path), + ); } if (this.language.skipJSON !== undefined) { - return _.includes(this.language.skipJSON, path.basename(sample.path)); + return _.includes( + this.language.skipJSON, + path.basename(sample.path), + ); } return false; } @@ -317,45 +431,68 @@ class JSONFixture extends LanguageFixture { // FIXME: this should only run once const prioritySamples = _.concat( testsInDir("test/inputs/json/priority", "json"), - testsInDir("test/inputs/json/samples", "json") + testsInDir("test/inputs/json/samples", "json"), ); - const skipMiscJSON = process.env.QUICKTEST !== undefined || this.language.skipMiscJSON; - const miscSamples = skipMiscJSON ? [] : testsInDir("test/inputs/json/misc", "json"); - - let { priority, others } = samplesFromSources(sources, prioritySamples, miscSamples, "json"); + const skipMiscJSON = + process.env.QUICKTEST !== undefined || this.language.skipMiscJSON; + const miscSamples = skipMiscJSON + ? [] + : testsInDir("test/inputs/json/misc", "json"); + + let { priority, others } = samplesFromSources( + sources, + prioritySamples, + miscSamples, + "json", + ); - const combinationInputs = _.map([1, 2, 3, 4], n => - _.find(prioritySamples, p => p.endsWith(`/priority/combinations${n}.json`)) + const combinationInputs = _.map([1, 2, 3, 4], (n) => + _.find(prioritySamples, (p) => + p.endsWith(`/priority/combinations${n}.json`), + ), ); - if (combinationInputs.some(p => p === undefined)) { - return failWith("priority/combinations[1234].json samples not found", prioritySamples); + if (combinationInputs.some((p) => p === undefined)) { + return failWith( + "priority/combinations[1234].json samples not found", + { prioritySamples }, + ); } if (sources.length === 0 && !ONLY_OUTPUT) { - const quickTestSamples = _.chain(this.language.quickTestRendererOptions) - .flatMap(qt => { + const quickTestSamples = _.chain( + this.language.quickTestRendererOptions, + ) + .flatMap((qt) => { if (Array.isArray(qt)) { const [filename, ro] = qt; - const input = _.find(([] as string[]).concat(prioritySamples, miscSamples), p => - p.endsWith(`/${filename}`) + const input = _.find( + ([] as string[]).concat( + prioritySamples, + miscSamples, + ), + (p) => p.endsWith(`/${filename}`), ); + if (input === undefined) { - return failWith(`quick-test sample ${filename} not found`, qt); + return failWith( + `quick-test sample ${filename} not found`, + { qt }, + ); } return [ { path: input, additionalRendererOptions: ro, - saveOutput: false - } + saveOutput: false, + }, ]; - } else { - return _.map(combinationInputs, p => ({ - path: defined(p), - additionalRendererOptions: qt, - saveOutput: false - })); } + + return _.map(combinationInputs, (p) => ({ + path: defined(p), + additionalRendererOptions: qt, + saveOutput: false, + })); }) .value(); priority = quickTestSamples.concat(priority); @@ -374,11 +511,11 @@ class JSONToXToYFixture extends JSONFixture { constructor( private readonly _fixturePrefix: string, - languageXName: string, + languageXName: LanguageName, languageXOutputFilename: string, rendererOptions: RendererOptions, skipJSON: string[], - language: languages.Language + language: languages.Language, ) { super({ name: languageXName, @@ -396,7 +533,7 @@ class JSONToXToYFixture extends JSONFixture { skipSchema: [], rendererOptions, quickTestRendererOptions: [], - sourceFiles: language.sourceFiles + sourceFiles: language.sourceFiles, }); this.runLanguage = language; this.name = `${this._fixturePrefix}-${language.name}`; @@ -409,7 +546,7 @@ class JSONToXToYFixture extends JSONFixture { async test( filename: string, additionalRendererOptions: RendererOptions, - _additionalFiles: string[] + _additionalFiles: string[], ): Promise { // Generate code for Y from X await quicktypeForLanguage( @@ -417,18 +554,28 @@ class JSONToXToYFixture extends JSONFixture { this.language.output, this.language.name, false, - additionalRendererOptions + additionalRendererOptions, ); // Parse the sample with the code generated from its schema, and compare to the sample - compareJsonFileToJson(comparisonArgs(this.runLanguage, filename, filename, additionalRendererOptions)); + compareJsonFileToJson( + comparisonArgs( + this.runLanguage, + filename, + filename, + additionalRendererOptions, + ), + ); return 1; } shouldSkipTest(sample: Sample): boolean { if (super.shouldSkipTest(sample)) return true; - return _.includes(this.runLanguage.skipJSON, path.basename(sample.path)); + return _.includes( + this.runLanguage.skipJSON, + path.basename(sample.path), + ); } } @@ -444,7 +591,7 @@ class JSONSchemaJSONFixture extends JSONToXToYFixture { "blns-object.json", // AJV refuses to even "compile" the schema we generate "31189.json", // same here "437e7.json", // uri/string confusion - "ed095.json" // same here on Travis + "ed095.json", // same here on Travis ]; super("schema-json", "schema", "schema.json", {}, skipJSON, language); } @@ -452,21 +599,28 @@ class JSONSchemaJSONFixture extends JSONToXToYFixture { async test( filename: string, additionalRendererOptions: RendererOptions, - additionalFiles: string[] + additionalFiles: string[], ): Promise { - let input = JSON.parse(fs.readFileSync(filename, "utf8")); - let schema = JSON.parse(fs.readFileSync(this.language.output, "utf8")); + const input = JSON.parse(fs.readFileSync(filename, "utf8")); + const schema = JSON.parse( + fs.readFileSync(this.language.output, "utf8"), + ); - let ajv = new Ajv({ format: "full", unknownFormats: ["integer", "boolean"] }); + const ajv = new Ajv({ + format: "full", + unknownFormats: ["integer", "boolean"], + }); // Make Ajv's date-time compatible with what we recognize. All non-standard // JSON formats that we use for transformed type kinds must be registered here // with a validation function. // FIXME: Unify this with what's in StringTypes.ts. - ajv.addFormat("date-time", (s: string) => dateTimeRecognizer.isDateTime(s)); - let valid = ajv.validate(schema, input); + ajv.addFormat("date-time", (s: string) => + dateTimeRecognizer.isDateTime(s), + ); + const valid = ajv.validate(schema, input); if (!valid) { failWith("Generated schema does not validate input JSON.", { - filename + filename, }); } @@ -474,19 +628,19 @@ class JSONSchemaJSONFixture extends JSONToXToYFixture { // Generate a schema from the schema, making sure the schemas are the same // FIXME: We could move this to the superclass and test it for all JSON->X->Y - let schemaSchema = "schema-from-schema.json"; + const schemaSchema = "schema-from-schema.json"; await quicktype({ src: [this.language.output], srcLang: this.language.name, lang: this.language.name, topLevel: this.language.topLevel, out: schemaSchema, - rendererOptions: {} + rendererOptions: {}, }); compareJsonFileToJson({ expectedFile: this.language.output, given: { file: schemaSchema }, - strict: true + strict: true, }); return 1; @@ -552,12 +706,19 @@ const skipTypeScriptTests = [ "ed095.json", // top-level is a map "f3139.json", "f3edf.json", - "f466a.json" + "f466a.json", ]; class JSONTypeScriptFixture extends JSONToXToYFixture { constructor(language: languages.Language) { - super("json-ts", "ts", "typescript.ts", { "just-types": "true" }, [], language); + super( + "json-ts", + "ts", + "typescript.ts", + { "just-types": "true" }, + [], + language, + ); } shouldSkipTest(sample: Sample): boolean { @@ -568,7 +729,10 @@ class JSONTypeScriptFixture extends JSONToXToYFixture { // This fixture tests generating code from JSON Schema. class JSONSchemaFixture extends LanguageFixture { - constructor(language: languages.Language, readonly name: string = `schema-${language.name}`) { + constructor( + language: languages.Language, + readonly name: string = `schema-${language.name}`, + ) { super(language); } @@ -585,8 +749,17 @@ class JSONSchemaFixture extends LanguageFixture { return _.includes(this.language.skipSchema, path.basename(sample.path)); } - async runQuicktype(filename: string, additionalRendererOptions: RendererOptions): Promise { - await quicktypeForLanguage(this.language, filename, "schema", false, additionalRendererOptions); + async runQuicktype( + filename: string, + additionalRendererOptions: RendererOptions, + ): Promise { + await quicktypeForLanguage( + this.language, + filename, + "schema", + false, + additionalRendererOptions, + ); } additionalFiles(sample: Sample): string[] { @@ -597,36 +770,48 @@ class JSONSchemaFixture extends LanguageFixture { async test( _sample: string, additionalRendererOptions: RendererOptions, - additionalFiles: string[] + additionalFiles: string[], ): Promise { if (this.language.compileCommand) { await execAsync(this.language.compileCommand); } if (this.language.runCommand === undefined) return 0; - const failExtensions = this.language.features.map(f => `.fail.${f}.json`).concat([".fail.json"]); + const failExtensions = this.language.features + .map((f) => `.fail.${f}.json`) + .concat([".fail.json"]); for (const filename of additionalFiles) { - if (failExtensions.some(ext => filename.endsWith(ext))) { + if (failExtensions.some((ext) => filename.endsWith(ext))) { callAndExpectFailure( `Expected failure on input ${filename}`, () => exec( defined(this.language.runCommand)(filename), runEnvForLanguage(additionalRendererOptions), - false - ).stdout + false, + ).stdout, ); } else { let expected = filename; for (const feature of this.language.features) { - const featureFilename = filename.replace(".json", `.out.${feature}.json`); + const featureFilename = filename.replace( + ".json", + `.out.${feature}.json`, + ); if (fs.existsSync(featureFilename)) { expected = featureFilename; break; } } - compareJsonFileToJson(comparisonArgs(this.language, filename, expected, additionalRendererOptions)); + compareJsonFileToJson( + comparisonArgs( + this.language, + filename, + expected, + additionalRendererOptions, + ), + ); } } return additionalFiles.length; @@ -636,22 +821,27 @@ class JSONSchemaFixture extends LanguageFixture { function graphQLSchemaFilename(baseName: string): string { const baseMatch = baseName.match(/(.*\D)\d+$/); if (baseMatch === null) { - return failWith("GraphQL test filename does not correspond to naming schema", { baseName }); + return failWith( + "GraphQL test filename does not correspond to naming schema", + { baseName }, + ); } - return baseMatch[1] + ".gqlschema"; + return `${baseMatch[1]}.gqlschema`; } class GraphQLFixture extends LanguageFixture { constructor( language: languages.Language, private readonly _onlyExactName: boolean = false, - readonly name: string = `graphql-${language.name}` + readonly name: string = `graphql-${language.name}`, ) { super(language); } runForName(name: string): boolean { - return this.name === name || (!this._onlyExactName && name === "graphql"); + return ( + this.name === name || (!this._onlyExactName && name === "graphql") + ); } getSamples(sources: string[]): { priority: Sample[]; others: Sample[] } { @@ -663,7 +853,10 @@ class GraphQLFixture extends LanguageFixture { return false; } - async runQuicktype(filename: string, additionalRendererOptions: RendererOptions): Promise { + async runQuicktype( + filename: string, + additionalRendererOptions: RendererOptions, + ): Promise { const baseName = pathWithoutExtension(filename, ".graphql"); const schemaFilename = graphQLSchemaFilename(baseName); await quicktypeForLanguage( @@ -672,7 +865,7 @@ class GraphQLFixture extends LanguageFixture { "graphql", false, additionalRendererOptions, - schemaFilename + schemaFilename, ); } @@ -684,7 +877,7 @@ class GraphQLFixture extends LanguageFixture { async test( _filename: string, additionalRendererOptions: RendererOptions, - additionalFiles: string[] + additionalFiles: string[], ): Promise { if (this.language.compileCommand) { await execAsync(this.language.compileCommand); @@ -692,14 +885,24 @@ class GraphQLFixture extends LanguageFixture { if (this.language.runCommand === undefined) return 0; for (const fn of additionalFiles) { - compareJsonFileToJson(comparisonArgs(this.language, fn, fn, additionalRendererOptions)); + compareJsonFileToJson( + comparisonArgs( + this.language, + fn, + fn, + additionalRendererOptions, + ), + ); } return additionalFiles.length; } } class CommandSuccessfulLanguageFixture extends LanguageFixture { - constructor(language: languages.Language, public name: string = language.name) { + constructor( + language: languages.Language, + public name: string = language.name, + ) { super(language); } @@ -707,15 +910,24 @@ class CommandSuccessfulLanguageFixture extends LanguageFixture { return this.name === name || name === "json"; } - async runQuicktype(sample: string, additionalRendererOptions: RendererOptions): Promise { + async runQuicktype( + sample: string, + additionalRendererOptions: RendererOptions, + ): Promise { // FIXME: add options - await quicktypeForLanguage(this.language, sample, "json", true, additionalRendererOptions); + await quicktypeForLanguage( + this.language, + sample, + "json", + true, + additionalRendererOptions, + ); } async test( filename: string, _additionalRendererOptions: RendererOptions, - _additionalFiles: string[] + _additionalFiles: string[], ): Promise { if (this.language.compileCommand) { await execAsync(this.language.compileCommand); @@ -746,44 +958,65 @@ class CommandSuccessfulLanguageFixture extends LanguageFixture { // FIXME: this should only run once const prioritySamples = _.concat( testsInDir("test/inputs/json/priority", "json"), - testsInDir("test/inputs/json/samples", "json") + testsInDir("test/inputs/json/samples", "json"), ); - const miscSamples = this.language.skipMiscJSON ? [] : testsInDir("test/inputs/json/misc", "json"); + const miscSamples = this.language.skipMiscJSON + ? [] + : testsInDir("test/inputs/json/misc", "json"); - let { priority, others } = samplesFromSources(sources, prioritySamples, miscSamples, "json"); + let { priority, others } = samplesFromSources( + sources, + prioritySamples, + miscSamples, + "json", + ); - const combinationInputs = _.map([1, 2, 3, 4], n => - _.find(prioritySamples, p => p.endsWith(`/priority/combinations${n}.json`)) + const combinationInputs = _.map([1, 2, 3, 4], (n) => + _.find(prioritySamples, (p) => + p.endsWith(`/priority/combinations${n}.json`), + ), ); - if (combinationInputs.some(p => p === undefined)) { - return failWith("priority/combinations[1234].json samples not found", prioritySamples); + if (combinationInputs.some((p) => p === undefined)) { + return failWith( + "priority/combinations[1234].json samples not found", + { prioritySamples }, + ); } if (sources.length === 0 && !ONLY_OUTPUT) { - const quickTestSamples = _.chain(this.language.quickTestRendererOptions) - .flatMap(qt => { + const quickTestSamples = _.chain( + this.language.quickTestRendererOptions, + ) + .flatMap((qt) => { if (Array.isArray(qt)) { const [filename, ro] = qt; - const input = _.find(([] as string[]).concat(prioritySamples, miscSamples), p => - p.endsWith(`/${filename}`) + const input = _.find( + ([] as string[]).concat( + prioritySamples, + miscSamples, + ), + (p) => p.endsWith(`/${filename}`), ); if (input === undefined) { - return failWith(`quick-test sample ${filename} not found`, qt); + return failWith( + `quick-test sample ${filename} not found`, + { qt }, + ); } return [ { path: input, additionalRendererOptions: ro, - saveOutput: false - } + saveOutput: false, + }, ]; - } else { - return _.map(combinationInputs, p => ({ - path: defined(p), - additionalRendererOptions: qt, - saveOutput: false - })); } + + return _.map(combinationInputs, (p) => ({ + path: defined(p), + additionalRendererOptions: qt, + saveOutput: false, + })); }) .value(); priority = quickTestSamples.concat(priority); @@ -796,9 +1029,15 @@ class CommandSuccessfulLanguageFixture extends LanguageFixture { export const allFixtures: Fixture[] = [ // new JSONFixture(languages.CrystalLanguage), new JSONFixture(languages.CSharpLanguage), - new JSONFixture(languages.CSharpLanguageSystemTextJson, "csharp-SystemTextJson"), + new JSONFixture( + languages.CSharpLanguageSystemTextJson, + "csharp-SystemTextJson", + ), new JSONFixture(languages.JavaLanguage), - new JSONFixture(languages.JavaLanguageWithLegacyDateTime, "java-datetime-legacy"), + new JSONFixture( + languages.JavaLanguageWithLegacyDateTime, + "java-datetime-legacy", + ), new JSONFixture(languages.JavaLanguageWithLombok, "java-lombok"), new JSONFixture(languages.GoLanguage), new JSONFixture(languages.CJSONLanguage), @@ -821,13 +1060,20 @@ export const allFixtures: Fixture[] = [ new JSONFixture(languages.DartLanguage), new JSONFixture(languages.PikeLanguage), new JSONFixture(languages.HaskellLanguage), + new JSONFixture(languages.ElixirLanguage), new JSONSchemaJSONFixture(languages.CSharpLanguage), new JSONTypeScriptFixture(languages.CSharpLanguage), // new JSONSchemaFixture(languages.CrystalLanguage), new JSONSchemaFixture(languages.CSharpLanguage), new JSONSchemaFixture(languages.JavaLanguage), - new JSONSchemaFixture(languages.JavaLanguageWithLegacyDateTime, "schema-java-datetime-legacy"), - new JSONSchemaFixture(languages.JavaLanguageWithLombok, "schema-java-lombok"), + new JSONSchemaFixture( + languages.JavaLanguageWithLegacyDateTime, + "schema-java-datetime-legacy", + ), + new JSONSchemaFixture( + languages.JavaLanguageWithLombok, + "schema-java-lombok", + ), new JSONSchemaFixture(languages.GoLanguage), new JSONSchemaFixture(languages.CJSONLanguage), new JSONSchemaFixture(languages.CPlusPlusLanguage), @@ -840,16 +1086,28 @@ export const allFixtures: Fixture[] = [ new JSONSchemaFixture(languages.FlowLanguage), new JSONSchemaFixture(languages.JavaScriptLanguage), new JSONSchemaFixture(languages.KotlinLanguage), - new JSONSchemaFixture(languages.KotlinJacksonLanguage, "schema-kotlin-jackson"), + new JSONSchemaFixture( + languages.KotlinJacksonLanguage, + "schema-kotlin-jackson", + ), new JSONSchemaFixture(languages.Scala3Language), new JSONSchemaFixture(languages.DartLanguage), new JSONSchemaFixture(languages.PikeLanguage), new JSONSchemaFixture(languages.HaskellLanguage), + new JSONSchemaFixture(languages.ElixirLanguage), // FIXME: Why are we missing so many language with GraphQL? new GraphQLFixture(languages.CSharpLanguage), new GraphQLFixture(languages.JavaLanguage), - new GraphQLFixture(languages.JavaLanguageWithLegacyDateTime, false, "graphql-java-datetime-legacy"), - new GraphQLFixture(languages.JavaLanguageWithLombok, false, "graphql-java-lombok"), + new GraphQLFixture( + languages.JavaLanguageWithLegacyDateTime, + false, + "graphql-java-datetime-legacy", + ), + new GraphQLFixture( + languages.JavaLanguageWithLombok, + false, + "graphql-java-lombok", + ), new GraphQLFixture(languages.GoLanguage), new GraphQLFixture(languages.CJSONLanguage), new GraphQLFixture(languages.CPlusPlusLanguage), @@ -863,5 +1121,6 @@ export const allFixtures: Fixture[] = [ new GraphQLFixture(languages.PikeLanguage), new GraphQLFixture(languages.HaskellLanguage), new GraphQLFixture(languages.PHPLanguage), - new CommandSuccessfulLanguageFixture(languages.JavaScriptPropTypesLanguage) + new GraphQLFixture(languages.ElixirLanguage), + new CommandSuccessfulLanguageFixture(languages.JavaScriptPropTypesLanguage), ]; diff --git a/test/fixtures/cplusplus/main.cpp b/test/fixtures/cplusplus/main.cpp index 3052e3c21..d963530b5 100644 --- a/test/fixtures/cplusplus/main.cpp +++ b/test/fixtures/cplusplus/main.cpp @@ -14,14 +14,14 @@ int main(int argc, const char * argv[]) { std::cerr << "Usage: " << argv[0] << " FILE"; return 1; } - + std::ifstream t(argv[1]); std::string str((std::istreambuf_iterator(t)), std::istreambuf_iterator()); TopLevel tl = json::parse(str); json j2 = tl; - + std::cout << j2 << std::endl; return 0; diff --git a/test/fixtures/csharp-SystemTextJson/.vscode/launch.json b/test/fixtures/csharp-SystemTextJson/.vscode/launch.json index 5143f096f..d4083c9b3 100644 --- a/test/fixtures/csharp-SystemTextJson/.vscode/launch.json +++ b/test/fixtures/csharp-SystemTextJson/.vscode/launch.json @@ -1,9 +1,9 @@ { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ { "name": ".NET Core Launch (console)", "type": "coreclr", @@ -25,4 +25,4 @@ "processId": "${command:pickProcess}" } ] -} \ No newline at end of file +} diff --git a/test/fixtures/csharp-SystemTextJson/.vscode/tasks.json b/test/fixtures/csharp-SystemTextJson/.vscode/tasks.json index 9f4391576..472e19d9d 100644 --- a/test/fixtures/csharp-SystemTextJson/.vscode/tasks.json +++ b/test/fixtures/csharp-SystemTextJson/.vscode/tasks.json @@ -6,11 +6,9 @@ "tasks": [ { "taskName": "build", - "args": [ - "${workspaceRoot}/test.csproj" - ], + "args": ["${workspaceRoot}/test.csproj"], "isBuildCommand": true, "problemMatcher": "$msCompile" } ] -} \ No newline at end of file +} diff --git a/test/fixtures/csharp-SystemTextJson/test.csproj b/test/fixtures/csharp-SystemTextJson/test.csproj index 22a4b741a..1f5224ffd 100755 --- a/test/fixtures/csharp-SystemTextJson/test.csproj +++ b/test/fixtures/csharp-SystemTextJson/test.csproj @@ -4,6 +4,6 @@ net6 - + - \ No newline at end of file + diff --git a/test/fixtures/csharp/.vscode/launch.json b/test/fixtures/csharp/.vscode/launch.json index 5143f096f..d4083c9b3 100644 --- a/test/fixtures/csharp/.vscode/launch.json +++ b/test/fixtures/csharp/.vscode/launch.json @@ -1,9 +1,9 @@ { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ { "name": ".NET Core Launch (console)", "type": "coreclr", @@ -25,4 +25,4 @@ "processId": "${command:pickProcess}" } ] -} \ No newline at end of file +} diff --git a/test/fixtures/csharp/.vscode/tasks.json b/test/fixtures/csharp/.vscode/tasks.json index 9f4391576..472e19d9d 100644 --- a/test/fixtures/csharp/.vscode/tasks.json +++ b/test/fixtures/csharp/.vscode/tasks.json @@ -6,11 +6,9 @@ "tasks": [ { "taskName": "build", - "args": [ - "${workspaceRoot}/test.csproj" - ], + "args": ["${workspaceRoot}/test.csproj"], "isBuildCommand": true, "problemMatcher": "$msCompile" } ] -} \ No newline at end of file +} diff --git a/test/fixtures/csharp/test.csproj b/test/fixtures/csharp/test.csproj index 2e46824ab..2fbf1477c 100755 --- a/test/fixtures/csharp/test.csproj +++ b/test/fixtures/csharp/test.csproj @@ -4,6 +4,6 @@ netcoreapp6.0 - + - \ No newline at end of file + diff --git a/test/fixtures/elixir/.gitignore b/test/fixtures/elixir/.gitignore new file mode 100644 index 000000000..b7cb8a54f --- /dev/null +++ b/test/fixtures/elixir/.gitignore @@ -0,0 +1,26 @@ +# The directory Mix will write compiled artifacts to. +/_build/ + +# If you run "mix test --cover", coverage assets end up here. +/cover/ + +# The directory Mix downloads your dependencies sources to. +/deps/ + +# Where third-party dependencies like ExDoc output generated docs. +/doc/ + +# Ignore .fetch files in case you like to edit your project deps locally. +/.fetch + +# If the VM crashes, it generates a dump, let's ignore it too. +erl_crash.dump + +# Also ignore archive artifacts (built via "mix archive.build"). +*.ez + +# Ignore package tarball (built via "mix hex.build"). +quick_type_test-*.tar + +# Temporary files, for example, from tests. +/tmp/ diff --git a/test/fixtures/elixir/main.exs b/test/fixtures/elixir/main.exs new file mode 100644 index 000000000..bfca397cb --- /dev/null +++ b/test/fixtures/elixir/main.exs @@ -0,0 +1,13 @@ +defmodule Main do + def run do + [file_path | _] = System.argv() + + file_path + |> File.read!() + |> TopLevel.from_json() + |> TopLevel.to_json() + |> IO.puts() + end +end + +Main.run() diff --git a/test/fixtures/elixir/mix.exs b/test/fixtures/elixir/mix.exs new file mode 100644 index 000000000..94666f7c7 --- /dev/null +++ b/test/fixtures/elixir/mix.exs @@ -0,0 +1,31 @@ +defmodule QuickTypeTest.MixProject do + use Mix.Project + + def project do + [ + app: :quick_type_test, + version: "0.1.0", + elixir: "~> 1.15", + elixirc_paths: elixirc_paths(Mix.env()), + elixirc_options: [ignore_module_conflict: true], + start_permanent: Mix.env() == :prod, + deps: deps() + ] + end + + # Run "mix help compile.app" to learn about applications. + def application do + [ + extra_applications: [:logger] + ] + end + + defp elixirc_paths(_), do: ["./"] + + # Run "mix help deps" to learn about dependencies. + defp deps do + [ + {:jason, "~> 1.2"} + ] + end +end diff --git a/test/fixtures/elixir/mix.lock b/test/fixtures/elixir/mix.lock new file mode 100644 index 000000000..ddb949c99 --- /dev/null +++ b/test/fixtures/elixir/mix.lock @@ -0,0 +1,3 @@ +%{ + "jason": {:hex, :jason, "1.4.1", "af1504e35f629ddcdd6addb3513c3853991f694921b1b9368b0bd32beb9f1b63", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "fbb01ecdfd565b56261302f7e1fcc27c4fb8f32d56eab74db621fc154604a7a1"}, +} diff --git a/test/fixtures/elm/elm-package.json b/test/fixtures/elm/elm-package.json index f422b20ff..d688a53c9 100644 --- a/test/fixtures/elm/elm-package.json +++ b/test/fixtures/elm/elm-package.json @@ -3,9 +3,7 @@ "summary": "helpful summary of your project, less than 80 characters", "repository": "https://github.com/user/project.git", "license": "BSD3", - "source-directories": [ - "." - ], + "source-directories": ["."], "exposed-modules": [], "dependencies": { "NoRedInk/elm-decode-pipeline": "3.0.0 <= v < 4.0.0", diff --git a/test/fixtures/elm/runner.js b/test/fixtures/elm/runner.js index 61bdded06..d1c23b799 100644 --- a/test/fixtures/elm/runner.js +++ b/test/fixtures/elm/runner.js @@ -1,13 +1,17 @@ const Elm = require("./elm.js"); const fs = require("fs"); -let ports = Elm.Main.worker().ports; +const ports = Elm.Main.worker().ports; -ports.toJS.subscribe(function(result) { +ports.toJS.subscribe((result) => { if (result.startsWith("Error: ")) { - process.stderr.write(result + "\n", function() { process.exit(1); }); + process.stderr.write(result + "\n", () => { + process.exit(1); + }); } else { - process.stdout.write(result + "\n", function() { process.exit(0); }); + process.stdout.write(result + "\n", () => { + process.exit(0); + }); } }); diff --git a/test/fixtures/flow/main.js b/test/fixtures/flow/main.js index 0911b0b99..0953249fc 100644 --- a/test/fixtures/flow/main.js +++ b/test/fixtures/flow/main.js @@ -7,7 +7,7 @@ const fs = require("fs"); const sample = process.argv[2]; const json = fs.readFileSync(sample).toString(); -let value = TopLevel.toTopLevel(json); -let backToJson = TopLevel.topLevelToJson(value); +const value = TopLevel.toTopLevel(json); +const backToJson = TopLevel.topLevelToJson(value); console.log(backToJson); diff --git a/test/fixtures/javascript-prop-types/main.js b/test/fixtures/javascript-prop-types/main.js index 2d98efd53..36febff60 100644 --- a/test/fixtures/javascript-prop-types/main.js +++ b/test/fixtures/javascript-prop-types/main.js @@ -7,10 +7,15 @@ const sample = argv[2]; const json = readFileSync(sample); const obj = JSON.parse(json); -const results = checkPropTypes({ obj: TopLevel }, { obj }, "prop", "MyComponent"); +const results = checkPropTypes( + { obj: TopLevel }, + { obj }, + "prop", + "MyComponent", +); if (results) { - console.log("Failure:", results); + console.log("Failure:", results); } else { - console.log("Success"); + console.log("Success"); } diff --git a/test/fixtures/javascript-prop-types/package.json b/test/fixtures/javascript-prop-types/package.json index f708256f2..91b5d9b09 100644 --- a/test/fixtures/javascript-prop-types/package.json +++ b/test/fixtures/javascript-prop-types/package.json @@ -1,15 +1,15 @@ { - "name": "javascript-prop-types", - "version": "0.1.0", - "type": "module", - "description": "Test builds.", - "main": "main.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "Apache-2.0", - "dependencies": { - "check-prop-types": "^1.1.2" - } + "name": "javascript-prop-types", + "version": "0.1.0", + "type": "module", + "description": "Test builds.", + "main": "main.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "Apache-2.0", + "dependencies": { + "check-prop-types": "^1.1.2" + } } diff --git a/test/fixtures/javascript/main.js b/test/fixtures/javascript/main.js index f76a027b2..cb60dd70d 100644 --- a/test/fixtures/javascript/main.js +++ b/test/fixtures/javascript/main.js @@ -6,7 +6,7 @@ const process = require("process"); const sample = process.argv[2]; const json = fs.readFileSync(sample); -let value = TopLevel.toTopLevel(json); -let backToJson = TopLevel.topLevelToJson(value); +const value = TopLevel.toTopLevel(json); +const backToJson = TopLevel.topLevelToJson(value); console.log(backToJson); diff --git a/test/fixtures/kotlin/sample.json b/test/fixtures/kotlin/sample.json index 2745fb5f2..aa95faec7 100644 --- a/test/fixtures/kotlin/sample.json +++ b/test/fixtures/kotlin/sample.json @@ -1,3 +1,3 @@ { "name": "David" -} \ No newline at end of file +} diff --git a/test/fixtures/objective-c/sample.json b/test/fixtures/objective-c/sample.json index 65685de44..2b49c232a 100644 --- a/test/fixtures/objective-c/sample.json +++ b/test/fixtures/objective-c/sample.json @@ -1,1853 +1,1872 @@ - [{ - "id": "6263117491", - "type": "PushEvent", - "actor": { - "id": 12358972, - "login": "CodePipeline-Test", - "display_login": "CodePipeline-Test", - "gravatar_id": "", - "url": "https://api.github.com/users/CodePipeline-Test", - "avatar_url": "https://avatars.githubusercontent.com/u/12358972?" - }, - "repo": { - "id": 63971386, - "name": "CodePipeline-Test/feature-tests", - "url": "https://api.github.com/repos/CodePipeline-Test/feature-tests" - }, - "payload": { - "push_id": 1861573815, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/job-worker-features-V5zkpTEUgBlA4TOEJrWq", - "head": "f283b1955dd88fe65210c842e63408d5ad30d322", - "before": "873d322eb50db0068ae3d0ea2e79cee345e31c93", - "commits": [{ - "sha": "f283b1955dd88fe65210c842e63408d5ad30d322", - "author": { - "email": "CodePipeline-Test@users.noreply.github.com", - "name": "CodePipeline-Test" - }, - "message": "Test commit", - "distinct": true, - "url": "https://api.github.com/repos/CodePipeline-Test/feature-tests/commits/f283b1955dd88fe65210c842e63408d5ad30d322" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z" - }, - { - "id": "6263117489", - "type": "PushEvent", - "actor": { - "id": 16156445, - "login": "JonnyPickard", - "display_login": "JonnyPickard", - "gravatar_id": "", - "url": "https://api.github.com/users/JonnyPickard", - "avatar_url": "https://avatars.githubusercontent.com/u/16156445?" - }, - "repo": { - "id": 97318059, - "name": "JonnyPickard/albums-react-native", - "url": "https://api.github.com/repos/JonnyPickard/albums-react-native" - }, - "payload": { - "push_id": 1861573814, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "a11c7aedf4f1800357864302fe08fc277e9e8652", - "before": "d33e7adbb46926d1d4030d0c855b245062f1d9b5", - "commits": [{ - "sha": "a11c7aedf4f1800357864302fe08fc277e9e8652", - "author": { - "email": "jonathandpickard@gmail.com", - "name": "Jonny Pickard" - }, - "message": "Add basic server to send JSON", - "distinct": true, - "url": "https://api.github.com/repos/JonnyPickard/albums-react-native/commits/a11c7aedf4f1800357864302fe08fc277e9e8652" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z" - }, - { - "id": "6263117487", - "type": "IssueCommentEvent", - "actor": { - "id": 4236651, - "login": "0x53A", - "display_login": "0x53A", - "gravatar_id": "", - "url": "https://api.github.com/users/0x53A", - "avatar_url": "https://avatars.githubusercontent.com/u/4236651?" - }, - "repo": { - "id": 29048891, - "name": "Microsoft/visualfsharp", - "url": "https://api.github.com/repos/Microsoft/visualfsharp" - }, - "payload": { - "action": "created", - "issue": { - "url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335", - "repository_url": "https://api.github.com/repos/Microsoft/visualfsharp", - "labels_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335/labels{/name}", - "comments_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335/comments", - "events_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335/events", - "html_url": "https://github.com/Microsoft/visualfsharp/issues/3335", - "id": 243089775, - "number": 3335, - "title": "[15.3 pre] loading in VS / publish fails if FSharp.Compiler.Tools is imported", - "user": { - "login": "0x53A", - "id": 4236651, - "avatar_url": "https://avatars7.githubusercontent.com/u/4236651?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/0x53A", - "html_url": "https://github.com/0x53A", - "followers_url": "https://api.github.com/users/0x53A/followers", - "following_url": "https://api.github.com/users/0x53A/following{/other_user}", - "gists_url": "https://api.github.com/users/0x53A/gists{/gist_id}", - "starred_url": "https://api.github.com/users/0x53A/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/0x53A/subscriptions", - "organizations_url": "https://api.github.com/users/0x53A/orgs", - "repos_url": "https://api.github.com/users/0x53A/repos", - "events_url": "https://api.github.com/users/0x53A/events{/privacy}", - "received_events_url": "https://api.github.com/users/0x53A/received_events", - "type": "User", - "site_admin": false - }, - "labels": [{ - "id": 308803045, - "url": "https://api.github.com/repos/Microsoft/visualfsharp/labels/Area-CoreCLR", - "name": "Area-CoreCLR", - "color": "5319e7", - "default": false - }], - "state": "closed", - "locked": false, - "assignee": null, - "assignees": [ - - ], - "milestone": { - "url": "https://api.github.com/repos/Microsoft/visualfsharp/milestones/9", - "html_url": "https://github.com/Microsoft/visualfsharp/milestone/9", - "labels_url": "https://api.github.com/repos/Microsoft/visualfsharp/milestones/9/labels", - "id": 2233574, - "number": 9, - "title": "VS 2017 Updates", - "description": "This milestone is for any bug, new feature, or improvement which makes it into a later VS 2017 update.", - "creator": { - "login": "cartermp", - "id": 6309070, - "avatar_url": "https://avatars4.githubusercontent.com/u/6309070?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/cartermp", - "html_url": "https://github.com/cartermp", - "followers_url": "https://api.github.com/users/cartermp/followers", - "following_url": "https://api.github.com/users/cartermp/following{/other_user}", - "gists_url": "https://api.github.com/users/cartermp/gists{/gist_id}", - "starred_url": "https://api.github.com/users/cartermp/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/cartermp/subscriptions", - "organizations_url": "https://api.github.com/users/cartermp/orgs", - "repos_url": "https://api.github.com/users/cartermp/repos", - "events_url": "https://api.github.com/users/cartermp/events{/privacy}", - "received_events_url": "https://api.github.com/users/cartermp/received_events", - "type": "User", - "site_admin": false - }, - "open_issues": 55, - "closed_issues": 158, - "state": "open", - "created_at": "2017-01-06T17:42:02Z", - "updated_at": "2017-07-15T00:13:34Z", - "due_on": null, - "closed_at": null - }, - "comments": 29, - "created_at": "2017-07-14T19:28:04Z", - "updated_at": "2017-07-15T17:06:46Z", - "closed_at": "2017-07-15T00:13:33Z", - "body": "\r\nEdit2: everything works, thanks @KevinRansom \r\n\r\n_Edited_\r\n\r\nI have tried to test if / how a project using paket works in the new world of ``dotnet 2``, comparing C#, F#, and the previous F# sdk (FSharp.NET.Sdk). I have also tested if using F# without paket works.\r\n\r\nHere are four branches, one for each test: https://github.com/0x53A/dotnet-tests.\r\n\r\nResults:\r\n\r\n* paket works with C# and ``Microsoft.NET.Sdk``: https://github.com/0x53A/dotnet-tests/tree/csharp+paket\r\n* paket works with F# when using the 1.x sdk (``FSharp.NET.Sdk``): https://github.com/0x53A/dotnet-tests/tree/fsharp+paket+FSharp.NET.Sdk\r\n* paket ~does NOT~ does work with F# and ``Microsoft.NET.Sdk``: https://github.com/0x53A/dotnet-tests/tree/fsharp+paket\r\n* using F# with ``Microsoft.NET.Sdk`` and nuget does work: https://github.com/0x53A/dotnet-tests/tree/fsharp+nuget\r\n\r\nThe paket version I have tested this with is ``5.6.12``.\r\n\r\nIt is kind of funny that C# seems to work flawlessly with paket." - }, - "comment": { - "url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/comments/315547940", - "html_url": "https://github.com/Microsoft/visualfsharp/issues/3335#issuecomment-315547940", - "issue_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335", - "id": 315547940, - "user": { - "login": "0x53A", - "id": 4236651, - "avatar_url": "https://avatars7.githubusercontent.com/u/4236651?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/0x53A", - "html_url": "https://github.com/0x53A", - "followers_url": "https://api.github.com/users/0x53A/followers", - "following_url": "https://api.github.com/users/0x53A/following{/other_user}", - "gists_url": "https://api.github.com/users/0x53A/gists{/gist_id}", - "starred_url": "https://api.github.com/users/0x53A/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/0x53A/subscriptions", - "organizations_url": "https://api.github.com/users/0x53A/orgs", - "repos_url": "https://api.github.com/users/0x53A/repos", - "events_url": "https://api.github.com/users/0x53A/events{/privacy}", - "received_events_url": "https://api.github.com/users/0x53A/received_events", - "type": "User", - "site_admin": false - }, - "created_at": "2017-07-15T17:06:46Z", - "updated_at": "2017-07-15T17:06:46Z", - "body": "3) DisableImplicitFSharpCoreReference and paket\r\n\r\npaket.dependencies:\r\n\r\n```nuget FSharp.Core 4.0.0.1```\r\n\r\n```Xml\r\n\r\n \r\n net461\r\n true\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\n=>\r\n\r\n```\r\nC:\\source\\dotnet-tests>dotnet publish\r\nMicrosoft (R) Build Engine version 15.3.406.54721 for .NET Core\r\nCopyright (C) Microsoft Corporation. All rights reserved.\r\n\r\nC:\\source\\dotnet-tests\\Library.fs(7,17): error FS0039: The value, namespace, type or module 'Result' is not defined. [C:\\source\\dotnet-tests\\paket-fsharp-test.fsproj]\r\nC:\\source\\dotnet-tests\\Library.fs(8,42): error FS0039: The pattern discriminator 'Ok' is not defined. [C:\\source\\dotnet-tests\\paket-fsharp-test.fsproj]\r\n```\r\n\r\nwhich is good.\r\n\r\n-----------------\r\n\r\nSo it looks like both properties work as expected. It seems that in __2)__ the compiler automagically referenced some FSharp.Core, because none was explicitly referenced." - } - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z", - "org": { - "id": 6154722, - "login": "Microsoft", - "gravatar_id": "", - "url": "https://api.github.com/orgs/Microsoft", - "avatar_url": "https://avatars.githubusercontent.com/u/6154722?" - } - }, - { - "id": "6263117486", - "type": "PushEvent", - "actor": { - "id": 982267, - "login": "gxela", - "display_login": "gxela", - "gravatar_id": "", - "url": "https://api.github.com/users/gxela", - "avatar_url": "https://avatars.githubusercontent.com/u/982267?" - }, - "repo": { - "id": 97197951, - "name": "AudioBible/AudioBible.life", - "url": "https://api.github.com/repos/AudioBible/AudioBible.life" - }, - "payload": { - "push_id": 1861573811, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "31e079597959be78850e06c623383d522f8fe283", - "before": "11d32ac0eb7051ddc7da05dab183f10ed861fa61", - "commits": [{ - "sha": "31e079597959be78850e06c623383d522f8fe283", - "author": { - "email": "alex@goretoy.com", - "name": "Alex Goretoy" - }, - "message": "update", - "distinct": true, - "url": "https://api.github.com/repos/AudioBible/AudioBible.life/commits/31e079597959be78850e06c623383d522f8fe283" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z", - "org": { - "id": 29329308, - "login": "AudioBible", - "gravatar_id": "", - "url": "https://api.github.com/orgs/AudioBible", - "avatar_url": "https://avatars.githubusercontent.com/u/29329308?" - } - }, - { - "id": "6263117481", - "type": "CreateEvent", - "actor": { - "id": 998519, - "login": "martinstabe", - "display_login": "martinstabe", - "gravatar_id": "", - "url": "https://api.github.com/users/martinstabe", - "avatar_url": "https://avatars.githubusercontent.com/u/998519?" - }, - "repo": { - "id": 90621389, - "name": "ft-interactive/archive", - "url": "https://api.github.com/repos/ft-interactive/archive" - }, - "payload": { - "ref": "personal-data", - "ref_type": "branch", - "master_branch": "master", - "description": "Refactored versions of a few older FT interactive stories", - "pusher_type": "user" - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z", - "org": { - "id": 2511089, - "login": "ft-interactive", - "gravatar_id": "", - "url": "https://api.github.com/orgs/ft-interactive", - "avatar_url": "https://avatars.githubusercontent.com/u/2511089?" - } - }, - { - "id": "6263117480", - "type": "PushEvent", - "actor": { - "id": 30200303, - "login": "musikdusche", - "display_login": "musikdusche", - "gravatar_id": "", - "url": "https://api.github.com/users/musikdusche", - "avatar_url": "https://avatars.githubusercontent.com/u/30200303?" - }, - "repo": { - "id": 97330240, - "name": "musikdusche/hello-world", - "url": "https://api.github.com/repos/musikdusche/hello-world" - }, - "payload": { - "push_id": 1861573809, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/readmeworks", - "head": "e09f4ef810382578be4ba49bcc351c94ac8b15f9", - "before": "10f052d3f22eaad13302b5e0e6d1a4af77a73f91", - "commits": [{ - "sha": "e09f4ef810382578be4ba49bcc351c94ac8b15f9", - "author": { - "email": "f.toens@gmx.de", - "name": "musikdusche" - }, - "message": "Update README.md\n\ntrying out markdown syntaxes", - "distinct": true, - "url": "https://api.github.com/repos/musikdusche/hello-world/commits/e09f4ef810382578be4ba49bcc351c94ac8b15f9" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z" - }, - { - "id": "6263117478", - "type": "PushEvent", - "actor": { - "id": 4712642, - "login": "neu-rah", - "display_login": "neu-rah", - "gravatar_id": "", - "url": "https://api.github.com/users/neu-rah", - "avatar_url": "https://avatars.githubusercontent.com/u/4712642?" - }, - "repo": { - "id": 23024191, - "name": "neu-rah/ArduinoMenu", - "url": "https://api.github.com/repos/neu-rah/ArduinoMenu" - }, - "payload": { - "push_id": 1861573808, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "1557e3155279ca19e35048f8a6758189cbb2231a", - "before": "fb1b8c70b324bf73231728a708fe496991c51607", - "commits": [{ - "sha": "1557e3155279ca19e35048f8a6758189cbb2231a", - "author": { - "email": "ruihfazevedo@gmail.com", - "name": "Rui Azevedo" - }, - "message": "remove pin collision between encoder and serial on I2C example as noted by Paul Gaertner", - "distinct": true, - "url": "https://api.github.com/repos/neu-rah/ArduinoMenu/commits/1557e3155279ca19e35048f8a6758189cbb2231a" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:47Z" - }, - { - "id": "6263117476", - "type": "PushEvent", - "actor": { - "id": 22308572, - "login": "zfang399", - "display_login": "zfang399", - "gravatar_id": "", - "url": "https://api.github.com/users/zfang399", - "avatar_url": "https://avatars.githubusercontent.com/u/22308572?" - }, - "repo": { - "id": 93472978, - "name": "zfang399/LeetCode-Problems", - "url": "https://api.github.com/repos/zfang399/LeetCode-Problems" - }, - "payload": { - "push_id": 1861573807, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "dffd54fc9872b0a14ae7b3089c541db439c77dc6", - "before": "31643c5f628a91714dabf3c0472d6b3b6f2d75f9", - "commits": [{ - "sha": "dffd54fc9872b0a14ae7b3089c541db439c77dc6", - "author": { - "email": "zfang@nd.edu", - "name": "Zhaoyuan Fang" - }, - "message": "Reverse Linked List II", - "distinct": true, - "url": "https://api.github.com/repos/zfang399/LeetCode-Problems/commits/dffd54fc9872b0a14ae7b3089c541db439c77dc6" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z" - }, - { - "id": "6263117475", - "type": "PushEvent", - "actor": { - "id": 4750766, - "login": "rohintangirala", - "display_login": "rohintangirala", - "gravatar_id": "", - "url": "https://api.github.com/users/rohintangirala", - "avatar_url": "https://avatars.githubusercontent.com/u/4750766?" - }, - "repo": { - "id": 97284340, - "name": "Twenty-App/Twenty-App.github.io", - "url": "https://api.github.com/repos/Twenty-App/Twenty-App.github.io" - }, - "payload": { - "push_id": 1861573806, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "90effa1defcc57fbb19d118a3cf773e200542333", - "before": "a3a94db8f23bec183df701cc6f27b761be8f6250", - "commits": [{ - "sha": "90effa1defcc57fbb19d118a3cf773e200542333", - "author": { - "email": "rohinkt@gmail.com", - "name": "Rohin Tangirala" - }, - "message": "Set theme jekyll-theme-tactile", - "distinct": true, - "url": "https://api.github.com/repos/Twenty-App/Twenty-App.github.io/commits/90effa1defcc57fbb19d118a3cf773e200542333" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 30188091, - "login": "Twenty-App", - "gravatar_id": "", - "url": "https://api.github.com/orgs/Twenty-App", - "avatar_url": "https://avatars.githubusercontent.com/u/30188091?" - } - }, - { - "id": "6263117473", - "type": "PushEvent", - "actor": { - "id": 8517910, - "login": "LombiqBot", - "display_login": "LombiqBot", - "gravatar_id": "", - "url": "https://api.github.com/users/LombiqBot", - "avatar_url": "https://avatars.githubusercontent.com/u/8517910?" - }, - "repo": { - "id": 46594739, - "name": "Lombiq/Associativy-Taxonomies-Adapter", - "url": "https://api.github.com/repos/Lombiq/Associativy-Taxonomies-Adapter" - }, - "payload": { - "push_id": 1861573805, - "size": 0, - "distinct_size": 0, - "ref": "refs/heads/orchard-upgrade-1.10", - "head": "e1d77dd00dfdc65d5d84b1712be94e609273c838", - "before": "e1d77dd00dfdc65d5d84b1712be94e609273c838", - "commits": [ - - ] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 8158177, - "login": "Lombiq", - "gravatar_id": "", - "url": "https://api.github.com/orgs/Lombiq", - "avatar_url": "https://avatars.githubusercontent.com/u/8158177?" - } - }, - { - "id": "6263117472", - "type": "PushEvent", - "actor": { - "id": 25966, - "login": "reconbot", - "display_login": "reconbot", - "gravatar_id": "", - "url": "https://api.github.com/users/reconbot", - "avatar_url": "https://avatars.githubusercontent.com/u/25966?" - }, - "repo": { - "id": 893522, - "name": "EmergingTechnologyAdvisors/node-serialport", - "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport" - }, - "payload": { - "push_id": 1861573804, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a", - "before": "2361fa599a16a10ad07ffe863fe00bb2bc75d29a", - "commits": [{ - "sha": "9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a", - "author": { - "email": "wizard@roborooter.com", - "name": "Francis Gulotta" - }, - "message": "[unix] Move setting up the baudrate to the end of the open()\n\n- Test 1000000 baud", - "distinct": true, - "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/commits/9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 8947774, - "login": "EmergingTechnologyAdvisors", - "gravatar_id": "", - "url": "https://api.github.com/orgs/EmergingTechnologyAdvisors", - "avatar_url": "https://avatars.githubusercontent.com/u/8947774?" - } - }, - { - "id": "6263117471", - "type": "IssueCommentEvent", - "actor": { - "id": 737750, - "login": "samuelkarp", - "display_login": "samuelkarp", - "gravatar_id": "", - "url": "https://api.github.com/users/samuelkarp", - "avatar_url": "https://avatars.githubusercontent.com/u/737750?" - }, - "repo": { - "id": 59514412, - "name": "awslabs/amazon-ecr-credential-helper", - "url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper" - }, - "payload": { - "action": "created", - "issue": { - "url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49", - "repository_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper", - "labels_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49/labels{/name}", - "comments_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49/comments", - "events_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49/events", - "html_url": "https://github.com/awslabs/amazon-ecr-credential-helper/issues/49", - "id": 241526602, - "number": 49, - "title": "no basic auth credentials yet AWS CLI has access", - "user": { - "login": "guyisra", - "id": 1073521, - "avatar_url": "https://avatars5.githubusercontent.com/u/1073521?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/guyisra", - "html_url": "https://github.com/guyisra", - "followers_url": "https://api.github.com/users/guyisra/followers", - "following_url": "https://api.github.com/users/guyisra/following{/other_user}", - "gists_url": "https://api.github.com/users/guyisra/gists{/gist_id}", - "starred_url": "https://api.github.com/users/guyisra/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/guyisra/subscriptions", - "organizations_url": "https://api.github.com/users/guyisra/orgs", - "repos_url": "https://api.github.com/users/guyisra/repos", - "events_url": "https://api.github.com/users/guyisra/events{/privacy}", - "received_events_url": "https://api.github.com/users/guyisra/received_events", - "type": "User", - "site_admin": false - }, - "labels": [ - - ], - "state": "open", - "locked": false, - "assignee": null, - "assignees": [ - - ], - "milestone": null, - "comments": 3, - "created_at": "2017-07-09T13:59:15Z", - "updated_at": "2017-07-15T17:06:46Z", - "closed_at": null, - "body": "I am using Docker v17 and for some reason when trying to push to ECR I get no basic auth credentials.\r\n\r\nThis doesn't happen if I manually login with `aws ecr get-login ...`\r\n\r\nthe policy is configured correctly, I can run other AWS commands.\r\nIt gives the same response with either a profile with the proper policy or with the access key and secret explicitly set.." - }, - "comment": { - "url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/comments/315547939", - "html_url": "https://github.com/awslabs/amazon-ecr-credential-helper/issues/49#issuecomment-315547939", - "issue_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49", - "id": 315547939, - "user": { - "login": "samuelkarp", - "id": 737750, - "avatar_url": "https://avatars7.githubusercontent.com/u/737750?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/samuelkarp", - "html_url": "https://github.com/samuelkarp", - "followers_url": "https://api.github.com/users/samuelkarp/followers", - "following_url": "https://api.github.com/users/samuelkarp/following{/other_user}", - "gists_url": "https://api.github.com/users/samuelkarp/gists{/gist_id}", - "starred_url": "https://api.github.com/users/samuelkarp/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/samuelkarp/subscriptions", - "organizations_url": "https://api.github.com/users/samuelkarp/orgs", - "repos_url": "https://api.github.com/users/samuelkarp/repos", - "events_url": "https://api.github.com/users/samuelkarp/events{/privacy}", - "received_events_url": "https://api.github.com/users/samuelkarp/received_events", - "type": "User", - "site_admin": false - }, - "created_at": "2017-07-15T17:06:46Z", - "updated_at": "2017-07-15T17:06:46Z", - "body": "@mskutin Thanks for providing the log; that's very helpful. Can you let me know what region this was for so I can investigate further?" - } - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 3299148, - "login": "awslabs", - "gravatar_id": "", - "url": "https://api.github.com/orgs/awslabs", - "avatar_url": "https://avatars.githubusercontent.com/u/3299148?" - } - }, - { - "id": "6263117468", - "type": "IssueCommentEvent", - "actor": { - "id": 1645308, - "login": "almereyda", - "display_login": "almereyda", - "gravatar_id": "", - "url": "https://api.github.com/users/almereyda", - "avatar_url": "https://avatars.githubusercontent.com/u/1645308?" - }, - "repo": { - "id": 22657662, - "name": "wsargent/docker-cheat-sheet", - "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet" - }, - "payload": { - "action": "created", - "issue": { - "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136", - "repository_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet", - "labels_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136/labels{/name}", - "comments_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136/comments", - "events_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136/events", - "html_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136", - "id": 243181907, - "number": 136, - "title": "Volumes can be files", - "user": { - "login": "phoen1x", - "id": 2550793, - "avatar_url": "https://avatars7.githubusercontent.com/u/2550793?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/phoen1x", - "html_url": "https://github.com/phoen1x", - "followers_url": "https://api.github.com/users/phoen1x/followers", - "following_url": "https://api.github.com/users/phoen1x/following{/other_user}", - "gists_url": "https://api.github.com/users/phoen1x/gists{/gist_id}", - "starred_url": "https://api.github.com/users/phoen1x/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/phoen1x/subscriptions", - "organizations_url": "https://api.github.com/users/phoen1x/orgs", - "repos_url": "https://api.github.com/users/phoen1x/repos", - "events_url": "https://api.github.com/users/phoen1x/events{/privacy}", - "received_events_url": "https://api.github.com/users/phoen1x/received_events", - "type": "User", - "site_admin": false - }, - "labels": [ - - ], - "state": "open", - "locked": false, - "assignee": null, - "assignees": [ - - ], - "milestone": null, - "comments": 0, - "created_at": "2017-07-15T15:28:10Z", - "updated_at": "2017-07-15T17:06:46Z", - "closed_at": null, - "pull_request": { - "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/pulls/136", - "html_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136", - "diff_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136.diff", - "patch_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136.patch" - }, - "body": "Just wanted to add that is possible to mount files as volumes. \r\n\r\nDon't know if that is worth mentioning. But it can be useful if you want to toy around with a image from [Docker Hub](https://hub.docker.com) without writing your own Dockerfile." - }, - "comment": { - "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/comments/315547938", - "html_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136#issuecomment-315547938", - "issue_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136", - "id": 315547938, - "user": { - "login": "almereyda", - "id": 1645308, - "avatar_url": "https://avatars4.githubusercontent.com/u/1645308?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/almereyda", - "html_url": "https://github.com/almereyda", - "followers_url": "https://api.github.com/users/almereyda/followers", - "following_url": "https://api.github.com/users/almereyda/following{/other_user}", - "gists_url": "https://api.github.com/users/almereyda/gists{/gist_id}", - "starred_url": "https://api.github.com/users/almereyda/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/almereyda/subscriptions", - "organizations_url": "https://api.github.com/users/almereyda/orgs", - "repos_url": "https://api.github.com/users/almereyda/repos", - "events_url": "https://api.github.com/users/almereyda/events{/privacy}", - "received_events_url": "https://api.github.com/users/almereyda/received_events", - "type": "User", - "site_admin": false - }, - "created_at": "2017-07-15T17:06:46Z", - "updated_at": "2017-07-15T17:06:46Z", - "body": "Indeed, I do that all the time when modifying assets that were turned into immutable images already." - } - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z" - }, - { - "id": "6263117464", - "type": "PushEvent", - "actor": { - "id": 19437824, - "login": "keriwheatley", - "display_login": "keriwheatley", - "gravatar_id": "", - "url": "https://api.github.com/users/keriwheatley", - "avatar_url": "https://avatars.githubusercontent.com/u/19437824?" - }, - "repo": { - "id": 91394098, - "name": "keriwheatley/coursework", - "url": "https://api.github.com/repos/keriwheatley/coursework" - }, - "payload": { - "push_id": 1861573800, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "490f194beb4be216ed955d187aee265443dd532c", - "before": "14034277c8e715f9988686d85701b501845705e7", - "commits": [{ - "sha": "490f194beb4be216ed955d187aee265443dd532c", - "author": { - "email": "keri.wheatley@civitaslearning.com", - "name": "Keri Wheatley" - }, - "message": "updates to twitter_popularity", - "distinct": true, - "url": "https://api.github.com/repos/keriwheatley/coursework/commits/490f194beb4be216ed955d187aee265443dd532c" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z" - }, - { - "id": "6263117462", - "type": "CreateEvent", - "actor": { - "id": 12358972, - "login": "CodePipeline-Test", - "display_login": "CodePipeline-Test", - "gravatar_id": "", - "url": "https://api.github.com/users/CodePipeline-Test", - "avatar_url": "https://avatars.githubusercontent.com/u/12358972?" - }, - "repo": { - "id": 63971386, - "name": "CodePipeline-Test/feature-tests", - "url": "https://api.github.com/repos/CodePipeline-Test/feature-tests" - }, - "payload": { - "ref": "job-worker-features-V5zkpTEUgBlA4TOEJrWq", - "ref_type": "branch", - "master_branch": "master", - "description": "for feature tests", - "pusher_type": "user" - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z" - }, - { - "id": "6263117460", - "type": "WatchEvent", - "actor": { - "id": 9091565, - "login": "chiprunner1995", - "display_login": "chiprunner1995", - "gravatar_id": "", - "url": "https://api.github.com/users/chiprunner1995", - "avatar_url": "https://avatars.githubusercontent.com/u/9091565?" - }, - "repo": { - "id": 308512, - "name": "psake/psake", - "url": "https://api.github.com/repos/psake/psake" - }, - "payload": { - "action": "started" - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 1007585, - "login": "psake", - "gravatar_id": "", - "url": "https://api.github.com/orgs/psake", - "avatar_url": "https://avatars.githubusercontent.com/u/1007585?" - } - }, - { - "id": "6263117459", - "type": "PushEvent", - "actor": { - "id": 30199151, - "login": "Geoffers888", - "display_login": "Geoffers888", - "gravatar_id": "", - "url": "https://api.github.com/users/Geoffers888", - "avatar_url": "https://avatars.githubusercontent.com/u/30199151?" - }, - "repo": { - "id": 97330344, - "name": "Geoffers888/Console-Boxes", - "url": "https://api.github.com/repos/Geoffers888/Console-Boxes" - }, - "payload": { - "push_id": 1861573799, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "46f85052c269c7ede354a698e05e5ef5359bc71b", - "before": "ecb8a45cc1e49ee60ffa880eba8219b294ec44f5", - "commits": [{ - "sha": "46f85052c269c7ede354a698e05e5ef5359bc71b", - "author": { - "email": "geoff.cowin@gmail.com", - "name": "Geoffers888" - }, - "message": "Create README.md", - "distinct": true, - "url": "https://api.github.com/repos/Geoffers888/Console-Boxes/commits/46f85052c269c7ede354a698e05e5ef5359bc71b" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z" - }, - { - "id": "6263117454", - "type": "PushEvent", - "actor": { - "id": 8517910, - "login": "LombiqBot", - "display_login": "LombiqBot", - "gravatar_id": "", - "url": "https://api.github.com/users/LombiqBot", - "avatar_url": "https://avatars.githubusercontent.com/u/8517910?" - }, - "repo": { - "id": 46624662, - "name": "Lombiq/Orchard-External-Pages", - "url": "https://api.github.com/repos/Lombiq/Orchard-External-Pages" - }, - "payload": { - "push_id": 1861573796, - "size": 0, - "distinct_size": 0, - "ref": "refs/heads/issue/OSOE-7", - "head": "a630eb8494f07e6f11a5bc396a0829d5aa690c5f", - "before": "a630eb8494f07e6f11a5bc396a0829d5aa690c5f", - "commits": [ - - ] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 8158177, - "login": "Lombiq", - "gravatar_id": "", - "url": "https://api.github.com/orgs/Lombiq", - "avatar_url": "https://avatars.githubusercontent.com/u/8158177?" - } - }, - { - "id": "6263117451", - "type": "PullRequestEvent", - "actor": { - "id": 25966, - "login": "reconbot", - "display_login": "reconbot", - "gravatar_id": "", - "url": "https://api.github.com/users/reconbot", - "avatar_url": "https://avatars.githubusercontent.com/u/25966?" - }, - "repo": { - "id": 893522, - "name": "EmergingTechnologyAdvisors/node-serialport", - "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport" - }, - "payload": { - "action": "closed", - "number": 1235, - "pull_request": { - "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235", - "id": 130722112, - "html_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235", - "diff_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235.diff", - "patch_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235.patch", - "issue_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235", - "number": 1235, - "state": "closed", - "locked": false, - "title": "[unix] Move setting up the baudrate to the end of the open() to better support custom baudrates", - "user": { - "login": "reconbot", - "id": 25966, - "avatar_url": "https://avatars6.githubusercontent.com/u/25966?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/reconbot", - "html_url": "https://github.com/reconbot", - "followers_url": "https://api.github.com/users/reconbot/followers", - "following_url": "https://api.github.com/users/reconbot/following{/other_user}", - "gists_url": "https://api.github.com/users/reconbot/gists{/gist_id}", - "starred_url": "https://api.github.com/users/reconbot/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/reconbot/subscriptions", - "organizations_url": "https://api.github.com/users/reconbot/orgs", - "repos_url": "https://api.github.com/users/reconbot/repos", - "events_url": "https://api.github.com/users/reconbot/events{/privacy}", - "received_events_url": "https://api.github.com/users/reconbot/received_events", - "type": "User", - "site_admin": false - }, - "body": "- Test 1000000 baud\r\n\r\ncloses #1077", - "created_at": "2017-07-15T16:53:28Z", - "updated_at": "2017-07-15T17:06:45Z", - "closed_at": "2017-07-15T17:06:45Z", - "merged_at": "2017-07-15T17:06:45Z", - "merge_commit_sha": "9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a", - "assignee": null, - "assignees": [ - - ], - "requested_reviewers": [ - - ], - "milestone": null, - "commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/commits", - "review_comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/comments", - "review_comment_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/comments{/number}", - "comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235/comments", - "statuses_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/e57b3d685f6497ebe8669ce8b05894bacd895177", - "head": { - "label": "EmergingTechnologyAdvisors:1000000-baud", - "ref": "1000000-baud", - "sha": "e57b3d685f6497ebe8669ce8b05894bacd895177", - "user": { - "login": "EmergingTechnologyAdvisors", - "id": 8947774, - "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/EmergingTechnologyAdvisors", - "html_url": "https://github.com/EmergingTechnologyAdvisors", - "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", - "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", - "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", - "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", - "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", - "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", - "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", - "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", - "type": "Organization", - "site_admin": false - }, - "repo": { - "id": 893522, - "name": "node-serialport", - "full_name": "EmergingTechnologyAdvisors/node-serialport", - "owner": { - "login": "EmergingTechnologyAdvisors", - "id": 8947774, - "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/EmergingTechnologyAdvisors", - "html_url": "https://github.com/EmergingTechnologyAdvisors", - "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", - "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", - "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", - "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", - "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", - "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", - "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", - "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", - "type": "Organization", - "site_admin": false - }, - "private": false, - "html_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", - "description": "Node.js package to access serial ports for reading and writing. Welcome your robotic JavaScript overlords. Better yet, program them!", - "fork": false, - "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport", - "forks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/forks", - "keys_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/teams", - "hooks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/hooks", - "issue_events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/events{/number}", - "events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/events", - "assignees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/assignees{/user}", - "branches_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/branches{/branch}", - "tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/tags", - "blobs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/{sha}", - "languages_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/languages", - "stargazers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/stargazers", - "contributors_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contributors", - "subscribers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscribers", - "subscription_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscription", - "commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contents/{+path}", - "compare_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/merges", - "archive_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/downloads", - "issues_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues{/number}", - "pulls_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls{/number}", - "milestones_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/milestones{/number}", - "notifications_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/labels{/name}", - "releases_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/releases{/id}", - "deployments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/deployments", - "created_at": "2010-09-07T12:24:28Z", - "updated_at": "2017-07-14T16:30:58Z", - "pushed_at": "2017-07-15T17:06:45Z", - "git_url": "git://github.com/EmergingTechnologyAdvisors/node-serialport.git", - "ssh_url": "git@github.com:EmergingTechnologyAdvisors/node-serialport.git", - "clone_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport.git", - "svn_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", - "homepage": "", - "size": 1914, - "stargazers_count": 2829, - "watchers_count": 2829, - "language": "JavaScript", - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": false, - "has_pages": true, - "forks_count": 601, - "mirror_url": null, - "open_issues_count": 30, - "forks": 601, - "open_issues": 30, - "watchers": 2829, - "default_branch": "master" - } - }, - "base": { - "label": "EmergingTechnologyAdvisors:master", - "ref": "master", - "sha": "ee7315f59c7698811f4f76405383f18680843926", - "user": { - "login": "EmergingTechnologyAdvisors", - "id": 8947774, - "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/EmergingTechnologyAdvisors", - "html_url": "https://github.com/EmergingTechnologyAdvisors", - "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", - "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", - "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", - "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", - "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", - "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", - "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", - "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", - "type": "Organization", - "site_admin": false - }, - "repo": { - "id": 893522, - "name": "node-serialport", - "full_name": "EmergingTechnologyAdvisors/node-serialport", - "owner": { - "login": "EmergingTechnologyAdvisors", - "id": 8947774, - "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/EmergingTechnologyAdvisors", - "html_url": "https://github.com/EmergingTechnologyAdvisors", - "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", - "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", - "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", - "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", - "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", - "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", - "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", - "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", - "type": "Organization", - "site_admin": false - }, - "private": false, - "html_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", - "description": "Node.js package to access serial ports for reading and writing. Welcome your robotic JavaScript overlords. Better yet, program them!", - "fork": false, - "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport", - "forks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/forks", - "keys_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/keys{/key_id}", - "collaborators_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/collaborators{/collaborator}", - "teams_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/teams", - "hooks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/hooks", - "issue_events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/events{/number}", - "events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/events", - "assignees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/assignees{/user}", - "branches_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/branches{/branch}", - "tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/tags", - "blobs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/blobs{/sha}", - "git_tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/tags{/sha}", - "git_refs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/refs{/sha}", - "trees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/trees{/sha}", - "statuses_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/{sha}", - "languages_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/languages", - "stargazers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/stargazers", - "contributors_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contributors", - "subscribers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscribers", - "subscription_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscription", - "commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/commits{/sha}", - "git_commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/commits{/sha}", - "comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/comments{/number}", - "issue_comment_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/comments{/number}", - "contents_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contents/{+path}", - "compare_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/compare/{base}...{head}", - "merges_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/merges", - "archive_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/{archive_format}{/ref}", - "downloads_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/downloads", - "issues_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues{/number}", - "pulls_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls{/number}", - "milestones_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/milestones{/number}", - "notifications_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/notifications{?since,all,participating}", - "labels_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/labels{/name}", - "releases_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/releases{/id}", - "deployments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/deployments", - "created_at": "2010-09-07T12:24:28Z", - "updated_at": "2017-07-14T16:30:58Z", - "pushed_at": "2017-07-15T17:06:45Z", - "git_url": "git://github.com/EmergingTechnologyAdvisors/node-serialport.git", - "ssh_url": "git@github.com:EmergingTechnologyAdvisors/node-serialport.git", - "clone_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport.git", - "svn_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", - "homepage": "", - "size": 1914, - "stargazers_count": 2829, - "watchers_count": 2829, - "language": "JavaScript", - "has_issues": true, - "has_projects": true, - "has_downloads": true, - "has_wiki": false, - "has_pages": true, - "forks_count": 601, - "mirror_url": null, - "open_issues_count": 30, - "forks": 601, - "open_issues": 30, - "watchers": 2829, - "default_branch": "master" - } - }, - "_links": { - "self": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235" - }, - "html": { - "href": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235" - }, - "issue": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235" - }, - "comments": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235/comments" - }, - "review_comments": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/comments" - }, - "review_comment": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/comments{/number}" - }, - "commits": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/commits" - }, - "statuses": { - "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/e57b3d685f6497ebe8669ce8b05894bacd895177" - } - }, - "merged": true, - "mergeable": null, - "rebaseable": null, - "mergeable_state": "unknown", - "merged_by": { - "login": "reconbot", - "id": 25966, - "avatar_url": "https://avatars6.githubusercontent.com/u/25966?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/reconbot", - "html_url": "https://github.com/reconbot", - "followers_url": "https://api.github.com/users/reconbot/followers", - "following_url": "https://api.github.com/users/reconbot/following{/other_user}", - "gists_url": "https://api.github.com/users/reconbot/gists{/gist_id}", - "starred_url": "https://api.github.com/users/reconbot/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/reconbot/subscriptions", - "organizations_url": "https://api.github.com/users/reconbot/orgs", - "repos_url": "https://api.github.com/users/reconbot/repos", - "events_url": "https://api.github.com/users/reconbot/events{/privacy}", - "received_events_url": "https://api.github.com/users/reconbot/received_events", - "type": "User", - "site_admin": false - }, - "comments": 0, - "review_comments": 0, - "maintainer_can_modify": false, - "commits": 1, - "additions": 24, - "deletions": 14, - "changed_files": 2 - } - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z", - "org": { - "id": 8947774, - "login": "EmergingTechnologyAdvisors", - "gravatar_id": "", - "url": "https://api.github.com/orgs/EmergingTechnologyAdvisors", - "avatar_url": "https://avatars.githubusercontent.com/u/8947774?" - } - }, - { - "id": "6263117447", - "type": "PushEvent", - "actor": { - "id": 11887843, - "login": "trimox", - "display_login": "trimox", - "gravatar_id": "", - "url": "https://api.github.com/users/trimox", - "avatar_url": "https://avatars.githubusercontent.com/u/11887843?" - }, - "repo": { - "id": 88184430, - "name": "trimox/angular-mdc-web", - "url": "https://api.github.com/repos/trimox/angular-mdc-web" - }, - "payload": { - "push_id": 1861573792, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "59de0a8bfb229e7e72a1960132fdf24f0a770a08", - "before": "27327b3a3cb4e58ddb1b1188cb0f04092d850106", - "commits": [{ - "sha": "59de0a8bfb229e7e72a1960132fdf24f0a770a08", - "author": { - "email": "trimoxal@gmail.com", - "name": "Dominic Carretto" - }, - "message": "fix(snackbar): Fix actionHandler still required if actionText is empty", - "distinct": true, - "url": "https://api.github.com/repos/trimox/angular-mdc-web/commits/59de0a8bfb229e7e72a1960132fdf24f0a770a08" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:46Z" - }, - { - "id": "6263117445", - "type": "WatchEvent", - "actor": { - "id": 1006434, - "login": "enorrmann", - "display_login": "enorrmann", - "gravatar_id": "", - "url": "https://api.github.com/users/enorrmann", - "avatar_url": "https://avatars.githubusercontent.com/u/1006434?" - }, - "repo": { - "id": 14699489, - "name": "walmik/scribbletune", - "url": "https://api.github.com/repos/walmik/scribbletune" - }, - "payload": { - "action": "started" - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117444", - "type": "PushEvent", - "actor": { - "id": 24412103, - "login": "james341", - "display_login": "james341", - "gravatar_id": "", - "url": "https://api.github.com/users/james341", - "avatar_url": "https://avatars.githubusercontent.com/u/24412103?" - }, - "repo": { - "id": 96979484, - "name": "james341/loading-yan-rp", - "url": "https://api.github.com/repos/james341/loading-yan-rp" - }, - "payload": { - "push_id": 1861573791, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "16bb35eb4a43d916a40155996c9d7dfadb007573", - "before": "ad4b96a5b924783e42d1d0cbf0fd1b5cba3cbd2f", - "commits": [{ - "sha": "16bb35eb4a43d916a40155996c9d7dfadb007573", - "author": { - "email": "taine049@gmail.com", - "name": "james341" - }, - "message": "Add files via upload", - "distinct": true, - "url": "https://api.github.com/repos/james341/loading-yan-rp/commits/16bb35eb4a43d916a40155996c9d7dfadb007573" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117441", - "type": "PushEvent", - "actor": { - "id": 4676211, - "login": "kanke", - "display_login": "kanke", - "gravatar_id": "", - "url": "https://api.github.com/users/kanke", - "avatar_url": "https://avatars.githubusercontent.com/u/4676211?" - }, - "repo": { - "id": 97262451, - "name": "kanke/RedisServerClone", - "url": "https://api.github.com/repos/kanke/RedisServerClone" - }, - "payload": { - "push_id": 1861573790, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "e6312819f0acdc40008b06ae7a2c6c211c2f1db0", - "before": "f9a4fe7e866181c74fbc9352310fbc6c539d2aff", - "commits": [{ - "sha": "e6312819f0acdc40008b06ae7a2c6c211c2f1db0", - "author": { - "email": "sugarkanke@yahoo.com", - "name": "Kanke" - }, - "message": "Adding gitignore and readme.md content. Code cleanup.", - "distinct": true, - "url": "https://api.github.com/repos/kanke/RedisServerClone/commits/e6312819f0acdc40008b06ae7a2c6c211c2f1db0" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117440", - "type": "PushEvent", - "actor": { - "id": 16622965, - "login": "jainhitesh9998", - "display_login": "jainhitesh9998", - "gravatar_id": "", - "url": "https://api.github.com/users/jainhitesh9998", - "avatar_url": "https://avatars.githubusercontent.com/u/16622965?" - }, - "repo": { - "id": 94244445, - "name": "jainhitesh9998/WebDevelopment", - "url": "https://api.github.com/repos/jainhitesh9998/WebDevelopment" - }, - "payload": { - "push_id": 1861573789, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "9e3c3f5f437fbc1f21a30f19f764787b86a393be", - "before": "d69d496b80a5806406f2313d67e63f3adf61b97e", - "commits": [{ - "sha": "9e3c3f5f437fbc1f21a30f19f764787b86a393be", - "author": { - "email": "jainhitesh9998@gmail.com", - "name": "Hitesh C" - }, - "message": "added sounds for the clone", - "distinct": true, - "url": "https://api.github.com/repos/jainhitesh9998/WebDevelopment/commits/9e3c3f5f437fbc1f21a30f19f764787b86a393be" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117437", - "type": "PushEvent", - "actor": { - "id": 1491646, - "login": "MikroAcse", - "display_login": "MikroAcse", - "gravatar_id": "", - "url": "https://api.github.com/users/MikroAcse", - "avatar_url": "https://avatars.githubusercontent.com/u/1491646?" - }, - "repo": { - "id": 96892535, - "name": "MikroAcse/VariousTelegramBots", - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots" - }, - "payload": { - "push_id": 1861573788, - "size": 11, - "distinct_size": 11, - "ref": "refs/heads/dev", - "head": "7ef25bf6aad45c9da53a2d5918e553c68cd69dd4", - "before": "931cef7db8ec69cc951fe8a5ecc2b909397e29a4", - "commits": [{ - "sha": "88b9e4e53f62ff7c9597f66d9e45a0a9be5fe1ca", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "upgrade Node.js version", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/88b9e4e53f62ff7c9597f66d9e45a0a9be5fe1ca" - }, - { - "sha": "d5b91bac58a8c3b88ddd9634578cb3beebb31015", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Update Node js version", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/d5b91bac58a8c3b88ddd9634578cb3beebb31015" - }, - { - "sha": "37cd86961e36e64c8ccd7873bbccc200b920d308", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Fix", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/37cd86961e36e64c8ccd7873bbccc200b920d308" - }, - { - "sha": "471451fd46b9bed62eef062553f480e788c24a3c", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Merge branch 'master' into dev\n\n# Conflicts:\n#\tapp.js", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/471451fd46b9bed62eef062553f480e788c24a3c" - }, - { - "sha": "8f5be591fae47f1ff051f992176faeed8fe3c2d7", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Removed unnecessary dependency and updated README.md", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/8f5be591fae47f1ff051f992176faeed8fe3c2d7" - }, - { - "sha": "d239750fbb26f13daf50a14e1c4a23375df9c5d9", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Update README", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/d239750fbb26f13daf50a14e1c4a23375df9c5d9" - }, - { - "sha": "94adaefc2b4107db89cdbc045a6a106724f12a2d", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Fix in readme", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/94adaefc2b4107db89cdbc045a6a106724f12a2d" - }, - { - "sha": "da8009c4da182c036efbc7a8e9d9353d1282d5ed", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Added version to readme", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/da8009c4da182c036efbc7a8e9d9353d1282d5ed" - }, - { - "sha": "1590092c64e774633040419b69d60d98197ddbde", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Removed requirement of deleted dependency", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/1590092c64e774633040419b69d60d98197ddbde" - }, - { - "sha": "1986905b1d32654a20916fafc60c7484ff85841a", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Yes or no in ChooseBot, slight changes in QuoteBot regexp", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/1986905b1d32654a20916fafc60c7484ff85841a" - }, - { - "sha": "7ef25bf6aad45c9da53a2d5918e553c68cd69dd4", - "author": { - "email": "mike.kroace@gmail.com", - "name": "Vitaly Rudenko" - }, - "message": "Merge commit '1986905b1d32654a20916fafc60c7484ff85841a' into dev", - "distinct": true, - "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/7ef25bf6aad45c9da53a2d5918e553c68cd69dd4" - } - ] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117435", - "type": "PushEvent", - "actor": { - "id": 12949454, - "login": "jarifibrahim", - "display_login": "jarifibrahim", - "gravatar_id": "", - "url": "https://api.github.com/users/jarifibrahim", - "avatar_url": "https://avatars.githubusercontent.com/u/12949454?" - }, - "repo": { - "id": 93039796, - "name": "jarifibrahim/OpenSourceHelpCommunity.github.io", - "url": "https://api.github.com/repos/jarifibrahim/OpenSourceHelpCommunity.github.io" - }, - "payload": { - "push_id": 1861573787, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/issue-4", - "head": "4b7341d9b7bb95f5f0e1d50831a9c978fc4fceb4", - "before": "57c0a65ee93de1955ad5691585a51c358188f311", - "commits": [{ - "sha": "4b7341d9b7bb95f5f0e1d50831a9c978fc4fceb4", - "author": { - "email": "jarifibrahim@gmail.com", - "name": "Ibrahim Jarif" - }, - "message": "Add travs.yml", - "distinct": true, - "url": "https://api.github.com/repos/jarifibrahim/OpenSourceHelpCommunity.github.io/commits/4b7341d9b7bb95f5f0e1d50831a9c978fc4fceb4" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117430", - "type": "IssueCommentEvent", - "actor": { - "id": 849609, - "login": "wrrn", - "display_login": "wrrn", - "gravatar_id": "", - "url": "https://api.github.com/users/wrrn", - "avatar_url": "https://avatars.githubusercontent.com/u/849609?" - }, - "repo": { - "id": 23096959, - "name": "golang/go", - "url": "https://api.github.com/repos/golang/go" - }, - "payload": { - "action": "created", - "issue": { - "url": "https://api.github.com/repos/golang/go/issues/21017", - "repository_url": "https://api.github.com/repos/golang/go", - "labels_url": "https://api.github.com/repos/golang/go/issues/21017/labels{/name}", - "comments_url": "https://api.github.com/repos/golang/go/issues/21017/comments", - "events_url": "https://api.github.com/repos/golang/go/issues/21017/events", - "html_url": "https://github.com/golang/go/issues/21017", - "id": 243177572, - "number": 21017, - "title": "Gophercon: Contributor Workshop Registration", - "user": { - "login": "jessfraz", - "id": 1445228, - "avatar_url": "https://avatars6.githubusercontent.com/u/1445228?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/jessfraz", - "html_url": "https://github.com/jessfraz", - "followers_url": "https://api.github.com/users/jessfraz/followers", - "following_url": "https://api.github.com/users/jessfraz/following{/other_user}", - "gists_url": "https://api.github.com/users/jessfraz/gists{/gist_id}", - "starred_url": "https://api.github.com/users/jessfraz/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/jessfraz/subscriptions", - "organizations_url": "https://api.github.com/users/jessfraz/orgs", - "repos_url": "https://api.github.com/users/jessfraz/repos", - "events_url": "https://api.github.com/users/jessfraz/events{/privacy}", - "received_events_url": "https://api.github.com/users/jessfraz/received_events", - "type": "User", - "site_admin": false - }, - "labels": [{ - "id": 150880243, - "url": "https://api.github.com/repos/golang/go/labels/HelpWanted", - "name": "HelpWanted", - "color": "fbca04", - "default": false - }], - "state": "open", - "locked": false, - "assignee": null, - "assignees": [ - - ], - "milestone": { - "url": "https://api.github.com/repos/golang/go/milestones/22", - "html_url": "https://github.com/golang/go/milestone/22", - "labels_url": "https://api.github.com/repos/golang/go/milestones/22/labels", - "id": 1067491, - "number": 22, - "title": "Unreleased", - "description": "Issues that do not affect released Go code and binaries.\r\n", - "creator": { - "login": "rsc", - "id": 104030, - "avatar_url": "https://avatars5.githubusercontent.com/u/104030?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/rsc", - "html_url": "https://github.com/rsc", - "followers_url": "https://api.github.com/users/rsc/followers", - "following_url": "https://api.github.com/users/rsc/following{/other_user}", - "gists_url": "https://api.github.com/users/rsc/gists{/gist_id}", - "starred_url": "https://api.github.com/users/rsc/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/rsc/subscriptions", - "organizations_url": "https://api.github.com/users/rsc/orgs", - "repos_url": "https://api.github.com/users/rsc/repos", - "events_url": "https://api.github.com/users/rsc/events{/privacy}", - "received_events_url": "https://api.github.com/users/rsc/received_events", - "type": "User", - "site_admin": false - }, - "open_issues": 707, - "closed_issues": 918, - "state": "open", - "created_at": "2015-04-14T18:48:22Z", - "updated_at": "2017-07-15T17:06:04Z", - "due_on": "2099-12-31T08:00:00Z", - "closed_at": null - }, - "comments": 14, - "created_at": "2017-07-15T14:13:29Z", - "updated_at": "2017-07-15T17:06:43Z", - "closed_at": null, - "body": "Please do not comment here until the Contributor Workshop begins.\r\n\r\nDuring the workshop leave a comment with your Gerritt profile ID here." - }, - "comment": { - "url": "https://api.github.com/repos/golang/go/issues/comments/315547934", - "html_url": "https://github.com/golang/go/issues/21017#issuecomment-315547934", - "issue_url": "https://api.github.com/repos/golang/go/issues/21017", - "id": 315547934, - "user": { - "login": "wrrn", - "id": 849609, - "avatar_url": "https://avatars7.githubusercontent.com/u/849609?v=4", - "gravatar_id": "", - "url": "https://api.github.com/users/wrrn", - "html_url": "https://github.com/wrrn", - "followers_url": "https://api.github.com/users/wrrn/followers", - "following_url": "https://api.github.com/users/wrrn/following{/other_user}", - "gists_url": "https://api.github.com/users/wrrn/gists{/gist_id}", - "starred_url": "https://api.github.com/users/wrrn/starred{/owner}{/repo}", - "subscriptions_url": "https://api.github.com/users/wrrn/subscriptions", - "organizations_url": "https://api.github.com/users/wrrn/orgs", - "repos_url": "https://api.github.com/users/wrrn/repos", - "events_url": "https://api.github.com/users/wrrn/events{/privacy}", - "received_events_url": "https://api.github.com/users/wrrn/received_events", - "type": "User", - "site_admin": false - }, - "created_at": "2017-07-15T17:06:43Z", - "updated_at": "2017-07-15T17:06:43Z", - "body": "22590" - } - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z", - "org": { - "id": 4314092, - "login": "golang", - "gravatar_id": "", - "url": "https://api.github.com/orgs/golang", - "avatar_url": "https://avatars.githubusercontent.com/u/4314092?" - } - }, - { - "id": "6263117428", - "type": "PushEvent", - "actor": { - "id": 6938676, - "login": "Ordinastie", - "display_login": "Ordinastie", - "gravatar_id": "", - "url": "https://api.github.com/users/Ordinastie", - "avatar_url": "https://avatars.githubusercontent.com/u/6938676?" - }, - "repo": { - "id": 17756561, - "name": "Ordinastie/MalisisDoors", - "url": "https://api.github.com/repos/Ordinastie/MalisisDoors" - }, - "payload": { - "push_id": 1861573783, - "size": 2, - "distinct_size": 2, - "ref": "refs/heads/1.12", - "head": "07334b1700ec9cd173c7560f293b7dd10dc24fd9", - "before": "ee8e1058833056afdcac559c22518b3706b3657f", - "commits": [{ - "sha": "52080012d79ae0320392379b5d054f3e17ec1b98", - "author": { - "email": "ordinastie@hotmail.com", - "name": "Ordinastie" - }, - "message": "Fixed getRegistryType()", - "distinct": true, - "url": "https://api.github.com/repos/Ordinastie/MalisisDoors/commits/52080012d79ae0320392379b5d054f3e17ec1b98" - }, - { - "sha": "07334b1700ec9cd173c7560f293b7dd10dc24fd9", - "author": { - "email": "ordinastie@hotmail.com", - "name": "Ordinastie" - }, - "message": "Updated forgegradle and curseforge version", - "distinct": true, - "url": "https://api.github.com/repos/Ordinastie/MalisisDoors/commits/07334b1700ec9cd173c7560f293b7dd10dc24fd9" - } - ] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117427", - "type": "DeleteEvent", - "actor": { - "id": 227909, - "login": "amcdnl", - "display_login": "amcdnl", - "gravatar_id": "", - "url": "https://api.github.com/users/amcdnl", - "avatar_url": "https://avatars.githubusercontent.com/u/227909?" - }, - "repo": { - "id": 94944874, - "name": "amcdnl/material2", - "url": "https://api.github.com/repos/amcdnl/material2" - }, - "payload": { - "ref": "autocomplete-demos", - "ref_type": "branch", - "pusher_type": "user" - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - }, - { - "id": "6263117426", - "type": "PushEvent", - "actor": { - "id": 16347325, - "login": "zxui", - "display_login": "zxui", - "gravatar_id": "", - "url": "https://api.github.com/users/zxui", - "avatar_url": "https://avatars.githubusercontent.com/u/16347325?" - }, - "repo": { - "id": 88623154, - "name": "zxui/auto-admin", - "url": "https://api.github.com/repos/zxui/auto-admin" - }, - "payload": { - "push_id": 1861573782, - "size": 1, - "distinct_size": 1, - "ref": "refs/heads/master", - "head": "70d47755fde8a5c4cfde101ba65caa6c1d6fcdb2", - "before": "f673e6b191197827bddb31bcffea61611e8a50b0", - "commits": [{ - "sha": "70d47755fde8a5c4cfde101ba65caa6c1d6fcdb2", - "author": { - "email": "zxshen@qq.com", - "name": "zxui" - }, - "message": "update", - "distinct": true, - "url": "https://api.github.com/repos/zxui/auto-admin/commits/70d47755fde8a5c4cfde101ba65caa6c1d6fcdb2" - }] - }, - "public": true, - "created_at": "2017-07-15T17:06:45Z" - } - ] +[ + { + "id": "6263117491", + "type": "PushEvent", + "actor": { + "id": 12358972, + "login": "CodePipeline-Test", + "display_login": "CodePipeline-Test", + "gravatar_id": "", + "url": "https://api.github.com/users/CodePipeline-Test", + "avatar_url": "https://avatars.githubusercontent.com/u/12358972?" + }, + "repo": { + "id": 63971386, + "name": "CodePipeline-Test/feature-tests", + "url": "https://api.github.com/repos/CodePipeline-Test/feature-tests" + }, + "payload": { + "push_id": 1861573815, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/job-worker-features-V5zkpTEUgBlA4TOEJrWq", + "head": "f283b1955dd88fe65210c842e63408d5ad30d322", + "before": "873d322eb50db0068ae3d0ea2e79cee345e31c93", + "commits": [ + { + "sha": "f283b1955dd88fe65210c842e63408d5ad30d322", + "author": { + "email": "CodePipeline-Test@users.noreply.github.com", + "name": "CodePipeline-Test" + }, + "message": "Test commit", + "distinct": true, + "url": "https://api.github.com/repos/CodePipeline-Test/feature-tests/commits/f283b1955dd88fe65210c842e63408d5ad30d322" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z" + }, + { + "id": "6263117489", + "type": "PushEvent", + "actor": { + "id": 16156445, + "login": "JonnyPickard", + "display_login": "JonnyPickard", + "gravatar_id": "", + "url": "https://api.github.com/users/JonnyPickard", + "avatar_url": "https://avatars.githubusercontent.com/u/16156445?" + }, + "repo": { + "id": 97318059, + "name": "JonnyPickard/albums-react-native", + "url": "https://api.github.com/repos/JonnyPickard/albums-react-native" + }, + "payload": { + "push_id": 1861573814, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "a11c7aedf4f1800357864302fe08fc277e9e8652", + "before": "d33e7adbb46926d1d4030d0c855b245062f1d9b5", + "commits": [ + { + "sha": "a11c7aedf4f1800357864302fe08fc277e9e8652", + "author": { + "email": "jonathandpickard@gmail.com", + "name": "Jonny Pickard" + }, + "message": "Add basic server to send JSON", + "distinct": true, + "url": "https://api.github.com/repos/JonnyPickard/albums-react-native/commits/a11c7aedf4f1800357864302fe08fc277e9e8652" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z" + }, + { + "id": "6263117487", + "type": "IssueCommentEvent", + "actor": { + "id": 4236651, + "login": "0x53A", + "display_login": "0x53A", + "gravatar_id": "", + "url": "https://api.github.com/users/0x53A", + "avatar_url": "https://avatars.githubusercontent.com/u/4236651?" + }, + "repo": { + "id": 29048891, + "name": "Microsoft/visualfsharp", + "url": "https://api.github.com/repos/Microsoft/visualfsharp" + }, + "payload": { + "action": "created", + "issue": { + "url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335", + "repository_url": "https://api.github.com/repos/Microsoft/visualfsharp", + "labels_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335/labels{/name}", + "comments_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335/comments", + "events_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335/events", + "html_url": "https://github.com/Microsoft/visualfsharp/issues/3335", + "id": 243089775, + "number": 3335, + "title": "[15.3 pre] loading in VS / publish fails if FSharp.Compiler.Tools is imported", + "user": { + "login": "0x53A", + "id": 4236651, + "avatar_url": "https://avatars7.githubusercontent.com/u/4236651?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/0x53A", + "html_url": "https://github.com/0x53A", + "followers_url": "https://api.github.com/users/0x53A/followers", + "following_url": "https://api.github.com/users/0x53A/following{/other_user}", + "gists_url": "https://api.github.com/users/0x53A/gists{/gist_id}", + "starred_url": "https://api.github.com/users/0x53A/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/0x53A/subscriptions", + "organizations_url": "https://api.github.com/users/0x53A/orgs", + "repos_url": "https://api.github.com/users/0x53A/repos", + "events_url": "https://api.github.com/users/0x53A/events{/privacy}", + "received_events_url": "https://api.github.com/users/0x53A/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 308803045, + "url": "https://api.github.com/repos/Microsoft/visualfsharp/labels/Area-CoreCLR", + "name": "Area-CoreCLR", + "color": "5319e7", + "default": false + } + ], + "state": "closed", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": { + "url": "https://api.github.com/repos/Microsoft/visualfsharp/milestones/9", + "html_url": "https://github.com/Microsoft/visualfsharp/milestone/9", + "labels_url": "https://api.github.com/repos/Microsoft/visualfsharp/milestones/9/labels", + "id": 2233574, + "number": 9, + "title": "VS 2017 Updates", + "description": "This milestone is for any bug, new feature, or improvement which makes it into a later VS 2017 update.", + "creator": { + "login": "cartermp", + "id": 6309070, + "avatar_url": "https://avatars4.githubusercontent.com/u/6309070?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/cartermp", + "html_url": "https://github.com/cartermp", + "followers_url": "https://api.github.com/users/cartermp/followers", + "following_url": "https://api.github.com/users/cartermp/following{/other_user}", + "gists_url": "https://api.github.com/users/cartermp/gists{/gist_id}", + "starred_url": "https://api.github.com/users/cartermp/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/cartermp/subscriptions", + "organizations_url": "https://api.github.com/users/cartermp/orgs", + "repos_url": "https://api.github.com/users/cartermp/repos", + "events_url": "https://api.github.com/users/cartermp/events{/privacy}", + "received_events_url": "https://api.github.com/users/cartermp/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 55, + "closed_issues": 158, + "state": "open", + "created_at": "2017-01-06T17:42:02Z", + "updated_at": "2017-07-15T00:13:34Z", + "due_on": null, + "closed_at": null + }, + "comments": 29, + "created_at": "2017-07-14T19:28:04Z", + "updated_at": "2017-07-15T17:06:46Z", + "closed_at": "2017-07-15T00:13:33Z", + "body": "\r\nEdit2: everything works, thanks @KevinRansom \r\n\r\n_Edited_\r\n\r\nI have tried to test if / how a project using paket works in the new world of ``dotnet 2``, comparing C#, F#, and the previous F# sdk (FSharp.NET.Sdk). I have also tested if using F# without paket works.\r\n\r\nHere are four branches, one for each test: https://github.com/0x53A/dotnet-tests.\r\n\r\nResults:\r\n\r\n* paket works with C# and ``Microsoft.NET.Sdk``: https://github.com/0x53A/dotnet-tests/tree/csharp+paket\r\n* paket works with F# when using the 1.x sdk (``FSharp.NET.Sdk``): https://github.com/0x53A/dotnet-tests/tree/fsharp+paket+FSharp.NET.Sdk\r\n* paket ~does NOT~ does work with F# and ``Microsoft.NET.Sdk``: https://github.com/0x53A/dotnet-tests/tree/fsharp+paket\r\n* using F# with ``Microsoft.NET.Sdk`` and nuget does work: https://github.com/0x53A/dotnet-tests/tree/fsharp+nuget\r\n\r\nThe paket version I have tested this with is ``5.6.12``.\r\n\r\nIt is kind of funny that C# seems to work flawlessly with paket." + }, + "comment": { + "url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/comments/315547940", + "html_url": "https://github.com/Microsoft/visualfsharp/issues/3335#issuecomment-315547940", + "issue_url": "https://api.github.com/repos/Microsoft/visualfsharp/issues/3335", + "id": 315547940, + "user": { + "login": "0x53A", + "id": 4236651, + "avatar_url": "https://avatars7.githubusercontent.com/u/4236651?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/0x53A", + "html_url": "https://github.com/0x53A", + "followers_url": "https://api.github.com/users/0x53A/followers", + "following_url": "https://api.github.com/users/0x53A/following{/other_user}", + "gists_url": "https://api.github.com/users/0x53A/gists{/gist_id}", + "starred_url": "https://api.github.com/users/0x53A/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/0x53A/subscriptions", + "organizations_url": "https://api.github.com/users/0x53A/orgs", + "repos_url": "https://api.github.com/users/0x53A/repos", + "events_url": "https://api.github.com/users/0x53A/events{/privacy}", + "received_events_url": "https://api.github.com/users/0x53A/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2017-07-15T17:06:46Z", + "updated_at": "2017-07-15T17:06:46Z", + "body": "3) DisableImplicitFSharpCoreReference and paket\r\n\r\npaket.dependencies:\r\n\r\n```nuget FSharp.Core 4.0.0.1```\r\n\r\n```Xml\r\n\r\n \r\n net461\r\n true\r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n```\r\n\r\n=>\r\n\r\n```\r\nC:\\source\\dotnet-tests>dotnet publish\r\nMicrosoft (R) Build Engine version 15.3.406.54721 for .NET Core\r\nCopyright (C) Microsoft Corporation. All rights reserved.\r\n\r\nC:\\source\\dotnet-tests\\Library.fs(7,17): error FS0039: The value, namespace, type or module 'Result' is not defined. [C:\\source\\dotnet-tests\\paket-fsharp-test.fsproj]\r\nC:\\source\\dotnet-tests\\Library.fs(8,42): error FS0039: The pattern discriminator 'Ok' is not defined. [C:\\source\\dotnet-tests\\paket-fsharp-test.fsproj]\r\n```\r\n\r\nwhich is good.\r\n\r\n-----------------\r\n\r\nSo it looks like both properties work as expected. It seems that in __2)__ the compiler automagically referenced some FSharp.Core, because none was explicitly referenced." + } + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z", + "org": { + "id": 6154722, + "login": "Microsoft", + "gravatar_id": "", + "url": "https://api.github.com/orgs/Microsoft", + "avatar_url": "https://avatars.githubusercontent.com/u/6154722?" + } + }, + { + "id": "6263117486", + "type": "PushEvent", + "actor": { + "id": 982267, + "login": "gxela", + "display_login": "gxela", + "gravatar_id": "", + "url": "https://api.github.com/users/gxela", + "avatar_url": "https://avatars.githubusercontent.com/u/982267?" + }, + "repo": { + "id": 97197951, + "name": "AudioBible/AudioBible.life", + "url": "https://api.github.com/repos/AudioBible/AudioBible.life" + }, + "payload": { + "push_id": 1861573811, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "31e079597959be78850e06c623383d522f8fe283", + "before": "11d32ac0eb7051ddc7da05dab183f10ed861fa61", + "commits": [ + { + "sha": "31e079597959be78850e06c623383d522f8fe283", + "author": { + "email": "alex@goretoy.com", + "name": "Alex Goretoy" + }, + "message": "update", + "distinct": true, + "url": "https://api.github.com/repos/AudioBible/AudioBible.life/commits/31e079597959be78850e06c623383d522f8fe283" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z", + "org": { + "id": 29329308, + "login": "AudioBible", + "gravatar_id": "", + "url": "https://api.github.com/orgs/AudioBible", + "avatar_url": "https://avatars.githubusercontent.com/u/29329308?" + } + }, + { + "id": "6263117481", + "type": "CreateEvent", + "actor": { + "id": 998519, + "login": "martinstabe", + "display_login": "martinstabe", + "gravatar_id": "", + "url": "https://api.github.com/users/martinstabe", + "avatar_url": "https://avatars.githubusercontent.com/u/998519?" + }, + "repo": { + "id": 90621389, + "name": "ft-interactive/archive", + "url": "https://api.github.com/repos/ft-interactive/archive" + }, + "payload": { + "ref": "personal-data", + "ref_type": "branch", + "master_branch": "master", + "description": "Refactored versions of a few older FT interactive stories", + "pusher_type": "user" + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z", + "org": { + "id": 2511089, + "login": "ft-interactive", + "gravatar_id": "", + "url": "https://api.github.com/orgs/ft-interactive", + "avatar_url": "https://avatars.githubusercontent.com/u/2511089?" + } + }, + { + "id": "6263117480", + "type": "PushEvent", + "actor": { + "id": 30200303, + "login": "musikdusche", + "display_login": "musikdusche", + "gravatar_id": "", + "url": "https://api.github.com/users/musikdusche", + "avatar_url": "https://avatars.githubusercontent.com/u/30200303?" + }, + "repo": { + "id": 97330240, + "name": "musikdusche/hello-world", + "url": "https://api.github.com/repos/musikdusche/hello-world" + }, + "payload": { + "push_id": 1861573809, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/readmeworks", + "head": "e09f4ef810382578be4ba49bcc351c94ac8b15f9", + "before": "10f052d3f22eaad13302b5e0e6d1a4af77a73f91", + "commits": [ + { + "sha": "e09f4ef810382578be4ba49bcc351c94ac8b15f9", + "author": { + "email": "f.toens@gmx.de", + "name": "musikdusche" + }, + "message": "Update README.md\n\ntrying out markdown syntaxes", + "distinct": true, + "url": "https://api.github.com/repos/musikdusche/hello-world/commits/e09f4ef810382578be4ba49bcc351c94ac8b15f9" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z" + }, + { + "id": "6263117478", + "type": "PushEvent", + "actor": { + "id": 4712642, + "login": "neu-rah", + "display_login": "neu-rah", + "gravatar_id": "", + "url": "https://api.github.com/users/neu-rah", + "avatar_url": "https://avatars.githubusercontent.com/u/4712642?" + }, + "repo": { + "id": 23024191, + "name": "neu-rah/ArduinoMenu", + "url": "https://api.github.com/repos/neu-rah/ArduinoMenu" + }, + "payload": { + "push_id": 1861573808, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "1557e3155279ca19e35048f8a6758189cbb2231a", + "before": "fb1b8c70b324bf73231728a708fe496991c51607", + "commits": [ + { + "sha": "1557e3155279ca19e35048f8a6758189cbb2231a", + "author": { + "email": "ruihfazevedo@gmail.com", + "name": "Rui Azevedo" + }, + "message": "remove pin collision between encoder and serial on I2C example as noted by Paul Gaertner", + "distinct": true, + "url": "https://api.github.com/repos/neu-rah/ArduinoMenu/commits/1557e3155279ca19e35048f8a6758189cbb2231a" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:47Z" + }, + { + "id": "6263117476", + "type": "PushEvent", + "actor": { + "id": 22308572, + "login": "zfang399", + "display_login": "zfang399", + "gravatar_id": "", + "url": "https://api.github.com/users/zfang399", + "avatar_url": "https://avatars.githubusercontent.com/u/22308572?" + }, + "repo": { + "id": 93472978, + "name": "zfang399/LeetCode-Problems", + "url": "https://api.github.com/repos/zfang399/LeetCode-Problems" + }, + "payload": { + "push_id": 1861573807, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "dffd54fc9872b0a14ae7b3089c541db439c77dc6", + "before": "31643c5f628a91714dabf3c0472d6b3b6f2d75f9", + "commits": [ + { + "sha": "dffd54fc9872b0a14ae7b3089c541db439c77dc6", + "author": { + "email": "zfang@nd.edu", + "name": "Zhaoyuan Fang" + }, + "message": "Reverse Linked List II", + "distinct": true, + "url": "https://api.github.com/repos/zfang399/LeetCode-Problems/commits/dffd54fc9872b0a14ae7b3089c541db439c77dc6" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z" + }, + { + "id": "6263117475", + "type": "PushEvent", + "actor": { + "id": 4750766, + "login": "rohintangirala", + "display_login": "rohintangirala", + "gravatar_id": "", + "url": "https://api.github.com/users/rohintangirala", + "avatar_url": "https://avatars.githubusercontent.com/u/4750766?" + }, + "repo": { + "id": 97284340, + "name": "Twenty-App/Twenty-App.github.io", + "url": "https://api.github.com/repos/Twenty-App/Twenty-App.github.io" + }, + "payload": { + "push_id": 1861573806, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "90effa1defcc57fbb19d118a3cf773e200542333", + "before": "a3a94db8f23bec183df701cc6f27b761be8f6250", + "commits": [ + { + "sha": "90effa1defcc57fbb19d118a3cf773e200542333", + "author": { + "email": "rohinkt@gmail.com", + "name": "Rohin Tangirala" + }, + "message": "Set theme jekyll-theme-tactile", + "distinct": true, + "url": "https://api.github.com/repos/Twenty-App/Twenty-App.github.io/commits/90effa1defcc57fbb19d118a3cf773e200542333" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 30188091, + "login": "Twenty-App", + "gravatar_id": "", + "url": "https://api.github.com/orgs/Twenty-App", + "avatar_url": "https://avatars.githubusercontent.com/u/30188091?" + } + }, + { + "id": "6263117473", + "type": "PushEvent", + "actor": { + "id": 8517910, + "login": "LombiqBot", + "display_login": "LombiqBot", + "gravatar_id": "", + "url": "https://api.github.com/users/LombiqBot", + "avatar_url": "https://avatars.githubusercontent.com/u/8517910?" + }, + "repo": { + "id": 46594739, + "name": "Lombiq/Associativy-Taxonomies-Adapter", + "url": "https://api.github.com/repos/Lombiq/Associativy-Taxonomies-Adapter" + }, + "payload": { + "push_id": 1861573805, + "size": 0, + "distinct_size": 0, + "ref": "refs/heads/orchard-upgrade-1.10", + "head": "e1d77dd00dfdc65d5d84b1712be94e609273c838", + "before": "e1d77dd00dfdc65d5d84b1712be94e609273c838", + "commits": [] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 8158177, + "login": "Lombiq", + "gravatar_id": "", + "url": "https://api.github.com/orgs/Lombiq", + "avatar_url": "https://avatars.githubusercontent.com/u/8158177?" + } + }, + { + "id": "6263117472", + "type": "PushEvent", + "actor": { + "id": 25966, + "login": "reconbot", + "display_login": "reconbot", + "gravatar_id": "", + "url": "https://api.github.com/users/reconbot", + "avatar_url": "https://avatars.githubusercontent.com/u/25966?" + }, + "repo": { + "id": 893522, + "name": "EmergingTechnologyAdvisors/node-serialport", + "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport" + }, + "payload": { + "push_id": 1861573804, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a", + "before": "2361fa599a16a10ad07ffe863fe00bb2bc75d29a", + "commits": [ + { + "sha": "9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a", + "author": { + "email": "wizard@roborooter.com", + "name": "Francis Gulotta" + }, + "message": "[unix] Move setting up the baudrate to the end of the open()\n\n- Test 1000000 baud", + "distinct": true, + "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/commits/9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 8947774, + "login": "EmergingTechnologyAdvisors", + "gravatar_id": "", + "url": "https://api.github.com/orgs/EmergingTechnologyAdvisors", + "avatar_url": "https://avatars.githubusercontent.com/u/8947774?" + } + }, + { + "id": "6263117471", + "type": "IssueCommentEvent", + "actor": { + "id": 737750, + "login": "samuelkarp", + "display_login": "samuelkarp", + "gravatar_id": "", + "url": "https://api.github.com/users/samuelkarp", + "avatar_url": "https://avatars.githubusercontent.com/u/737750?" + }, + "repo": { + "id": 59514412, + "name": "awslabs/amazon-ecr-credential-helper", + "url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper" + }, + "payload": { + "action": "created", + "issue": { + "url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49", + "repository_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper", + "labels_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49/labels{/name}", + "comments_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49/comments", + "events_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49/events", + "html_url": "https://github.com/awslabs/amazon-ecr-credential-helper/issues/49", + "id": 241526602, + "number": 49, + "title": "no basic auth credentials yet AWS CLI has access", + "user": { + "login": "guyisra", + "id": 1073521, + "avatar_url": "https://avatars5.githubusercontent.com/u/1073521?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/guyisra", + "html_url": "https://github.com/guyisra", + "followers_url": "https://api.github.com/users/guyisra/followers", + "following_url": "https://api.github.com/users/guyisra/following{/other_user}", + "gists_url": "https://api.github.com/users/guyisra/gists{/gist_id}", + "starred_url": "https://api.github.com/users/guyisra/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/guyisra/subscriptions", + "organizations_url": "https://api.github.com/users/guyisra/orgs", + "repos_url": "https://api.github.com/users/guyisra/repos", + "events_url": "https://api.github.com/users/guyisra/events{/privacy}", + "received_events_url": "https://api.github.com/users/guyisra/received_events", + "type": "User", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 3, + "created_at": "2017-07-09T13:59:15Z", + "updated_at": "2017-07-15T17:06:46Z", + "closed_at": null, + "body": "I am using Docker v17 and for some reason when trying to push to ECR I get no basic auth credentials.\r\n\r\nThis doesn't happen if I manually login with `aws ecr get-login ...`\r\n\r\nthe policy is configured correctly, I can run other AWS commands.\r\nIt gives the same response with either a profile with the proper policy or with the access key and secret explicitly set.." + }, + "comment": { + "url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/comments/315547939", + "html_url": "https://github.com/awslabs/amazon-ecr-credential-helper/issues/49#issuecomment-315547939", + "issue_url": "https://api.github.com/repos/awslabs/amazon-ecr-credential-helper/issues/49", + "id": 315547939, + "user": { + "login": "samuelkarp", + "id": 737750, + "avatar_url": "https://avatars7.githubusercontent.com/u/737750?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/samuelkarp", + "html_url": "https://github.com/samuelkarp", + "followers_url": "https://api.github.com/users/samuelkarp/followers", + "following_url": "https://api.github.com/users/samuelkarp/following{/other_user}", + "gists_url": "https://api.github.com/users/samuelkarp/gists{/gist_id}", + "starred_url": "https://api.github.com/users/samuelkarp/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/samuelkarp/subscriptions", + "organizations_url": "https://api.github.com/users/samuelkarp/orgs", + "repos_url": "https://api.github.com/users/samuelkarp/repos", + "events_url": "https://api.github.com/users/samuelkarp/events{/privacy}", + "received_events_url": "https://api.github.com/users/samuelkarp/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2017-07-15T17:06:46Z", + "updated_at": "2017-07-15T17:06:46Z", + "body": "@mskutin Thanks for providing the log; that's very helpful. Can you let me know what region this was for so I can investigate further?" + } + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 3299148, + "login": "awslabs", + "gravatar_id": "", + "url": "https://api.github.com/orgs/awslabs", + "avatar_url": "https://avatars.githubusercontent.com/u/3299148?" + } + }, + { + "id": "6263117468", + "type": "IssueCommentEvent", + "actor": { + "id": 1645308, + "login": "almereyda", + "display_login": "almereyda", + "gravatar_id": "", + "url": "https://api.github.com/users/almereyda", + "avatar_url": "https://avatars.githubusercontent.com/u/1645308?" + }, + "repo": { + "id": 22657662, + "name": "wsargent/docker-cheat-sheet", + "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet" + }, + "payload": { + "action": "created", + "issue": { + "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136", + "repository_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet", + "labels_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136/labels{/name}", + "comments_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136/comments", + "events_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136/events", + "html_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136", + "id": 243181907, + "number": 136, + "title": "Volumes can be files", + "user": { + "login": "phoen1x", + "id": 2550793, + "avatar_url": "https://avatars7.githubusercontent.com/u/2550793?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/phoen1x", + "html_url": "https://github.com/phoen1x", + "followers_url": "https://api.github.com/users/phoen1x/followers", + "following_url": "https://api.github.com/users/phoen1x/following{/other_user}", + "gists_url": "https://api.github.com/users/phoen1x/gists{/gist_id}", + "starred_url": "https://api.github.com/users/phoen1x/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/phoen1x/subscriptions", + "organizations_url": "https://api.github.com/users/phoen1x/orgs", + "repos_url": "https://api.github.com/users/phoen1x/repos", + "events_url": "https://api.github.com/users/phoen1x/events{/privacy}", + "received_events_url": "https://api.github.com/users/phoen1x/received_events", + "type": "User", + "site_admin": false + }, + "labels": [], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": null, + "comments": 0, + "created_at": "2017-07-15T15:28:10Z", + "updated_at": "2017-07-15T17:06:46Z", + "closed_at": null, + "pull_request": { + "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/pulls/136", + "html_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136", + "diff_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136.diff", + "patch_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136.patch" + }, + "body": "Just wanted to add that is possible to mount files as volumes. \r\n\r\nDon't know if that is worth mentioning. But it can be useful if you want to toy around with a image from [Docker Hub](https://hub.docker.com) without writing your own Dockerfile." + }, + "comment": { + "url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/comments/315547938", + "html_url": "https://github.com/wsargent/docker-cheat-sheet/pull/136#issuecomment-315547938", + "issue_url": "https://api.github.com/repos/wsargent/docker-cheat-sheet/issues/136", + "id": 315547938, + "user": { + "login": "almereyda", + "id": 1645308, + "avatar_url": "https://avatars4.githubusercontent.com/u/1645308?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/almereyda", + "html_url": "https://github.com/almereyda", + "followers_url": "https://api.github.com/users/almereyda/followers", + "following_url": "https://api.github.com/users/almereyda/following{/other_user}", + "gists_url": "https://api.github.com/users/almereyda/gists{/gist_id}", + "starred_url": "https://api.github.com/users/almereyda/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/almereyda/subscriptions", + "organizations_url": "https://api.github.com/users/almereyda/orgs", + "repos_url": "https://api.github.com/users/almereyda/repos", + "events_url": "https://api.github.com/users/almereyda/events{/privacy}", + "received_events_url": "https://api.github.com/users/almereyda/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2017-07-15T17:06:46Z", + "updated_at": "2017-07-15T17:06:46Z", + "body": "Indeed, I do that all the time when modifying assets that were turned into immutable images already." + } + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z" + }, + { + "id": "6263117464", + "type": "PushEvent", + "actor": { + "id": 19437824, + "login": "keriwheatley", + "display_login": "keriwheatley", + "gravatar_id": "", + "url": "https://api.github.com/users/keriwheatley", + "avatar_url": "https://avatars.githubusercontent.com/u/19437824?" + }, + "repo": { + "id": 91394098, + "name": "keriwheatley/coursework", + "url": "https://api.github.com/repos/keriwheatley/coursework" + }, + "payload": { + "push_id": 1861573800, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "490f194beb4be216ed955d187aee265443dd532c", + "before": "14034277c8e715f9988686d85701b501845705e7", + "commits": [ + { + "sha": "490f194beb4be216ed955d187aee265443dd532c", + "author": { + "email": "keri.wheatley@civitaslearning.com", + "name": "Keri Wheatley" + }, + "message": "updates to twitter_popularity", + "distinct": true, + "url": "https://api.github.com/repos/keriwheatley/coursework/commits/490f194beb4be216ed955d187aee265443dd532c" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z" + }, + { + "id": "6263117462", + "type": "CreateEvent", + "actor": { + "id": 12358972, + "login": "CodePipeline-Test", + "display_login": "CodePipeline-Test", + "gravatar_id": "", + "url": "https://api.github.com/users/CodePipeline-Test", + "avatar_url": "https://avatars.githubusercontent.com/u/12358972?" + }, + "repo": { + "id": 63971386, + "name": "CodePipeline-Test/feature-tests", + "url": "https://api.github.com/repos/CodePipeline-Test/feature-tests" + }, + "payload": { + "ref": "job-worker-features-V5zkpTEUgBlA4TOEJrWq", + "ref_type": "branch", + "master_branch": "master", + "description": "for feature tests", + "pusher_type": "user" + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z" + }, + { + "id": "6263117460", + "type": "WatchEvent", + "actor": { + "id": 9091565, + "login": "chiprunner1995", + "display_login": "chiprunner1995", + "gravatar_id": "", + "url": "https://api.github.com/users/chiprunner1995", + "avatar_url": "https://avatars.githubusercontent.com/u/9091565?" + }, + "repo": { + "id": 308512, + "name": "psake/psake", + "url": "https://api.github.com/repos/psake/psake" + }, + "payload": { + "action": "started" + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 1007585, + "login": "psake", + "gravatar_id": "", + "url": "https://api.github.com/orgs/psake", + "avatar_url": "https://avatars.githubusercontent.com/u/1007585?" + } + }, + { + "id": "6263117459", + "type": "PushEvent", + "actor": { + "id": 30199151, + "login": "Geoffers888", + "display_login": "Geoffers888", + "gravatar_id": "", + "url": "https://api.github.com/users/Geoffers888", + "avatar_url": "https://avatars.githubusercontent.com/u/30199151?" + }, + "repo": { + "id": 97330344, + "name": "Geoffers888/Console-Boxes", + "url": "https://api.github.com/repos/Geoffers888/Console-Boxes" + }, + "payload": { + "push_id": 1861573799, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "46f85052c269c7ede354a698e05e5ef5359bc71b", + "before": "ecb8a45cc1e49ee60ffa880eba8219b294ec44f5", + "commits": [ + { + "sha": "46f85052c269c7ede354a698e05e5ef5359bc71b", + "author": { + "email": "geoff.cowin@gmail.com", + "name": "Geoffers888" + }, + "message": "Create README.md", + "distinct": true, + "url": "https://api.github.com/repos/Geoffers888/Console-Boxes/commits/46f85052c269c7ede354a698e05e5ef5359bc71b" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z" + }, + { + "id": "6263117454", + "type": "PushEvent", + "actor": { + "id": 8517910, + "login": "LombiqBot", + "display_login": "LombiqBot", + "gravatar_id": "", + "url": "https://api.github.com/users/LombiqBot", + "avatar_url": "https://avatars.githubusercontent.com/u/8517910?" + }, + "repo": { + "id": 46624662, + "name": "Lombiq/Orchard-External-Pages", + "url": "https://api.github.com/repos/Lombiq/Orchard-External-Pages" + }, + "payload": { + "push_id": 1861573796, + "size": 0, + "distinct_size": 0, + "ref": "refs/heads/issue/OSOE-7", + "head": "a630eb8494f07e6f11a5bc396a0829d5aa690c5f", + "before": "a630eb8494f07e6f11a5bc396a0829d5aa690c5f", + "commits": [] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 8158177, + "login": "Lombiq", + "gravatar_id": "", + "url": "https://api.github.com/orgs/Lombiq", + "avatar_url": "https://avatars.githubusercontent.com/u/8158177?" + } + }, + { + "id": "6263117451", + "type": "PullRequestEvent", + "actor": { + "id": 25966, + "login": "reconbot", + "display_login": "reconbot", + "gravatar_id": "", + "url": "https://api.github.com/users/reconbot", + "avatar_url": "https://avatars.githubusercontent.com/u/25966?" + }, + "repo": { + "id": 893522, + "name": "EmergingTechnologyAdvisors/node-serialport", + "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport" + }, + "payload": { + "action": "closed", + "number": 1235, + "pull_request": { + "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235", + "id": 130722112, + "html_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235", + "diff_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235.diff", + "patch_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235.patch", + "issue_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235", + "number": 1235, + "state": "closed", + "locked": false, + "title": "[unix] Move setting up the baudrate to the end of the open() to better support custom baudrates", + "user": { + "login": "reconbot", + "id": 25966, + "avatar_url": "https://avatars6.githubusercontent.com/u/25966?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/reconbot", + "html_url": "https://github.com/reconbot", + "followers_url": "https://api.github.com/users/reconbot/followers", + "following_url": "https://api.github.com/users/reconbot/following{/other_user}", + "gists_url": "https://api.github.com/users/reconbot/gists{/gist_id}", + "starred_url": "https://api.github.com/users/reconbot/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/reconbot/subscriptions", + "organizations_url": "https://api.github.com/users/reconbot/orgs", + "repos_url": "https://api.github.com/users/reconbot/repos", + "events_url": "https://api.github.com/users/reconbot/events{/privacy}", + "received_events_url": "https://api.github.com/users/reconbot/received_events", + "type": "User", + "site_admin": false + }, + "body": "- Test 1000000 baud\r\n\r\ncloses #1077", + "created_at": "2017-07-15T16:53:28Z", + "updated_at": "2017-07-15T17:06:45Z", + "closed_at": "2017-07-15T17:06:45Z", + "merged_at": "2017-07-15T17:06:45Z", + "merge_commit_sha": "9c67ee2a43c0e12a5d8d0345e42c866f550d5d0a", + "assignee": null, + "assignees": [], + "requested_reviewers": [], + "milestone": null, + "commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/commits", + "review_comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/comments", + "review_comment_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/comments{/number}", + "comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235/comments", + "statuses_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/e57b3d685f6497ebe8669ce8b05894bacd895177", + "head": { + "label": "EmergingTechnologyAdvisors:1000000-baud", + "ref": "1000000-baud", + "sha": "e57b3d685f6497ebe8669ce8b05894bacd895177", + "user": { + "login": "EmergingTechnologyAdvisors", + "id": 8947774, + "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/EmergingTechnologyAdvisors", + "html_url": "https://github.com/EmergingTechnologyAdvisors", + "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", + "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", + "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", + "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", + "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", + "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", + "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", + "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 893522, + "name": "node-serialport", + "full_name": "EmergingTechnologyAdvisors/node-serialport", + "owner": { + "login": "EmergingTechnologyAdvisors", + "id": 8947774, + "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/EmergingTechnologyAdvisors", + "html_url": "https://github.com/EmergingTechnologyAdvisors", + "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", + "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", + "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", + "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", + "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", + "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", + "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", + "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", + "description": "Node.js package to access serial ports for reading and writing. Welcome your robotic JavaScript overlords. Better yet, program them!", + "fork": false, + "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport", + "forks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/forks", + "keys_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/teams", + "hooks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/hooks", + "issue_events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/events{/number}", + "events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/events", + "assignees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/assignees{/user}", + "branches_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/branches{/branch}", + "tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/tags", + "blobs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/{sha}", + "languages_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/languages", + "stargazers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/stargazers", + "contributors_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contributors", + "subscribers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscribers", + "subscription_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscription", + "commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contents/{+path}", + "compare_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/merges", + "archive_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/downloads", + "issues_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues{/number}", + "pulls_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls{/number}", + "milestones_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/milestones{/number}", + "notifications_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/labels{/name}", + "releases_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/releases{/id}", + "deployments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/deployments", + "created_at": "2010-09-07T12:24:28Z", + "updated_at": "2017-07-14T16:30:58Z", + "pushed_at": "2017-07-15T17:06:45Z", + "git_url": "git://github.com/EmergingTechnologyAdvisors/node-serialport.git", + "ssh_url": "git@github.com:EmergingTechnologyAdvisors/node-serialport.git", + "clone_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport.git", + "svn_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", + "homepage": "", + "size": 1914, + "stargazers_count": 2829, + "watchers_count": 2829, + "language": "JavaScript", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": true, + "forks_count": 601, + "mirror_url": null, + "open_issues_count": 30, + "forks": 601, + "open_issues": 30, + "watchers": 2829, + "default_branch": "master" + } + }, + "base": { + "label": "EmergingTechnologyAdvisors:master", + "ref": "master", + "sha": "ee7315f59c7698811f4f76405383f18680843926", + "user": { + "login": "EmergingTechnologyAdvisors", + "id": 8947774, + "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/EmergingTechnologyAdvisors", + "html_url": "https://github.com/EmergingTechnologyAdvisors", + "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", + "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", + "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", + "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", + "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", + "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", + "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", + "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", + "type": "Organization", + "site_admin": false + }, + "repo": { + "id": 893522, + "name": "node-serialport", + "full_name": "EmergingTechnologyAdvisors/node-serialport", + "owner": { + "login": "EmergingTechnologyAdvisors", + "id": 8947774, + "avatar_url": "https://avatars7.githubusercontent.com/u/8947774?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/EmergingTechnologyAdvisors", + "html_url": "https://github.com/EmergingTechnologyAdvisors", + "followers_url": "https://api.github.com/users/EmergingTechnologyAdvisors/followers", + "following_url": "https://api.github.com/users/EmergingTechnologyAdvisors/following{/other_user}", + "gists_url": "https://api.github.com/users/EmergingTechnologyAdvisors/gists{/gist_id}", + "starred_url": "https://api.github.com/users/EmergingTechnologyAdvisors/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/EmergingTechnologyAdvisors/subscriptions", + "organizations_url": "https://api.github.com/users/EmergingTechnologyAdvisors/orgs", + "repos_url": "https://api.github.com/users/EmergingTechnologyAdvisors/repos", + "events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/events{/privacy}", + "received_events_url": "https://api.github.com/users/EmergingTechnologyAdvisors/received_events", + "type": "Organization", + "site_admin": false + }, + "private": false, + "html_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", + "description": "Node.js package to access serial ports for reading and writing. Welcome your robotic JavaScript overlords. Better yet, program them!", + "fork": false, + "url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport", + "forks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/forks", + "keys_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/keys{/key_id}", + "collaborators_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/collaborators{/collaborator}", + "teams_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/teams", + "hooks_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/hooks", + "issue_events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/events{/number}", + "events_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/events", + "assignees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/assignees{/user}", + "branches_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/branches{/branch}", + "tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/tags", + "blobs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/blobs{/sha}", + "git_tags_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/tags{/sha}", + "git_refs_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/refs{/sha}", + "trees_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/trees{/sha}", + "statuses_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/{sha}", + "languages_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/languages", + "stargazers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/stargazers", + "contributors_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contributors", + "subscribers_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscribers", + "subscription_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/subscription", + "commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/commits{/sha}", + "git_commits_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/git/commits{/sha}", + "comments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/comments{/number}", + "issue_comment_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/comments{/number}", + "contents_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/contents/{+path}", + "compare_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/compare/{base}...{head}", + "merges_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/merges", + "archive_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/{archive_format}{/ref}", + "downloads_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/downloads", + "issues_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues{/number}", + "pulls_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls{/number}", + "milestones_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/milestones{/number}", + "notifications_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/notifications{?since,all,participating}", + "labels_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/labels{/name}", + "releases_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/releases{/id}", + "deployments_url": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/deployments", + "created_at": "2010-09-07T12:24:28Z", + "updated_at": "2017-07-14T16:30:58Z", + "pushed_at": "2017-07-15T17:06:45Z", + "git_url": "git://github.com/EmergingTechnologyAdvisors/node-serialport.git", + "ssh_url": "git@github.com:EmergingTechnologyAdvisors/node-serialport.git", + "clone_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport.git", + "svn_url": "https://github.com/EmergingTechnologyAdvisors/node-serialport", + "homepage": "", + "size": 1914, + "stargazers_count": 2829, + "watchers_count": 2829, + "language": "JavaScript", + "has_issues": true, + "has_projects": true, + "has_downloads": true, + "has_wiki": false, + "has_pages": true, + "forks_count": 601, + "mirror_url": null, + "open_issues_count": 30, + "forks": 601, + "open_issues": 30, + "watchers": 2829, + "default_branch": "master" + } + }, + "_links": { + "self": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235" + }, + "html": { + "href": "https://github.com/EmergingTechnologyAdvisors/node-serialport/pull/1235" + }, + "issue": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235" + }, + "comments": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/issues/1235/comments" + }, + "review_comments": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/comments" + }, + "review_comment": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/comments{/number}" + }, + "commits": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/pulls/1235/commits" + }, + "statuses": { + "href": "https://api.github.com/repos/EmergingTechnologyAdvisors/node-serialport/statuses/e57b3d685f6497ebe8669ce8b05894bacd895177" + } + }, + "merged": true, + "mergeable": null, + "rebaseable": null, + "mergeable_state": "unknown", + "merged_by": { + "login": "reconbot", + "id": 25966, + "avatar_url": "https://avatars6.githubusercontent.com/u/25966?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/reconbot", + "html_url": "https://github.com/reconbot", + "followers_url": "https://api.github.com/users/reconbot/followers", + "following_url": "https://api.github.com/users/reconbot/following{/other_user}", + "gists_url": "https://api.github.com/users/reconbot/gists{/gist_id}", + "starred_url": "https://api.github.com/users/reconbot/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/reconbot/subscriptions", + "organizations_url": "https://api.github.com/users/reconbot/orgs", + "repos_url": "https://api.github.com/users/reconbot/repos", + "events_url": "https://api.github.com/users/reconbot/events{/privacy}", + "received_events_url": "https://api.github.com/users/reconbot/received_events", + "type": "User", + "site_admin": false + }, + "comments": 0, + "review_comments": 0, + "maintainer_can_modify": false, + "commits": 1, + "additions": 24, + "deletions": 14, + "changed_files": 2 + } + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z", + "org": { + "id": 8947774, + "login": "EmergingTechnologyAdvisors", + "gravatar_id": "", + "url": "https://api.github.com/orgs/EmergingTechnologyAdvisors", + "avatar_url": "https://avatars.githubusercontent.com/u/8947774?" + } + }, + { + "id": "6263117447", + "type": "PushEvent", + "actor": { + "id": 11887843, + "login": "trimox", + "display_login": "trimox", + "gravatar_id": "", + "url": "https://api.github.com/users/trimox", + "avatar_url": "https://avatars.githubusercontent.com/u/11887843?" + }, + "repo": { + "id": 88184430, + "name": "trimox/angular-mdc-web", + "url": "https://api.github.com/repos/trimox/angular-mdc-web" + }, + "payload": { + "push_id": 1861573792, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "59de0a8bfb229e7e72a1960132fdf24f0a770a08", + "before": "27327b3a3cb4e58ddb1b1188cb0f04092d850106", + "commits": [ + { + "sha": "59de0a8bfb229e7e72a1960132fdf24f0a770a08", + "author": { + "email": "trimoxal@gmail.com", + "name": "Dominic Carretto" + }, + "message": "fix(snackbar): Fix actionHandler still required if actionText is empty", + "distinct": true, + "url": "https://api.github.com/repos/trimox/angular-mdc-web/commits/59de0a8bfb229e7e72a1960132fdf24f0a770a08" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:46Z" + }, + { + "id": "6263117445", + "type": "WatchEvent", + "actor": { + "id": 1006434, + "login": "enorrmann", + "display_login": "enorrmann", + "gravatar_id": "", + "url": "https://api.github.com/users/enorrmann", + "avatar_url": "https://avatars.githubusercontent.com/u/1006434?" + }, + "repo": { + "id": 14699489, + "name": "walmik/scribbletune", + "url": "https://api.github.com/repos/walmik/scribbletune" + }, + "payload": { + "action": "started" + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117444", + "type": "PushEvent", + "actor": { + "id": 24412103, + "login": "james341", + "display_login": "james341", + "gravatar_id": "", + "url": "https://api.github.com/users/james341", + "avatar_url": "https://avatars.githubusercontent.com/u/24412103?" + }, + "repo": { + "id": 96979484, + "name": "james341/loading-yan-rp", + "url": "https://api.github.com/repos/james341/loading-yan-rp" + }, + "payload": { + "push_id": 1861573791, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "16bb35eb4a43d916a40155996c9d7dfadb007573", + "before": "ad4b96a5b924783e42d1d0cbf0fd1b5cba3cbd2f", + "commits": [ + { + "sha": "16bb35eb4a43d916a40155996c9d7dfadb007573", + "author": { + "email": "taine049@gmail.com", + "name": "james341" + }, + "message": "Add files via upload", + "distinct": true, + "url": "https://api.github.com/repos/james341/loading-yan-rp/commits/16bb35eb4a43d916a40155996c9d7dfadb007573" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117441", + "type": "PushEvent", + "actor": { + "id": 4676211, + "login": "kanke", + "display_login": "kanke", + "gravatar_id": "", + "url": "https://api.github.com/users/kanke", + "avatar_url": "https://avatars.githubusercontent.com/u/4676211?" + }, + "repo": { + "id": 97262451, + "name": "kanke/RedisServerClone", + "url": "https://api.github.com/repos/kanke/RedisServerClone" + }, + "payload": { + "push_id": 1861573790, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "e6312819f0acdc40008b06ae7a2c6c211c2f1db0", + "before": "f9a4fe7e866181c74fbc9352310fbc6c539d2aff", + "commits": [ + { + "sha": "e6312819f0acdc40008b06ae7a2c6c211c2f1db0", + "author": { + "email": "sugarkanke@yahoo.com", + "name": "Kanke" + }, + "message": "Adding gitignore and readme.md content. Code cleanup.", + "distinct": true, + "url": "https://api.github.com/repos/kanke/RedisServerClone/commits/e6312819f0acdc40008b06ae7a2c6c211c2f1db0" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117440", + "type": "PushEvent", + "actor": { + "id": 16622965, + "login": "jainhitesh9998", + "display_login": "jainhitesh9998", + "gravatar_id": "", + "url": "https://api.github.com/users/jainhitesh9998", + "avatar_url": "https://avatars.githubusercontent.com/u/16622965?" + }, + "repo": { + "id": 94244445, + "name": "jainhitesh9998/WebDevelopment", + "url": "https://api.github.com/repos/jainhitesh9998/WebDevelopment" + }, + "payload": { + "push_id": 1861573789, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "9e3c3f5f437fbc1f21a30f19f764787b86a393be", + "before": "d69d496b80a5806406f2313d67e63f3adf61b97e", + "commits": [ + { + "sha": "9e3c3f5f437fbc1f21a30f19f764787b86a393be", + "author": { + "email": "jainhitesh9998@gmail.com", + "name": "Hitesh C" + }, + "message": "added sounds for the clone", + "distinct": true, + "url": "https://api.github.com/repos/jainhitesh9998/WebDevelopment/commits/9e3c3f5f437fbc1f21a30f19f764787b86a393be" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117437", + "type": "PushEvent", + "actor": { + "id": 1491646, + "login": "MikroAcse", + "display_login": "MikroAcse", + "gravatar_id": "", + "url": "https://api.github.com/users/MikroAcse", + "avatar_url": "https://avatars.githubusercontent.com/u/1491646?" + }, + "repo": { + "id": 96892535, + "name": "MikroAcse/VariousTelegramBots", + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots" + }, + "payload": { + "push_id": 1861573788, + "size": 11, + "distinct_size": 11, + "ref": "refs/heads/dev", + "head": "7ef25bf6aad45c9da53a2d5918e553c68cd69dd4", + "before": "931cef7db8ec69cc951fe8a5ecc2b909397e29a4", + "commits": [ + { + "sha": "88b9e4e53f62ff7c9597f66d9e45a0a9be5fe1ca", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "upgrade Node.js version", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/88b9e4e53f62ff7c9597f66d9e45a0a9be5fe1ca" + }, + { + "sha": "d5b91bac58a8c3b88ddd9634578cb3beebb31015", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Update Node js version", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/d5b91bac58a8c3b88ddd9634578cb3beebb31015" + }, + { + "sha": "37cd86961e36e64c8ccd7873bbccc200b920d308", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Fix", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/37cd86961e36e64c8ccd7873bbccc200b920d308" + }, + { + "sha": "471451fd46b9bed62eef062553f480e788c24a3c", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Merge branch 'master' into dev\n\n# Conflicts:\n#\tapp.js", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/471451fd46b9bed62eef062553f480e788c24a3c" + }, + { + "sha": "8f5be591fae47f1ff051f992176faeed8fe3c2d7", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Removed unnecessary dependency and updated README.md", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/8f5be591fae47f1ff051f992176faeed8fe3c2d7" + }, + { + "sha": "d239750fbb26f13daf50a14e1c4a23375df9c5d9", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Update README", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/d239750fbb26f13daf50a14e1c4a23375df9c5d9" + }, + { + "sha": "94adaefc2b4107db89cdbc045a6a106724f12a2d", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Fix in readme", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/94adaefc2b4107db89cdbc045a6a106724f12a2d" + }, + { + "sha": "da8009c4da182c036efbc7a8e9d9353d1282d5ed", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Added version to readme", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/da8009c4da182c036efbc7a8e9d9353d1282d5ed" + }, + { + "sha": "1590092c64e774633040419b69d60d98197ddbde", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Removed requirement of deleted dependency", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/1590092c64e774633040419b69d60d98197ddbde" + }, + { + "sha": "1986905b1d32654a20916fafc60c7484ff85841a", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Yes or no in ChooseBot, slight changes in QuoteBot regexp", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/1986905b1d32654a20916fafc60c7484ff85841a" + }, + { + "sha": "7ef25bf6aad45c9da53a2d5918e553c68cd69dd4", + "author": { + "email": "mike.kroace@gmail.com", + "name": "Vitaly Rudenko" + }, + "message": "Merge commit '1986905b1d32654a20916fafc60c7484ff85841a' into dev", + "distinct": true, + "url": "https://api.github.com/repos/MikroAcse/VariousTelegramBots/commits/7ef25bf6aad45c9da53a2d5918e553c68cd69dd4" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117435", + "type": "PushEvent", + "actor": { + "id": 12949454, + "login": "jarifibrahim", + "display_login": "jarifibrahim", + "gravatar_id": "", + "url": "https://api.github.com/users/jarifibrahim", + "avatar_url": "https://avatars.githubusercontent.com/u/12949454?" + }, + "repo": { + "id": 93039796, + "name": "jarifibrahim/OpenSourceHelpCommunity.github.io", + "url": "https://api.github.com/repos/jarifibrahim/OpenSourceHelpCommunity.github.io" + }, + "payload": { + "push_id": 1861573787, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/issue-4", + "head": "4b7341d9b7bb95f5f0e1d50831a9c978fc4fceb4", + "before": "57c0a65ee93de1955ad5691585a51c358188f311", + "commits": [ + { + "sha": "4b7341d9b7bb95f5f0e1d50831a9c978fc4fceb4", + "author": { + "email": "jarifibrahim@gmail.com", + "name": "Ibrahim Jarif" + }, + "message": "Add travs.yml", + "distinct": true, + "url": "https://api.github.com/repos/jarifibrahim/OpenSourceHelpCommunity.github.io/commits/4b7341d9b7bb95f5f0e1d50831a9c978fc4fceb4" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117430", + "type": "IssueCommentEvent", + "actor": { + "id": 849609, + "login": "wrrn", + "display_login": "wrrn", + "gravatar_id": "", + "url": "https://api.github.com/users/wrrn", + "avatar_url": "https://avatars.githubusercontent.com/u/849609?" + }, + "repo": { + "id": 23096959, + "name": "golang/go", + "url": "https://api.github.com/repos/golang/go" + }, + "payload": { + "action": "created", + "issue": { + "url": "https://api.github.com/repos/golang/go/issues/21017", + "repository_url": "https://api.github.com/repos/golang/go", + "labels_url": "https://api.github.com/repos/golang/go/issues/21017/labels{/name}", + "comments_url": "https://api.github.com/repos/golang/go/issues/21017/comments", + "events_url": "https://api.github.com/repos/golang/go/issues/21017/events", + "html_url": "https://github.com/golang/go/issues/21017", + "id": 243177572, + "number": 21017, + "title": "Gophercon: Contributor Workshop Registration", + "user": { + "login": "jessfraz", + "id": 1445228, + "avatar_url": "https://avatars6.githubusercontent.com/u/1445228?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/jessfraz", + "html_url": "https://github.com/jessfraz", + "followers_url": "https://api.github.com/users/jessfraz/followers", + "following_url": "https://api.github.com/users/jessfraz/following{/other_user}", + "gists_url": "https://api.github.com/users/jessfraz/gists{/gist_id}", + "starred_url": "https://api.github.com/users/jessfraz/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/jessfraz/subscriptions", + "organizations_url": "https://api.github.com/users/jessfraz/orgs", + "repos_url": "https://api.github.com/users/jessfraz/repos", + "events_url": "https://api.github.com/users/jessfraz/events{/privacy}", + "received_events_url": "https://api.github.com/users/jessfraz/received_events", + "type": "User", + "site_admin": false + }, + "labels": [ + { + "id": 150880243, + "url": "https://api.github.com/repos/golang/go/labels/HelpWanted", + "name": "HelpWanted", + "color": "fbca04", + "default": false + } + ], + "state": "open", + "locked": false, + "assignee": null, + "assignees": [], + "milestone": { + "url": "https://api.github.com/repos/golang/go/milestones/22", + "html_url": "https://github.com/golang/go/milestone/22", + "labels_url": "https://api.github.com/repos/golang/go/milestones/22/labels", + "id": 1067491, + "number": 22, + "title": "Unreleased", + "description": "Issues that do not affect released Go code and binaries.\r\n", + "creator": { + "login": "rsc", + "id": 104030, + "avatar_url": "https://avatars5.githubusercontent.com/u/104030?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/rsc", + "html_url": "https://github.com/rsc", + "followers_url": "https://api.github.com/users/rsc/followers", + "following_url": "https://api.github.com/users/rsc/following{/other_user}", + "gists_url": "https://api.github.com/users/rsc/gists{/gist_id}", + "starred_url": "https://api.github.com/users/rsc/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/rsc/subscriptions", + "organizations_url": "https://api.github.com/users/rsc/orgs", + "repos_url": "https://api.github.com/users/rsc/repos", + "events_url": "https://api.github.com/users/rsc/events{/privacy}", + "received_events_url": "https://api.github.com/users/rsc/received_events", + "type": "User", + "site_admin": false + }, + "open_issues": 707, + "closed_issues": 918, + "state": "open", + "created_at": "2015-04-14T18:48:22Z", + "updated_at": "2017-07-15T17:06:04Z", + "due_on": "2099-12-31T08:00:00Z", + "closed_at": null + }, + "comments": 14, + "created_at": "2017-07-15T14:13:29Z", + "updated_at": "2017-07-15T17:06:43Z", + "closed_at": null, + "body": "Please do not comment here until the Contributor Workshop begins.\r\n\r\nDuring the workshop leave a comment with your Gerritt profile ID here." + }, + "comment": { + "url": "https://api.github.com/repos/golang/go/issues/comments/315547934", + "html_url": "https://github.com/golang/go/issues/21017#issuecomment-315547934", + "issue_url": "https://api.github.com/repos/golang/go/issues/21017", + "id": 315547934, + "user": { + "login": "wrrn", + "id": 849609, + "avatar_url": "https://avatars7.githubusercontent.com/u/849609?v=4", + "gravatar_id": "", + "url": "https://api.github.com/users/wrrn", + "html_url": "https://github.com/wrrn", + "followers_url": "https://api.github.com/users/wrrn/followers", + "following_url": "https://api.github.com/users/wrrn/following{/other_user}", + "gists_url": "https://api.github.com/users/wrrn/gists{/gist_id}", + "starred_url": "https://api.github.com/users/wrrn/starred{/owner}{/repo}", + "subscriptions_url": "https://api.github.com/users/wrrn/subscriptions", + "organizations_url": "https://api.github.com/users/wrrn/orgs", + "repos_url": "https://api.github.com/users/wrrn/repos", + "events_url": "https://api.github.com/users/wrrn/events{/privacy}", + "received_events_url": "https://api.github.com/users/wrrn/received_events", + "type": "User", + "site_admin": false + }, + "created_at": "2017-07-15T17:06:43Z", + "updated_at": "2017-07-15T17:06:43Z", + "body": "22590" + } + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z", + "org": { + "id": 4314092, + "login": "golang", + "gravatar_id": "", + "url": "https://api.github.com/orgs/golang", + "avatar_url": "https://avatars.githubusercontent.com/u/4314092?" + } + }, + { + "id": "6263117428", + "type": "PushEvent", + "actor": { + "id": 6938676, + "login": "Ordinastie", + "display_login": "Ordinastie", + "gravatar_id": "", + "url": "https://api.github.com/users/Ordinastie", + "avatar_url": "https://avatars.githubusercontent.com/u/6938676?" + }, + "repo": { + "id": 17756561, + "name": "Ordinastie/MalisisDoors", + "url": "https://api.github.com/repos/Ordinastie/MalisisDoors" + }, + "payload": { + "push_id": 1861573783, + "size": 2, + "distinct_size": 2, + "ref": "refs/heads/1.12", + "head": "07334b1700ec9cd173c7560f293b7dd10dc24fd9", + "before": "ee8e1058833056afdcac559c22518b3706b3657f", + "commits": [ + { + "sha": "52080012d79ae0320392379b5d054f3e17ec1b98", + "author": { + "email": "ordinastie@hotmail.com", + "name": "Ordinastie" + }, + "message": "Fixed getRegistryType()", + "distinct": true, + "url": "https://api.github.com/repos/Ordinastie/MalisisDoors/commits/52080012d79ae0320392379b5d054f3e17ec1b98" + }, + { + "sha": "07334b1700ec9cd173c7560f293b7dd10dc24fd9", + "author": { + "email": "ordinastie@hotmail.com", + "name": "Ordinastie" + }, + "message": "Updated forgegradle and curseforge version", + "distinct": true, + "url": "https://api.github.com/repos/Ordinastie/MalisisDoors/commits/07334b1700ec9cd173c7560f293b7dd10dc24fd9" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117427", + "type": "DeleteEvent", + "actor": { + "id": 227909, + "login": "amcdnl", + "display_login": "amcdnl", + "gravatar_id": "", + "url": "https://api.github.com/users/amcdnl", + "avatar_url": "https://avatars.githubusercontent.com/u/227909?" + }, + "repo": { + "id": 94944874, + "name": "amcdnl/material2", + "url": "https://api.github.com/repos/amcdnl/material2" + }, + "payload": { + "ref": "autocomplete-demos", + "ref_type": "branch", + "pusher_type": "user" + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + }, + { + "id": "6263117426", + "type": "PushEvent", + "actor": { + "id": 16347325, + "login": "zxui", + "display_login": "zxui", + "gravatar_id": "", + "url": "https://api.github.com/users/zxui", + "avatar_url": "https://avatars.githubusercontent.com/u/16347325?" + }, + "repo": { + "id": 88623154, + "name": "zxui/auto-admin", + "url": "https://api.github.com/repos/zxui/auto-admin" + }, + "payload": { + "push_id": 1861573782, + "size": 1, + "distinct_size": 1, + "ref": "refs/heads/master", + "head": "70d47755fde8a5c4cfde101ba65caa6c1d6fcdb2", + "before": "f673e6b191197827bddb31bcffea61611e8a50b0", + "commits": [ + { + "sha": "70d47755fde8a5c4cfde101ba65caa6c1d6fcdb2", + "author": { + "email": "zxshen@qq.com", + "name": "zxui" + }, + "message": "update", + "distinct": true, + "url": "https://api.github.com/repos/zxui/auto-admin/commits/70d47755fde8a5c4cfde101ba65caa6c1d6fcdb2" + } + ] + }, + "public": true, + "created_at": "2017-07-15T17:06:45Z" + } +] diff --git a/test/fixtures/typescript-effect-schema/main.ts b/test/fixtures/typescript-effect-schema/main.ts index 538914b6e..944b021f1 100644 --- a/test/fixtures/typescript-effect-schema/main.ts +++ b/test/fixtures/typescript-effect-schema/main.ts @@ -1,7 +1,7 @@ import * as TopLevel from "./TopLevel"; import fs from "fs"; import process from "process"; -import * as Schema from "@effect/schema/Schema"; +import * as Schema from "effect/Schema"; const sample = process.argv[2]; const json = fs.readFileSync(sample); @@ -10,7 +10,7 @@ const value = JSON.parse(json.toString()); let schema = TopLevel.TopLevel ?? TopLevel.TopLevelElement; if (!schema) { // Sometimes key is prefixed with funPrefixes (e.g. 2df80.json) - Object.keys(TopLevel).some(key => { + Object.keys(TopLevel).some((key) => { if (key.endsWith("TopLevel") || key.endsWith("TopLevelElement")) { schema = TopLevel[key]; return true; @@ -24,12 +24,12 @@ if (!schema) { let backToJson: string; if (Array.isArray(value)) { - const parsedValue = value.map(v => { - return Schema.parseSync(schema)(v); + const parsedValue = value.map((v) => { + return Schema.decodeUnknownSync(schema)(v); }); backToJson = JSON.stringify(parsedValue, null, 2); } else { - const parsedValue = Schema.parseSync(schema)(value); + const parsedValue = Schema.decodeUnknownSync(schema)(value); backToJson = JSON.stringify(parsedValue, null, 2); } diff --git a/test/fixtures/typescript-effect-schema/package-lock.json b/test/fixtures/typescript-effect-schema/package-lock.json index b94bf5c38..118b2e72c 100644 --- a/test/fixtures/typescript-effect-schema/package-lock.json +++ b/test/fixtures/typescript-effect-schema/package-lock.json @@ -1,7 +1,7 @@ { "name": "typescript-effect-schema", "version": "0.1.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { @@ -9,56 +9,17 @@ "version": "0.1.0", "license": "Apache-2.0", "dependencies": { - "@effect/schema": "^0.47.1" + "effect": "^3.10.0" }, "devDependencies": { "tsx": "^3.12.2", - "typescript": "^4.3.5" - } - }, - "node_modules/@effect/schema": { - "version": "0.47.1", - "resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.47.1.tgz", - "integrity": "sha512-aqh6U1Faqqi+iMENdCt3Wp/sYZH9QJLJPKUycOllzcjFmOnNlb9Yiw58LNhzLSoAqNOTUtHjx31EHk/P7h8tuQ==", - "peerDependencies": { - "effect": "2.0.0-next.54", - "fast-check": "^3.13.2" - } - }, - "node_modules/@esbuild-kit/cjs-loader": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.1.tgz", - "integrity": "sha512-lhc/XLith28QdW0HpHZvZKkorWgmCNT7sVelMHDj3HFdTfdqkwEKvT+aXVQtNAmCC39VJhunDkWhONWB7335mg==", - "dev": true, - "dependencies": { - "@esbuild-kit/core-utils": "^3.0.0", - "get-tsconfig": "^4.2.0" - } - }, - "node_modules/@esbuild-kit/core-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.0.0.tgz", - "integrity": "sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==", - "dev": true, - "dependencies": { - "esbuild": "~0.15.10", - "source-map-support": "^0.5.21" - } - }, - "node_modules/@esbuild-kit/esm-loader": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.4.tgz", - "integrity": "sha512-afmtLf6uqxD5IgwCzomtqCYIgz/sjHzCWZFvfS5+FzeYxOURPUo4QcHtqJxbxWOMOogKriZanN/1bJQE/ZL93A==", - "dev": true, - "dependencies": { - "@esbuild-kit/core-utils": "^3.0.0", - "get-tsconfig": "^4.2.0" + "typescript": "^5.4.0" } }, "node_modules/@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", "cpu": [ "arm" ], @@ -71,75 +32,26 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "optional": true, "os": [ - "linux" + "android" ], "engines": { "node": ">=12" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "node_modules/effect": { - "version": "2.0.0-next.54", - "resolved": "https://registry.npmjs.org/effect/-/effect-2.0.0-next.54.tgz", - "integrity": "sha512-qROhKMxlm6fpa90YRfWSgKeelDfhaDq2igPK+pIKupGehiCnZH4vd2qrY71HVZ10qZgXxh0VXpGyDQxJC+EQqw==", - "peer": true - }, - "node_modules/esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" - } - }, - "node_modules/esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", "cpu": [ "x64" ], @@ -152,26 +64,26 @@ "node": ">=12" } }, - "node_modules/esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ - "android" + "darwin" ], "engines": { "node": ">=12" } }, - "node_modules/esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", "cpu": [ "x64" ], @@ -184,26 +96,26 @@ "node": ">=12" } }, - "node_modules/esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", "cpu": [ "arm64" ], "dev": true, "optional": true, "os": [ - "darwin" + "freebsd" ], "engines": { "node": ">=12" } }, - "node_modules/esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", "cpu": [ "x64" ], @@ -216,28 +128,28 @@ "node": ">=12" } }, - "node_modules/esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", "cpu": [ - "arm64" + "arm" ], "dev": true, "optional": true, "os": [ - "freebsd" + "linux" ], "engines": { "node": ">=12" } }, - "node_modules/esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "optional": true, @@ -248,12 +160,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", "cpu": [ - "x64" + "ia32" ], "dev": true, "optional": true, @@ -264,12 +176,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", "cpu": [ - "arm" + "loong64" ], "dev": true, "optional": true, @@ -280,12 +192,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", "cpu": [ - "arm64" + "mips64el" ], "dev": true, "optional": true, @@ -296,12 +208,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", "cpu": [ - "mips64el" + "ppc64" ], "dev": true, "optional": true, @@ -312,12 +224,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", "cpu": [ - "ppc64" + "riscv64" ], "dev": true, "optional": true, @@ -328,12 +240,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", "cpu": [ - "riscv64" + "s390x" ], "dev": true, "optional": true, @@ -344,12 +256,12 @@ "node": ">=12" } }, - "node_modules/esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", "cpu": [ - "s390x" + "x64" ], "dev": true, "optional": true, @@ -360,10 +272,10 @@ "node": ">=12" } }, - "node_modules/esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", "cpu": [ "x64" ], @@ -376,10 +288,10 @@ "node": ">=12" } }, - "node_modules/esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", "cpu": [ "x64" ], @@ -392,10 +304,10 @@ "node": ">=12" } }, - "node_modules/esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", "cpu": [ "x64" ], @@ -408,12 +320,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", "cpu": [ - "ia32" + "arm64" ], "dev": true, "optional": true, @@ -424,12 +336,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", "cpu": [ - "x64" + "ia32" ], "dev": true, "optional": true, @@ -440,12 +352,12 @@ "node": ">=12" } }, - "node_modules/esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, "optional": true, @@ -456,10 +368,62 @@ "node": ">=12" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/effect": { + "version": "3.10.2", + "resolved": "https://registry.npmjs.org/effect/-/effect-3.10.2.tgz", + "integrity": "sha512-Sj73q9jwwR4t3WV6E0sw4KMhx0fAHebXavYS5rsHLrWKcf4fzhDh6IixJB6mDhT7rEax/9UsoYjzrc1p7VLwbw==", + "license": "MIT", + "dependencies": { + "fast-check": "^3.21.0" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, "node_modules/fast-check": { - "version": "3.13.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.13.2.tgz", - "integrity": "sha512-ouTiFyeMoqmNg253xqy4NSacr5sHxH6pZpLOaHgaAdgZxFWdtsfxExwolpveoAE9CJdV+WYjqErNGef6SqA5Mg==", + "version": "3.22.0", + "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.22.0.tgz", + "integrity": "sha512-8HKz3qXqnHYp/VCNn2qfjHdAdcI8zcSqOyX64GOMukp7SL2bfzfeDKjSd+UyECtejccaZv3LcvZTm9YDD22iCQ==", "funding": [ { "type": "individual", @@ -470,18 +434,18 @@ "url": "https://opencollective.com/fast-check" } ], - "peer": true, + "license": "MIT", "dependencies": { - "pure-rand": "^6.0.0" + "pure-rand": "^6.1.0" }, "engines": { "node": ">=8.0.0" } }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, "optional": true, @@ -493,18 +457,21 @@ } }, "node_modules/get-tsconfig": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.3.0.tgz", - "integrity": "sha512-YCcF28IqSay3fqpIu5y3Krg/utCBHBeoflkZyHj/QcqI2nrLPC3ZegS9CmIo+hJb8K7aiGsuUl7PwWVjNG2HQQ==", + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.3.tgz", + "integrity": "sha512-ZvkrzoUA0PQZM6fy6+/Hce561s+faD1rsNwhnO5FelNjyy7EMGJ3Rz1AQ8GYDWjhRs/7dBLOEJvhK8MiEJOAFg==", "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, "funding": { "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, "node_modules/pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", "funding": [ { "type": "individual", @@ -515,7 +482,16 @@ "url": "https://opencollective.com/fast-check" } ], - "peer": true + "license": "MIT" + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } }, "node_modules/source-map": { "version": "0.6.1", @@ -537,330 +513,34 @@ } }, "node_modules/tsx": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.2.tgz", - "integrity": "sha512-ykAEkoBg30RXxeOMVeZwar+JH632dZn9EUJVyJwhfag62k6UO/dIyJEV58YuLF6e5BTdV/qmbQrpkWqjq9cUnQ==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", + "integrity": "sha512-xHtFaKtHxM9LOklMmJdI3BEnQq/D5F73Of2E1GDrITi9sgoVkvIsrQUTY1G8FlmGtA+awCI4EBlTRRYxkL2sRg==", "dev": true, "dependencies": { - "@esbuild-kit/cjs-loader": "^2.4.1", - "@esbuild-kit/core-utils": "^3.0.0", - "@esbuild-kit/esm-loader": "^2.5.4" + "esbuild": "~0.18.20", + "get-tsconfig": "^4.7.2", + "source-map-support": "^0.5.21" }, "bin": { - "tsx": "dist/cli.js" + "tsx": "dist/cli.mjs" }, "optionalDependencies": { - "fsevents": "~2.3.2" + "fsevents": "~2.3.3" } }, "node_modules/typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" - } - } - }, - "dependencies": { - "@effect/schema": { - "version": "0.47.1", - "resolved": "https://registry.npmjs.org/@effect/schema/-/schema-0.47.1.tgz", - "integrity": "sha512-aqh6U1Faqqi+iMENdCt3Wp/sYZH9QJLJPKUycOllzcjFmOnNlb9Yiw58LNhzLSoAqNOTUtHjx31EHk/P7h8tuQ==", - "requires": {} - }, - "@esbuild-kit/cjs-loader": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@esbuild-kit/cjs-loader/-/cjs-loader-2.4.1.tgz", - "integrity": "sha512-lhc/XLith28QdW0HpHZvZKkorWgmCNT7sVelMHDj3HFdTfdqkwEKvT+aXVQtNAmCC39VJhunDkWhONWB7335mg==", - "dev": true, - "requires": { - "@esbuild-kit/core-utils": "^3.0.0", - "get-tsconfig": "^4.2.0" - } - }, - "@esbuild-kit/core-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@esbuild-kit/core-utils/-/core-utils-3.0.0.tgz", - "integrity": "sha512-TXmwH9EFS3DC2sI2YJWJBgHGhlteK0Xyu1VabwetMULfm3oYhbrsWV5yaSr2NTWZIgDGVLHbRf0inxbjXqAcmQ==", - "dev": true, - "requires": { - "esbuild": "~0.15.10", - "source-map-support": "^0.5.21" - } - }, - "@esbuild-kit/esm-loader": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/@esbuild-kit/esm-loader/-/esm-loader-2.5.4.tgz", - "integrity": "sha512-afmtLf6uqxD5IgwCzomtqCYIgz/sjHzCWZFvfS5+FzeYxOURPUo4QcHtqJxbxWOMOogKriZanN/1bJQE/ZL93A==", - "dev": true, - "requires": { - "@esbuild-kit/core-utils": "^3.0.0", - "get-tsconfig": "^4.2.0" - } - }, - "@esbuild/android-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.18.tgz", - "integrity": "sha512-5GT+kcs2WVGjVs7+boataCkO5Fg0y4kCjzkB5bAip7H4jfnOS3dA6KPiww9W1OEKTKeAcUVhdZGvgI65OXmUnw==", - "dev": true, - "optional": true - }, - "@esbuild/linux-loong64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.18.tgz", - "integrity": "sha512-L4jVKS82XVhw2nvzLg/19ClLWg0y27ulRwuP7lcyL6AbUWB5aPglXY3M21mauDQMDfRLs8cQmeT03r/+X3cZYQ==", - "dev": true, - "optional": true - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true - }, - "effect": { - "version": "2.0.0-next.54", - "resolved": "https://registry.npmjs.org/effect/-/effect-2.0.0-next.54.tgz", - "integrity": "sha512-qROhKMxlm6fpa90YRfWSgKeelDfhaDq2igPK+pIKupGehiCnZH4vd2qrY71HVZ10qZgXxh0VXpGyDQxJC+EQqw==", - "peer": true - }, - "esbuild": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.18.tgz", - "integrity": "sha512-x/R72SmW3sSFRm5zrrIjAhCeQSAWoni3CmHEqfQrZIQTM3lVCdehdwuIqaOtfC2slvpdlLa62GYoN8SxT23m6Q==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.15.18", - "@esbuild/linux-loong64": "0.15.18", - "esbuild-android-64": "0.15.18", - "esbuild-android-arm64": "0.15.18", - "esbuild-darwin-64": "0.15.18", - "esbuild-darwin-arm64": "0.15.18", - "esbuild-freebsd-64": "0.15.18", - "esbuild-freebsd-arm64": "0.15.18", - "esbuild-linux-32": "0.15.18", - "esbuild-linux-64": "0.15.18", - "esbuild-linux-arm": "0.15.18", - "esbuild-linux-arm64": "0.15.18", - "esbuild-linux-mips64le": "0.15.18", - "esbuild-linux-ppc64le": "0.15.18", - "esbuild-linux-riscv64": "0.15.18", - "esbuild-linux-s390x": "0.15.18", - "esbuild-netbsd-64": "0.15.18", - "esbuild-openbsd-64": "0.15.18", - "esbuild-sunos-64": "0.15.18", - "esbuild-windows-32": "0.15.18", - "esbuild-windows-64": "0.15.18", - "esbuild-windows-arm64": "0.15.18" - } - }, - "esbuild-android-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.18.tgz", - "integrity": "sha512-wnpt3OXRhcjfIDSZu9bnzT4/TNTDsOUvip0foZOUBG7QbSt//w3QV4FInVJxNhKc/ErhUxc5z4QjHtMi7/TbgA==", - "dev": true, - "optional": true - }, - "esbuild-android-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.18.tgz", - "integrity": "sha512-G4xu89B8FCzav9XU8EjsXacCKSG2FT7wW9J6hOc18soEHJdtWu03L3TQDGf0geNxfLTtxENKBzMSq9LlbjS8OQ==", - "dev": true, - "optional": true - }, - "esbuild-darwin-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.18.tgz", - "integrity": "sha512-2WAvs95uPnVJPuYKP0Eqx+Dl/jaYseZEUUT1sjg97TJa4oBtbAKnPnl3b5M9l51/nbx7+QAEtuummJZW0sBEmg==", - "dev": true, - "optional": true - }, - "esbuild-darwin-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.18.tgz", - "integrity": "sha512-tKPSxcTJ5OmNb1btVikATJ8NftlyNlc8BVNtyT/UAr62JFOhwHlnoPrhYWz09akBLHI9nElFVfWSTSRsrZiDUA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.18.tgz", - "integrity": "sha512-TT3uBUxkteAjR1QbsmvSsjpKjOX6UkCstr8nMr+q7zi3NuZ1oIpa8U41Y8I8dJH2fJgdC3Dj3CXO5biLQpfdZA==", - "dev": true, - "optional": true - }, - "esbuild-freebsd-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.18.tgz", - "integrity": "sha512-R/oVr+X3Tkh+S0+tL41wRMbdWtpWB8hEAMsOXDumSSa6qJR89U0S/PpLXrGF7Wk/JykfpWNokERUpCeHDl47wA==", - "dev": true, - "optional": true - }, - "esbuild-linux-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.18.tgz", - "integrity": "sha512-lphF3HiCSYtaa9p1DtXndiQEeQDKPl9eN/XNoBf2amEghugNuqXNZA/ZovthNE2aa4EN43WroO0B85xVSjYkbg==", - "dev": true, - "optional": true - }, - "esbuild-linux-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.18.tgz", - "integrity": "sha512-hNSeP97IviD7oxLKFuii5sDPJ+QHeiFTFLoLm7NZQligur8poNOWGIgpQ7Qf8Balb69hptMZzyOBIPtY09GZYw==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.18.tgz", - "integrity": "sha512-UH779gstRblS4aoS2qpMl3wjg7U0j+ygu3GjIeTonCcN79ZvpPee12Qun3vcdxX+37O5LFxz39XeW2I9bybMVA==", - "dev": true, - "optional": true - }, - "esbuild-linux-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.18.tgz", - "integrity": "sha512-54qr8kg/6ilcxd+0V3h9rjT4qmjc0CccMVWrjOEM/pEcUzt8X62HfBSeZfT2ECpM7104mk4yfQXkosY8Quptug==", - "dev": true, - "optional": true - }, - "esbuild-linux-mips64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.18.tgz", - "integrity": "sha512-Mk6Ppwzzz3YbMl/ZZL2P0q1tnYqh/trYZ1VfNP47C31yT0K8t9s7Z077QrDA/guU60tGNp2GOwCQnp+DYv7bxQ==", - "dev": true, - "optional": true - }, - "esbuild-linux-ppc64le": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.18.tgz", - "integrity": "sha512-b0XkN4pL9WUulPTa/VKHx2wLCgvIAbgwABGnKMY19WhKZPT+8BxhZdqz6EgkqCLld7X5qiCY2F/bfpUUlnFZ9w==", - "dev": true, - "optional": true - }, - "esbuild-linux-riscv64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.18.tgz", - "integrity": "sha512-ba2COaoF5wL6VLZWn04k+ACZjZ6NYniMSQStodFKH/Pu6RxzQqzsmjR1t9QC89VYJxBeyVPTaHuBMCejl3O/xg==", - "dev": true, - "optional": true - }, - "esbuild-linux-s390x": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.18.tgz", - "integrity": "sha512-VbpGuXEl5FCs1wDVp93O8UIzl3ZrglgnSQ+Hu79g7hZu6te6/YHgVJxCM2SqfIila0J3k0csfnf8VD2W7u2kzQ==", - "dev": true, - "optional": true - }, - "esbuild-netbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.18.tgz", - "integrity": "sha512-98ukeCdvdX7wr1vUYQzKo4kQ0N2p27H7I11maINv73fVEXt2kyh4K4m9f35U1K43Xc2QGXlzAw0K9yoU7JUjOg==", - "dev": true, - "optional": true - }, - "esbuild-openbsd-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.18.tgz", - "integrity": "sha512-yK5NCcH31Uae076AyQAXeJzt/vxIo9+omZRKj1pauhk3ITuADzuOx5N2fdHrAKPxN+zH3w96uFKlY7yIn490xQ==", - "dev": true, - "optional": true - }, - "esbuild-sunos-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.18.tgz", - "integrity": "sha512-On22LLFlBeLNj/YF3FT+cXcyKPEI263nflYlAhz5crxtp3yRG1Ugfr7ITyxmCmjm4vbN/dGrb/B7w7U8yJR9yw==", - "dev": true, - "optional": true - }, - "esbuild-windows-32": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.18.tgz", - "integrity": "sha512-o+eyLu2MjVny/nt+E0uPnBxYuJHBvho8vWsC2lV61A7wwTWC3jkN2w36jtA+yv1UgYkHRihPuQsL23hsCYGcOQ==", - "dev": true, - "optional": true - }, - "esbuild-windows-64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.18.tgz", - "integrity": "sha512-qinug1iTTaIIrCorAUjR0fcBk24fjzEedFYhhispP8Oc7SFvs+XeW3YpAKiKp8dRpizl4YYAhxMjlftAMJiaUw==", - "dev": true, - "optional": true - }, - "esbuild-windows-arm64": { - "version": "0.15.18", - "resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.18.tgz", - "integrity": "sha512-q9bsYzegpZcLziq0zgUi5KqGVtfhjxGbnksaBFYmWLxeV/S1fK4OLdq2DFYnXcLMjlZw2L0jLsk1eGoB522WXQ==", - "dev": true, - "optional": true - }, - "fast-check": { - "version": "3.13.2", - "resolved": "https://registry.npmjs.org/fast-check/-/fast-check-3.13.2.tgz", - "integrity": "sha512-ouTiFyeMoqmNg253xqy4NSacr5sHxH6pZpLOaHgaAdgZxFWdtsfxExwolpveoAE9CJdV+WYjqErNGef6SqA5Mg==", - "peer": true, - "requires": { - "pure-rand": "^6.0.0" + "node": ">=14.17" } - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, - "get-tsconfig": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.3.0.tgz", - "integrity": "sha512-YCcF28IqSay3fqpIu5y3Krg/utCBHBeoflkZyHj/QcqI2nrLPC3ZegS9CmIo+hJb8K7aiGsuUl7PwWVjNG2HQQ==", - "dev": true - }, - "pure-rand": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", - "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", - "peer": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "tsx": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.2.tgz", - "integrity": "sha512-ykAEkoBg30RXxeOMVeZwar+JH632dZn9EUJVyJwhfag62k6UO/dIyJEV58YuLF6e5BTdV/qmbQrpkWqjq9cUnQ==", - "dev": true, - "requires": { - "@esbuild-kit/cjs-loader": "^2.4.1", - "@esbuild-kit/core-utils": "^3.0.0", - "@esbuild-kit/esm-loader": "^2.5.4", - "fsevents": "~2.3.2" - } - }, - "typescript": { - "version": "4.9.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.4.tgz", - "integrity": "sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg==", - "dev": true } } } diff --git a/test/fixtures/typescript-effect-schema/package.json b/test/fixtures/typescript-effect-schema/package.json index 059f9656a..91b3ad6ce 100644 --- a/test/fixtures/typescript-effect-schema/package.json +++ b/test/fixtures/typescript-effect-schema/package.json @@ -10,9 +10,9 @@ "license": "Apache-2.0", "devDependencies": { "tsx": "^3.12.2", - "typescript": "^4.3.5" + "typescript": "^5.4.0" }, "dependencies": { - "@effect/schema": "^0.47.1" + "effect": "^3.10.0" } } diff --git a/test/fixtures/typescript-effect-schema/tsconfig.json b/test/fixtures/typescript-effect-schema/tsconfig.json index 3c2a002bd..a5befbe03 100644 --- a/test/fixtures/typescript-effect-schema/tsconfig.json +++ b/test/fixtures/typescript-effect-schema/tsconfig.json @@ -2,7 +2,5 @@ "compilerOptions": { "target": "es6" }, - "files": [ - "*.ts" - ] -} \ No newline at end of file + "files": ["*.ts"] +} diff --git a/test/fixtures/typescript-zod/main.ts b/test/fixtures/typescript-zod/main.ts index f7e16738c..8c207d961 100644 --- a/test/fixtures/typescript-zod/main.ts +++ b/test/fixtures/typescript-zod/main.ts @@ -2,7 +2,6 @@ import * as TopLevel from "./TopLevel"; import fs from "fs"; import process from "process"; - const sample = process.argv[2]; const json = fs.readFileSync(sample); @@ -10,8 +9,11 @@ const value = JSON.parse(json.toString()); let schema = TopLevel.TopLevelSchema ?? TopLevel.TopLevelElementSchema; if (!schema) { // Sometimes key is prefixed with funPrefixes (e.g. 2df80.json) - Object.keys(TopLevel).some(key => { - if (key.endsWith("TopLevelSchema") || key.endsWith("TopLevelElementSchema")) { + Object.keys(TopLevel).some((key) => { + if ( + key.endsWith("TopLevelSchema") || + key.endsWith("TopLevelElementSchema") + ) { schema = TopLevel[key]; return true; } @@ -24,7 +26,7 @@ if (!schema) { let backToJson: string; if (Array.isArray(value)) { - const parsedValue = value.map(v => schema.parse(v)); + const parsedValue = value.map((v) => schema.parse(v)); backToJson = JSON.stringify(parsedValue, null, 2); } else { const parsedValue = schema.parse(value); diff --git a/test/fixtures/typescript-zod/tsconfig.json b/test/fixtures/typescript-zod/tsconfig.json index 3c2a002bd..a5befbe03 100644 --- a/test/fixtures/typescript-zod/tsconfig.json +++ b/test/fixtures/typescript-zod/tsconfig.json @@ -2,7 +2,5 @@ "compilerOptions": { "target": "es6" }, - "files": [ - "*.ts" - ] -} \ No newline at end of file + "files": ["*.ts"] +} diff --git a/test/fixtures/typescript/main.ts b/test/fixtures/typescript/main.ts index 964d25d89..c22518dd2 100644 --- a/test/fixtures/typescript/main.ts +++ b/test/fixtures/typescript/main.ts @@ -7,7 +7,7 @@ const process = require("process"); const sample = process.argv[2]; const json = fs.readFileSync(sample); -let value = TopLevel.Convert.toTopLevel(json); -let backToJson = TopLevel.Convert.topLevelToJson(value); +const value = TopLevel.Convert.toTopLevel(json); +const backToJson = TopLevel.Convert.topLevelToJson(value); console.log(backToJson); diff --git a/test/fixtures/typescript/tsconfig.json b/test/fixtures/typescript/tsconfig.json index 3c2a002bd..a5befbe03 100644 --- a/test/fixtures/typescript/tsconfig.json +++ b/test/fixtures/typescript/tsconfig.json @@ -2,7 +2,5 @@ "compilerOptions": { "target": "es6" }, - "files": [ - "*.ts" - ] -} \ No newline at end of file + "files": ["*.ts"] +} diff --git a/test/inputs/json/misc/0a358.json b/test/inputs/json/misc/0a358.json index afb4007b5..40c8d99f3 100644 --- a/test/inputs/json/misc/0a358.json +++ b/test/inputs/json/misc/0a358.json @@ -1 +1,410 @@ -{"count": 245, "facets": {}, "results": [{"code": "ZW", "name": "Zimbabwe", "created_at": "2015-04-24T01:46:50.459583", "updated_at": "2015-04-24T01:46:50.459593", "uri": "http://api.lobbyfacts.eu/api/1/country/245", "id": 245}, {"code": "ZM", "name": "Zambia", "created_at": "2015-04-24T01:46:50.457459", "updated_at": "2015-04-24T01:46:50.457468", "uri": "http://api.lobbyfacts.eu/api/1/country/244", "id": 244}, {"code": "YE", "name": "Yemen", "created_at": "2015-04-24T01:46:50.454731", "updated_at": "2015-04-24T01:46:50.454741", "uri": "http://api.lobbyfacts.eu/api/1/country/243", "id": 243}, {"code": "EH", "name": "Western Sahara", "created_at": "2015-04-24T01:46:50.452002", "updated_at": "2015-04-24T01:46:50.452011", "uri": "http://api.lobbyfacts.eu/api/1/country/242", "id": 242}, {"code": "WF", "name": "Wallis & Futuna", "created_at": "2015-04-24T01:46:50.449346", "updated_at": "2015-04-24T01:46:50.449355", "uri": "http://api.lobbyfacts.eu/api/1/country/241", "id": 241}, {"code": "VN", "name": "Vietnam", "created_at": "2015-04-24T01:46:50.446644", "updated_at": "2015-04-24T01:46:50.446652", "uri": "http://api.lobbyfacts.eu/api/1/country/240", "id": 240}, {"code": "VE", "name": "Venezuela", "created_at": "2015-04-24T01:46:50.444031", "updated_at": "2015-04-24T01:46:50.444040", "uri": "http://api.lobbyfacts.eu/api/1/country/239", "id": 239}, {"code": "VU", "name": "Vanuatu", "created_at": "2015-04-24T01:46:50.441423", "updated_at": "2015-04-24T01:46:50.441433", "uri": "http://api.lobbyfacts.eu/api/1/country/238", "id": 238}, {"code": "UZ", "name": "Uzbekistan", "created_at": "2015-04-24T01:46:50.438748", "updated_at": "2015-04-24T01:46:50.438757", "uri": "http://api.lobbyfacts.eu/api/1/country/237", "id": 237}, {"code": "UY", "name": "Uruguay", "created_at": "2015-04-24T01:46:50.435761", "updated_at": "2015-04-24T01:46:50.435770", "uri": "http://api.lobbyfacts.eu/api/1/country/236", "id": 236}, {"code": "VI", "name": "United States Virgin Islands", "created_at": "2015-04-24T01:46:50.433229", "updated_at": "2015-04-24T01:46:50.433238", "uri": "http://api.lobbyfacts.eu/api/1/country/235", "id": 235}, {"code": "US", "name": "United States", "created_at": "2015-04-24T01:46:50.430335", "updated_at": "2015-04-24T01:46:50.430340", "uri": "http://api.lobbyfacts.eu/api/1/country/234", "id": 234}, {"code": "GB", "name": "United Kingdom", "created_at": "2015-04-24T01:46:50.427956", "updated_at": "2015-04-24T01:46:50.427961", "uri": "http://api.lobbyfacts.eu/api/1/country/233", "id": 233}, {"code": "AE", "name": "United Arab Emirates", "created_at": "2015-04-24T01:46:50.425383", "updated_at": "2015-04-24T01:46:50.425392", "uri": "http://api.lobbyfacts.eu/api/1/country/232", "id": 232}, {"code": "UA", "name": "Ukraine", "created_at": "2015-04-24T01:46:50.422970", "updated_at": "2015-04-24T01:46:50.422980", "uri": "http://api.lobbyfacts.eu/api/1/country/231", "id": 231}, {"code": "UG", "name": "Uganda", "created_at": "2015-04-24T01:46:50.419963", "updated_at": "2015-04-24T01:46:50.419968", "uri": "http://api.lobbyfacts.eu/api/1/country/230", "id": 230}, {"code": "TV", "name": "Tuvalu", "created_at": "2015-04-24T01:46:50.417896", "updated_at": "2015-04-24T01:46:50.417906", "uri": "http://api.lobbyfacts.eu/api/1/country/229", "id": 229}, {"code": "TC", "name": "Turks & Caicos Islands", "created_at": "2015-04-24T01:46:50.414854", "updated_at": "2015-04-24T01:46:50.414868", "uri": "http://api.lobbyfacts.eu/api/1/country/228", "id": 228}, {"code": "TM", "name": "Turkmenistan", "created_at": "2015-04-24T01:46:50.412601", "updated_at": "2015-04-24T01:46:50.412605", "uri": "http://api.lobbyfacts.eu/api/1/country/227", "id": 227}, {"code": "TR", "name": "Turkey", "created_at": "2015-04-24T01:46:50.411105", "updated_at": "2015-04-24T01:46:50.411110", "uri": "http://api.lobbyfacts.eu/api/1/country/226", "id": 226}, {"code": "TN", "name": "Tunisia", "created_at": "2015-04-24T01:46:50.409535", "updated_at": "2015-04-24T01:46:50.409539", "uri": "http://api.lobbyfacts.eu/api/1/country/225", "id": 225}, {"code": "TT", "name": "Trinidad & Tobago", "created_at": "2015-04-24T01:46:50.408030", "updated_at": "2015-04-24T01:46:50.408034", "uri": "http://api.lobbyfacts.eu/api/1/country/224", "id": 224}, {"code": "TO", "name": "Tonga", "created_at": "2015-04-24T01:46:50.406306", "updated_at": "2015-04-24T01:46:50.406311", "uri": "http://api.lobbyfacts.eu/api/1/country/223", "id": 223}, {"code": "TK", "name": "Tokelau", "created_at": "2015-04-24T01:46:50.404794", "updated_at": "2015-04-24T01:46:50.404799", "uri": "http://api.lobbyfacts.eu/api/1/country/222", "id": 222}, {"code": "TG", "name": "Togo", "created_at": "2015-04-24T01:46:50.403306", "updated_at": "2015-04-24T01:46:50.403310", "uri": "http://api.lobbyfacts.eu/api/1/country/221", "id": 221}, {"code": "TH", "name": "Thailand", "created_at": "2015-04-24T01:46:50.400840", "updated_at": "2015-04-24T01:46:50.400849", "uri": "http://api.lobbyfacts.eu/api/1/country/220", "id": 220}, {"code": "TZ", "name": "Tanzania", "created_at": "2015-04-24T01:46:50.397846", "updated_at": "2015-04-24T01:46:50.397855", "uri": "http://api.lobbyfacts.eu/api/1/country/219", "id": 219}, {"code": "TJ", "name": "Tajikistan", "created_at": "2015-04-24T01:46:50.394924", "updated_at": "2015-04-24T01:46:50.394933", "uri": "http://api.lobbyfacts.eu/api/1/country/218", "id": 218}, {"code": "TW", "name": "Taiwan", "created_at": "2015-04-24T01:46:50.391969", "updated_at": "2015-04-24T01:46:50.391978", "uri": "http://api.lobbyfacts.eu/api/1/country/217", "id": 217}, {"code": "SY", "name": "Syria", "created_at": "2015-04-24T01:46:50.389120", "updated_at": "2015-04-24T01:46:50.389124", "uri": "http://api.lobbyfacts.eu/api/1/country/216", "id": 216}, {"code": "CH", "name": "Switzerland", "created_at": "2015-04-24T01:46:50.386939", "updated_at": "2015-04-24T01:46:50.386943", "uri": "http://api.lobbyfacts.eu/api/1/country/215", "id": 215}, {"code": "SE", "name": "Sweden", "created_at": "2015-04-24T01:46:50.385345", "updated_at": "2015-04-24T01:46:50.385349", "uri": "http://api.lobbyfacts.eu/api/1/country/214", "id": 214}, {"code": "SZ", "name": "Swaziland", "created_at": "2015-04-24T01:46:50.383834", "updated_at": "2015-04-24T01:46:50.383838", "uri": "http://api.lobbyfacts.eu/api/1/country/213", "id": 213}, {"code": "SR", "name": "Suriname", "created_at": "2015-04-24T01:46:50.382073", "updated_at": "2015-04-24T01:46:50.382078", "uri": "http://api.lobbyfacts.eu/api/1/country/212", "id": 212}, {"code": "SD", "name": "Sudan", "created_at": "2015-04-24T01:46:50.380114", "updated_at": "2015-04-24T01:46:50.380119", "uri": "http://api.lobbyfacts.eu/api/1/country/211", "id": 211}, {"code": "LK", "name": "Sri Lanka", "created_at": "2015-04-24T01:46:50.378189", "updated_at": "2015-04-24T01:46:50.378195", "uri": "http://api.lobbyfacts.eu/api/1/country/210", "id": 210}, {"code": "ES", "name": "Spain", "created_at": "2015-04-24T01:46:50.376105", "updated_at": "2015-04-24T01:46:50.376109", "uri": "http://api.lobbyfacts.eu/api/1/country/209", "id": 209}, {"code": "SS", "name": "South Sudan", "created_at": "2015-04-24T01:46:50.373942", "updated_at": "2015-04-24T01:46:50.373946", "uri": "http://api.lobbyfacts.eu/api/1/country/208", "id": 208}, {"code": "KR", "name": "South Korea", "created_at": "2015-04-24T01:46:50.371790", "updated_at": "2015-04-24T01:46:50.371794", "uri": "http://api.lobbyfacts.eu/api/1/country/207", "id": 207}, {"code": "GS", "name": "South Georgia & The South Sandwish Islands", "created_at": "2015-04-24T01:46:50.369460", "updated_at": "2015-04-24T01:46:50.369465", "uri": "http://api.lobbyfacts.eu/api/1/country/206", "id": 206}, {"code": "ZA", "name": "South Africa", "created_at": "2015-04-24T01:46:50.367247", "updated_at": "2015-04-24T01:46:50.367252", "uri": "http://api.lobbyfacts.eu/api/1/country/205", "id": 205}, {"code": "SO", "name": "Somaliland", "created_at": "2015-04-24T01:46:50.362905", "updated_at": "2016-09-18T18:34:35.724427", "uri": "http://api.lobbyfacts.eu/api/1/country/204", "id": 204}, {"code": "SB", "name": "Solomon Islands", "created_at": "2015-04-24T01:46:50.360631", "updated_at": "2015-04-24T01:46:50.360635", "uri": "http://api.lobbyfacts.eu/api/1/country/203", "id": 203}, {"code": "SI", "name": "Slovenia", "created_at": "2015-04-24T01:46:50.358394", "updated_at": "2015-04-24T01:46:50.358399", "uri": "http://api.lobbyfacts.eu/api/1/country/202", "id": 202}, {"code": "SK", "name": "Slovakia", "created_at": "2015-04-24T01:46:50.356154", "updated_at": "2015-04-24T01:46:50.356158", "uri": "http://api.lobbyfacts.eu/api/1/country/201", "id": 201}, {"code": "SX", "name": "Sint Maarten", "created_at": "2015-04-24T01:46:50.353807", "updated_at": "2015-04-24T01:46:50.353811", "uri": "http://api.lobbyfacts.eu/api/1/country/200", "id": 200}, {"code": "SG", "name": "Singapore", "created_at": "2015-04-24T01:46:50.349354", "updated_at": "2015-04-24T01:46:50.349358", "uri": "http://api.lobbyfacts.eu/api/1/country/199", "id": 199}, {"code": "SL", "name": "Sierra Leone", "created_at": "2015-04-24T01:46:50.347186", "updated_at": "2015-04-24T01:46:50.347190", "uri": "http://api.lobbyfacts.eu/api/1/country/198", "id": 198}, {"code": "SC", "name": "Seychelles", "created_at": "2015-04-24T01:46:50.344980", "updated_at": "2015-04-24T01:46:50.344984", "uri": "http://api.lobbyfacts.eu/api/1/country/197", "id": 197}, {"code": "RS", "name": "Serbia", "created_at": "2015-04-24T01:46:50.342496", "updated_at": "2015-04-24T01:46:50.342501", "uri": "http://api.lobbyfacts.eu/api/1/country/196", "id": 196}], "next": "http://api.lobbyfacts.eu/api/1/country?limit=50&offset=50", "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 245, + "facets": {}, + "results": [ + { + "code": "ZW", + "name": "Zimbabwe", + "created_at": "2015-04-24T01:46:50.459583Z", + "updated_at": "2015-04-24T01:46:50.459593Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/245", + "id": 245 + }, + { + "code": "ZM", + "name": "Zambia", + "created_at": "2015-04-24T01:46:50.457459Z", + "updated_at": "2015-04-24T01:46:50.457468Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/244", + "id": 244 + }, + { + "code": "YE", + "name": "Yemen", + "created_at": "2015-04-24T01:46:50.454731Z", + "updated_at": "2015-04-24T01:46:50.454741Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/243", + "id": 243 + }, + { + "code": "EH", + "name": "Western Sahara", + "created_at": "2015-04-24T01:46:50.452002Z", + "updated_at": "2015-04-24T01:46:50.452011Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/242", + "id": 242 + }, + { + "code": "WF", + "name": "Wallis & Futuna", + "created_at": "2015-04-24T01:46:50.449346Z", + "updated_at": "2015-04-24T01:46:50.449355Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/241", + "id": 241 + }, + { + "code": "VN", + "name": "Vietnam", + "created_at": "2015-04-24T01:46:50.446644Z", + "updated_at": "2015-04-24T01:46:50.446652Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/240", + "id": 240 + }, + { + "code": "VE", + "name": "Venezuela", + "created_at": "2015-04-24T01:46:50.444031Z", + "updated_at": "2015-04-24T01:46:50.444040Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/239", + "id": 239 + }, + { + "code": "VU", + "name": "Vanuatu", + "created_at": "2015-04-24T01:46:50.441423Z", + "updated_at": "2015-04-24T01:46:50.441433Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/238", + "id": 238 + }, + { + "code": "UZ", + "name": "Uzbekistan", + "created_at": "2015-04-24T01:46:50.438748Z", + "updated_at": "2015-04-24T01:46:50.438757Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/237", + "id": 237 + }, + { + "code": "UY", + "name": "Uruguay", + "created_at": "2015-04-24T01:46:50.435761Z", + "updated_at": "2015-04-24T01:46:50.435770Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/236", + "id": 236 + }, + { + "code": "VI", + "name": "United States Virgin Islands", + "created_at": "2015-04-24T01:46:50.433229Z", + "updated_at": "2015-04-24T01:46:50.433238Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/235", + "id": 235 + }, + { + "code": "US", + "name": "United States", + "created_at": "2015-04-24T01:46:50.430335Z", + "updated_at": "2015-04-24T01:46:50.430340Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/234", + "id": 234 + }, + { + "code": "GB", + "name": "United Kingdom", + "created_at": "2015-04-24T01:46:50.427956Z", + "updated_at": "2015-04-24T01:46:50.427961Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/233", + "id": 233 + }, + { + "code": "AE", + "name": "United Arab Emirates", + "created_at": "2015-04-24T01:46:50.425383Z", + "updated_at": "2015-04-24T01:46:50.425392Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/232", + "id": 232 + }, + { + "code": "UA", + "name": "Ukraine", + "created_at": "2015-04-24T01:46:50.422970Z", + "updated_at": "2015-04-24T01:46:50.422980Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/231", + "id": 231 + }, + { + "code": "UG", + "name": "Uganda", + "created_at": "2015-04-24T01:46:50.419963Z", + "updated_at": "2015-04-24T01:46:50.419968Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/230", + "id": 230 + }, + { + "code": "TV", + "name": "Tuvalu", + "created_at": "2015-04-24T01:46:50.417896Z", + "updated_at": "2015-04-24T01:46:50.417906Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/229", + "id": 229 + }, + { + "code": "TC", + "name": "Turks & Caicos Islands", + "created_at": "2015-04-24T01:46:50.414854Z", + "updated_at": "2015-04-24T01:46:50.414868Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/228", + "id": 228 + }, + { + "code": "TM", + "name": "Turkmenistan", + "created_at": "2015-04-24T01:46:50.412601Z", + "updated_at": "2015-04-24T01:46:50.412605Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/227", + "id": 227 + }, + { + "code": "TR", + "name": "Turkey", + "created_at": "2015-04-24T01:46:50.411105Z", + "updated_at": "2015-04-24T01:46:50.411110Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/226", + "id": 226 + }, + { + "code": "TN", + "name": "Tunisia", + "created_at": "2015-04-24T01:46:50.409535Z", + "updated_at": "2015-04-24T01:46:50.409539Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/225", + "id": 225 + }, + { + "code": "TT", + "name": "Trinidad & Tobago", + "created_at": "2015-04-24T01:46:50.408030Z", + "updated_at": "2015-04-24T01:46:50.408034Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/224", + "id": 224 + }, + { + "code": "TO", + "name": "Tonga", + "created_at": "2015-04-24T01:46:50.406306Z", + "updated_at": "2015-04-24T01:46:50.406311Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/223", + "id": 223 + }, + { + "code": "TK", + "name": "Tokelau", + "created_at": "2015-04-24T01:46:50.404794Z", + "updated_at": "2015-04-24T01:46:50.404799Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/222", + "id": 222 + }, + { + "code": "TG", + "name": "Togo", + "created_at": "2015-04-24T01:46:50.403306Z", + "updated_at": "2015-04-24T01:46:50.403310Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/221", + "id": 221 + }, + { + "code": "TH", + "name": "Thailand", + "created_at": "2015-04-24T01:46:50.400840Z", + "updated_at": "2015-04-24T01:46:50.400849Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/220", + "id": 220 + }, + { + "code": "TZ", + "name": "Tanzania", + "created_at": "2015-04-24T01:46:50.397846Z", + "updated_at": "2015-04-24T01:46:50.397855Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/219", + "id": 219 + }, + { + "code": "TJ", + "name": "Tajikistan", + "created_at": "2015-04-24T01:46:50.394924Z", + "updated_at": "2015-04-24T01:46:50.394933Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/218", + "id": 218 + }, + { + "code": "TW", + "name": "Taiwan", + "created_at": "2015-04-24T01:46:50.391969Z", + "updated_at": "2015-04-24T01:46:50.391978Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/217", + "id": 217 + }, + { + "code": "SY", + "name": "Syria", + "created_at": "2015-04-24T01:46:50.389120Z", + "updated_at": "2015-04-24T01:46:50.389124Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/216", + "id": 216 + }, + { + "code": "CH", + "name": "Switzerland", + "created_at": "2015-04-24T01:46:50.386939Z", + "updated_at": "2015-04-24T01:46:50.386943Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/215", + "id": 215 + }, + { + "code": "SE", + "name": "Sweden", + "created_at": "2015-04-24T01:46:50.385345Z", + "updated_at": "2015-04-24T01:46:50.385349Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/214", + "id": 214 + }, + { + "code": "SZ", + "name": "Swaziland", + "created_at": "2015-04-24T01:46:50.383834Z", + "updated_at": "2015-04-24T01:46:50.383838Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/213", + "id": 213 + }, + { + "code": "SR", + "name": "Suriname", + "created_at": "2015-04-24T01:46:50.382073Z", + "updated_at": "2015-04-24T01:46:50.382078Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/212", + "id": 212 + }, + { + "code": "SD", + "name": "Sudan", + "created_at": "2015-04-24T01:46:50.380114Z", + "updated_at": "2015-04-24T01:46:50.380119Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/211", + "id": 211 + }, + { + "code": "LK", + "name": "Sri Lanka", + "created_at": "2015-04-24T01:46:50.378189Z", + "updated_at": "2015-04-24T01:46:50.378195Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/210", + "id": 210 + }, + { + "code": "ES", + "name": "Spain", + "created_at": "2015-04-24T01:46:50.376105Z", + "updated_at": "2015-04-24T01:46:50.376109Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/209", + "id": 209 + }, + { + "code": "SS", + "name": "South Sudan", + "created_at": "2015-04-24T01:46:50.373942Z", + "updated_at": "2015-04-24T01:46:50.373946Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/208", + "id": 208 + }, + { + "code": "KR", + "name": "South Korea", + "created_at": "2015-04-24T01:46:50.371790Z", + "updated_at": "2015-04-24T01:46:50.371794Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/207", + "id": 207 + }, + { + "code": "GS", + "name": "South Georgia & The South Sandwish Islands", + "created_at": "2015-04-24T01:46:50.369460Z", + "updated_at": "2015-04-24T01:46:50.369465Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/206", + "id": 206 + }, + { + "code": "ZA", + "name": "South Africa", + "created_at": "2015-04-24T01:46:50.367247Z", + "updated_at": "2015-04-24T01:46:50.367252Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/205", + "id": 205 + }, + { + "code": "SO", + "name": "Somaliland", + "created_at": "2015-04-24T01:46:50.362905Z", + "updated_at": "2016-09-18T18:34:35.724427Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/204", + "id": 204 + }, + { + "code": "SB", + "name": "Solomon Islands", + "created_at": "2015-04-24T01:46:50.360631Z", + "updated_at": "2015-04-24T01:46:50.360635Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/203", + "id": 203 + }, + { + "code": "SI", + "name": "Slovenia", + "created_at": "2015-04-24T01:46:50.358394Z", + "updated_at": "2015-04-24T01:46:50.358399Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/202", + "id": 202 + }, + { + "code": "SK", + "name": "Slovakia", + "created_at": "2015-04-24T01:46:50.356154Z", + "updated_at": "2015-04-24T01:46:50.356158Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/201", + "id": 201 + }, + { + "code": "SX", + "name": "Sint Maarten", + "created_at": "2015-04-24T01:46:50.353807Z", + "updated_at": "2015-04-24T01:46:50.353811Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/200", + "id": 200 + }, + { + "code": "SG", + "name": "Singapore", + "created_at": "2015-04-24T01:46:50.349354Z", + "updated_at": "2015-04-24T01:46:50.349358Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/199", + "id": 199 + }, + { + "code": "SL", + "name": "Sierra Leone", + "created_at": "2015-04-24T01:46:50.347186Z", + "updated_at": "2015-04-24T01:46:50.347190Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/198", + "id": 198 + }, + { + "code": "SC", + "name": "Seychelles", + "created_at": "2015-04-24T01:46:50.344980Z", + "updated_at": "2015-04-24T01:46:50.344984Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/197", + "id": 197 + }, + { + "code": "RS", + "name": "Serbia", + "created_at": "2015-04-24T01:46:50.342496Z", + "updated_at": "2015-04-24T01:46:50.342501Z", + "uri": "http://api.lobbyfacts.eu/api/1/country/196", + "id": 196 + } + ], + "next": "http://api.lobbyfacts.eu/api/1/country?limit=50&offset=50", + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/misc/26c9c.json b/test/inputs/json/misc/26c9c.json index 3629d5f9d..3c895e5a6 100644 --- a/test/inputs/json/misc/26c9c.json +++ b/test/inputs/json/misc/26c9c.json @@ -1,1063 +1,10499 @@ { - "meta" : { - "view" : { - "id" : "d6yy-54nr", - "name" : "Lottery Powerball Winning Numbers: Beginning 2010", - "attribution" : "New York State Gaming Commission", - "attributionLink" : "http://nylottery.ny.gov/wps/portal/Home/Lottery/home/your+lottery/drawing+results/drawingresults_powerball", - "averageRating" : 0, - "category" : "Government & Finance", - "createdAt" : 1362178006, - "description" : "Go to http://on.ny.gov/1GpWiHD on the New York Lottery website for past Powerball results and payouts.", - "displayType" : "table", - "downloadCount" : 225121, - "hideFromCatalog" : false, - "hideFromDataJson" : false, - "indexUpdatedAt" : 1501149821, - "locale" : "", - "newBackend" : false, - "numberOfComments" : 0, - "oid" : 26467445, - "provenance" : "official", - "publicationAppendEnabled" : false, - "publicationDate" : 1501149666, - "publicationGroup" : 708088, - "publicationStage" : "published", - "rowsUpdatedAt" : 1501149663, - "rowsUpdatedBy" : "xzik-pf59", - "tableId" : 14357003, - "totalTimesRated" : 0, - "viewCount" : 279585, - "viewLastModified" : 1501149666, - "viewType" : "tabular", - "columns" : [ { - "id" : -1, - "name" : "sid", - "dataTypeName" : "meta_data", - "fieldName" : ":sid", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "id", - "dataTypeName" : "meta_data", - "fieldName" : ":id", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "position", - "dataTypeName" : "meta_data", - "fieldName" : ":position", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "created_at", - "dataTypeName" : "meta_data", - "fieldName" : ":created_at", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "created_meta", - "dataTypeName" : "meta_data", - "fieldName" : ":created_meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "updated_at", - "dataTypeName" : "meta_data", - "fieldName" : ":updated_at", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "updated_meta", - "dataTypeName" : "meta_data", - "fieldName" : ":updated_meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "meta", - "dataTypeName" : "meta_data", - "fieldName" : ":meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : 313053589, - "name" : "Draw Date", - "dataTypeName" : "calendar_date", - "fieldName" : "draw_date", - "position" : 1, - "renderTypeName" : "calendar_date", - "tableColumnId" : 8275908, - "width" : 141, - "cachedContents" : { - "largest" : "2017-07-26T00:00:00", - "non_null" : 780, - "null" : 0, - "top" : [ { - "item" : "2017-07-26T00:00:00", - "count" : 20 - } ], - "smallest" : "2010-02-03T00:00:00" - }, - "format" : { - "view" : "date", - "align" : "center" + "meta": { + "view": { + "id": "d6yy-54nr", + "name": "Lottery Powerball Winning Numbers: Beginning 2010", + "attribution": "New York State Gaming Commission", + "attributionLink": "http://nylottery.ny.gov/wps/portal/Home/Lottery/home/your+lottery/drawing+results/drawingresults_powerball", + "averageRating": 0, + "category": "Government & Finance", + "createdAt": 1362178006, + "description": "Go to http://on.ny.gov/1GpWiHD on the New York Lottery website for past Powerball results and payouts.", + "displayType": "table", + "downloadCount": 225121, + "hideFromCatalog": false, + "hideFromDataJson": false, + "indexUpdatedAt": 1501149821, + "locale": "", + "newBackend": false, + "numberOfComments": 0, + "oid": 26467445, + "provenance": "official", + "publicationAppendEnabled": false, + "publicationDate": 1501149666, + "publicationGroup": 708088, + "publicationStage": "published", + "rowsUpdatedAt": 1501149663, + "rowsUpdatedBy": "xzik-pf59", + "tableId": 14357003, + "totalTimesRated": 0, + "viewCount": 279585, + "viewLastModified": 1501149666, + "viewType": "tabular", + "columns": [ + { + "id": -1, + "name": "sid", + "dataTypeName": "meta_data", + "fieldName": ":sid", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "id", + "dataTypeName": "meta_data", + "fieldName": ":id", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "position", + "dataTypeName": "meta_data", + "fieldName": ":position", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "created_at", + "dataTypeName": "meta_data", + "fieldName": ":created_at", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "created_meta", + "dataTypeName": "meta_data", + "fieldName": ":created_meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "updated_at", + "dataTypeName": "meta_data", + "fieldName": ":updated_at", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "updated_meta", + "dataTypeName": "meta_data", + "fieldName": ":updated_meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "meta", + "dataTypeName": "meta_data", + "fieldName": ":meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": 313053589, + "name": "Draw Date", + "dataTypeName": "calendar_date", + "fieldName": "draw_date", + "position": 1, + "renderTypeName": "calendar_date", + "tableColumnId": 8275908, + "width": 141, + "cachedContents": { + "largest": "2017-07-26T00:00:00Z", + "non_null": 780, + "null": 0, + "top": [ + { + "item": "2017-07-26T00:00:00Z", + "count": 20 + } + ], + "smallest": "2010-02-03T00:00:00Z" + }, + "format": { + "view": "date", + "align": "center" + } + }, + { + "id": 313053590, + "name": "Winning Numbers", + "dataTypeName": "text", + "fieldName": "winning_numbers", + "position": 2, + "renderTypeName": "text", + "tableColumnId": 8275909, + "width": 186, + "cachedContents": { + "largest": "50 51 59 61 63 04", + "non_null": 780, + "null": 0, + "top": [ + { + "item": "07 19 21 42 69 12", + "count": 20 + } + ], + "smallest": "01 02 07 09 55 29" + }, + "format": { + "align": "center" + } + }, + { + "id": 313053591, + "name": "Multiplier", + "dataTypeName": "number", + "fieldName": "multiplier", + "position": 3, + "renderTypeName": "number", + "tableColumnId": 8275910, + "width": 136, + "cachedContents": { + "largest": "10", + "non_null": 570, + "average": "2.975438596491228", + "null": 210, + "top": [ + { + "item": "2", + "count": 20 + }, + { + "item": "3", + "count": 19 + }, + { + "item": "5", + "count": 18 + }, + { + "item": "4", + "count": 17 + }, + { + "item": "10", + "count": 16 + } + ], + "smallest": "2", + "sum": "1696" + }, + "format": { + "precisionStyle": "standard", + "noCommas": "false", + "align": "center" + } + } + ], + "grants": [ + { + "inherited": false, + "type": "viewer", + "flags": ["public"] + } + ], + "metadata": { + "custom_fields": { + "Notes": { + "Notes": "The information contained on these pages is believed to be accurate. In the event of a discrepancy between the information displayed on this Web site concerning winning numbers and payouts and the information contained in the official and certified files maintained by the New York Lottery's Drawing Unit, those maintained by the Drawing Unit shall prevail." + }, + "Common Core": { + "Contact Email": "opendata@its.ny.gov", + "Publisher": "State of New York", + "Contact Name": "Open Data NY" + }, + "Dataset Summary": { + "Granularity": "Draw Date", + "Coverage": "Statewide", + "Data Frequency": "Twice weekly", + "Posting Frequency": "Twice weekly", + "Units": "Drawings Unit", + "Dataset Owner": "Lottery", + "Organization": "The New York Lottery", + "Time Period": "02/03/2010 to present", + "Contact Information": "Info@gaming.ny.gov" + }, + "Additional Resources": { + "See Also ": "http://www.powerball.com/pb_home.asp", + "See Also": "http://www.gaming.ny.gov/" + }, + "Dataset Information": { + "Agency": "Gaming Commission, New York State" + } + }, + "renderTypeConfig": { + "visible": { + "table": true + } + }, + "availableDisplayTypes": ["table", "fatrow", "page"], + "jsonQuery": { + "order": [ + { + "ascending": false, + "columnFieldName": "draw_date" + } + ] + }, + "rdfSubject": "0", + "attachments": [ + { + "blobId": "A13C17ED-D278-428F-BC24-CAAE9D82A787", + "assetId": "", + "name": "NYSGAM_Powerball_Overview.pdf", + "filename": "NYSGAM_Powerball_Overview.pdf" + }, + { + "blobId": "5A0D4D17-A176-44D4-B5A6-B8667F7D14C6", + "assetId": "", + "name": "NYSGAM_Powerball_DataDictionary.pdf", + "filename": "NYSGAM_Powerball_Winning_Numbers__DataDictionary.pdf" + } + ] + }, + "owner": { + "id": "xzik-pf59", + "displayName": "NY Open Data", + "profileImageUrlLarge": "/api/users/xzik-pf59/profile_images/LARGE", + "profileImageUrlMedium": "/api/users/xzik-pf59/profile_images/THUMB", + "profileImageUrlSmall": "/api/users/xzik-pf59/profile_images/TINY", + "roleName": "publisher", + "screenName": "NY Open Data", + "rights": [ + "create_datasets", + "edit_others_datasets", + "edit_nominations", + "approve_nominations", + "moderate_comments", + "manage_stories", + "feature_items", + "change_configurations", + "view_domain", + "view_others_datasets", + "create_pages", + "edit_pages", + "view_goals", + "view_dashboards", + "edit_goals", + "edit_dashboards", + "manage_provenance", + "view_story", + "view_unpublished_story", + "view_all_dataset_status_logs", + "use_data_connectors" + ] + }, + "query": { + "orderBys": [ + { + "ascending": false, + "expression": { + "columnId": 313053589, + "type": "column" + } + } + ] + }, + "rights": ["read"], + "tableAuthor": { + "id": "xzik-pf59", + "displayName": "NY Open Data", + "profileImageUrlLarge": "/api/users/xzik-pf59/profile_images/LARGE", + "profileImageUrlMedium": "/api/users/xzik-pf59/profile_images/THUMB", + "profileImageUrlSmall": "/api/users/xzik-pf59/profile_images/TINY", + "roleName": "publisher", + "screenName": "NY Open Data", + "rights": [ + "create_datasets", + "edit_others_datasets", + "edit_nominations", + "approve_nominations", + "moderate_comments", + "manage_stories", + "feature_items", + "change_configurations", + "view_domain", + "view_others_datasets", + "create_pages", + "edit_pages", + "view_goals", + "view_dashboards", + "edit_goals", + "edit_dashboards", + "manage_provenance", + "view_story", + "view_unpublished_story", + "view_all_dataset_status_logs", + "use_data_connectors" + ] + }, + "tags": ["powerball", "new york lottery", "winning", "results"], + "flags": ["default", "restorable", "restorePossibleForType"] } - }, { - "id" : 313053590, - "name" : "Winning Numbers", - "dataTypeName" : "text", - "fieldName" : "winning_numbers", - "position" : 2, - "renderTypeName" : "text", - "tableColumnId" : 8275909, - "width" : 186, - "cachedContents" : { - "largest" : "50 51 59 61 63 04", - "non_null" : 780, - "null" : 0, - "top" : [ { - "item" : "07 19 21 42 69 12", - "count" : 20 - } ], - "smallest" : "01 02 07 09 55 29" - }, - "format" : { - "align" : "center" - } - }, { - "id" : 313053591, - "name" : "Multiplier", - "dataTypeName" : "number", - "fieldName" : "multiplier", - "position" : 3, - "renderTypeName" : "number", - "tableColumnId" : 8275910, - "width" : 136, - "cachedContents" : { - "largest" : "10", - "non_null" : 570, - "average" : "2.975438596491228", - "null" : 210, - "top" : [ { - "item" : "2", - "count" : 20 - }, { - "item" : "3", - "count" : 19 - }, { - "item" : "5", - "count" : 18 - }, { - "item" : "4", - "count" : 17 - }, { - "item" : "10", - "count" : 16 - } ], - "smallest" : "2", - "sum" : "1696" - }, - "format" : { - "precisionStyle" : "standard", - "noCommas" : "false", - "align" : "center" - } - } ], - "grants" : [ { - "inherited" : false, - "type" : "viewer", - "flags" : [ "public" ] - } ], - "metadata" : { - "custom_fields" : { - "Notes" : { - "Notes" : "The information contained on these pages is believed to be accurate. In the event of a discrepancy between the information displayed on this Web site concerning winning numbers and payouts and the information contained in the official and certified files maintained by the New York Lottery's Drawing Unit, those maintained by the Drawing Unit shall prevail." - }, - "Common Core" : { - "Contact Email" : "opendata@its.ny.gov", - "Publisher" : "State of New York", - "Contact Name" : "Open Data NY" - }, - "Dataset Summary" : { - "Granularity" : "Draw Date", - "Coverage" : "Statewide", - "Data Frequency" : "Twice weekly", - "Posting Frequency" : "Twice weekly", - "Units" : "Drawings Unit", - "Dataset Owner" : "Lottery", - "Organization" : "The New York Lottery", - "Time Period" : "02/03/2010 to present", - "Contact Information" : "Info@gaming.ny.gov" - }, - "Additional Resources" : { - "See Also " : "http://www.powerball.com/pb_home.asp", - "See Also" : "http://www.gaming.ny.gov/" - }, - "Dataset Information" : { - "Agency" : "Gaming Commission, New York State" - } - }, - "renderTypeConfig" : { - "visible" : { - "table" : true - } - }, - "availableDisplayTypes" : [ "table", "fatrow", "page" ], - "jsonQuery" : { - "order" : [ { - "ascending" : false, - "columnFieldName" : "draw_date" - } ] - }, - "rdfSubject" : "0", - "attachments" : [ { - "blobId" : "A13C17ED-D278-428F-BC24-CAAE9D82A787", - "assetId" : "", - "name" : "NYSGAM_Powerball_Overview.pdf", - "filename" : "NYSGAM_Powerball_Overview.pdf" - }, { - "blobId" : "5A0D4D17-A176-44D4-B5A6-B8667F7D14C6", - "assetId" : "", - "name" : "NYSGAM_Powerball_DataDictionary.pdf", - "filename" : "NYSGAM_Powerball_Winning_Numbers__DataDictionary.pdf" - } ] - }, - "owner" : { - "id" : "xzik-pf59", - "displayName" : "NY Open Data", - "profileImageUrlLarge" : "/api/users/xzik-pf59/profile_images/LARGE", - "profileImageUrlMedium" : "/api/users/xzik-pf59/profile_images/THUMB", - "profileImageUrlSmall" : "/api/users/xzik-pf59/profile_images/TINY", - "roleName" : "publisher", - "screenName" : "NY Open Data", - "rights" : [ "create_datasets", "edit_others_datasets", "edit_nominations", "approve_nominations", "moderate_comments", "manage_stories", "feature_items", "change_configurations", "view_domain", "view_others_datasets", "create_pages", "edit_pages", "view_goals", "view_dashboards", "edit_goals", "edit_dashboards", "manage_provenance", "view_story", "view_unpublished_story", "view_all_dataset_status_logs", "use_data_connectors" ] - }, - "query" : { - "orderBys" : [ { - "ascending" : false, - "expression" : { - "columnId" : 313053589, - "type" : "column" - } - } ] - }, - "rights" : [ "read" ], - "tableAuthor" : { - "id" : "xzik-pf59", - "displayName" : "NY Open Data", - "profileImageUrlLarge" : "/api/users/xzik-pf59/profile_images/LARGE", - "profileImageUrlMedium" : "/api/users/xzik-pf59/profile_images/THUMB", - "profileImageUrlSmall" : "/api/users/xzik-pf59/profile_images/TINY", - "roleName" : "publisher", - "screenName" : "NY Open Data", - "rights" : [ "create_datasets", "edit_others_datasets", "edit_nominations", "approve_nominations", "moderate_comments", "manage_stories", "feature_items", "change_configurations", "view_domain", "view_others_datasets", "create_pages", "edit_pages", "view_goals", "view_dashboards", "edit_goals", "edit_dashboards", "manage_provenance", "view_story", "view_unpublished_story", "view_all_dataset_status_logs", "use_data_connectors" ] - }, - "tags" : [ "powerball", "new york lottery", "winning", "results" ], - "flags" : [ "default", "restorable", "restorePossibleForType" ] - } - }, - "data" : [ [ 1, "473F0579-3060-42E8-95C6-671B43230276", 1, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-03T00:00:00", "17 22 36 37 52 24", "2" ] -, [ 2, "13ED019C-14C2-48A1-9B40-43AEEF313BCC", 2, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-06T00:00:00", "14 22 52 54 59 04", "3" ] -, [ 3, "9AEDC183-E503-4F83-A0D9-A0F9C6571E33", 3, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-10T00:00:00", "05 08 29 37 38 34", "5" ] -, [ 4, "E67834B5-BF1F-4867-A457-8E26E87E9554", 4, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-13T00:00:00", "10 14 30 40 51 01", "4" ] -, [ 5, "ECD06EF9-3D48-4A32-BEEA-B9D0A8E1499A", 5, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-17T00:00:00", "07 08 19 26 36 15", "3" ] -, [ 6, "6A36058B-0D5F-4A4B-90C7-D37ED9754BCD", 6, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-20T00:00:00", "13 27 37 41 54 32", "2" ] -, [ 7, "5D95F0A8-F691-45BD-837B-0ACC5722C724", 7, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-24T00:00:00", "04 17 35 50 57 12", "2" ] -, [ 8, "7CDC9A40-0062-44DE-A33E-FCF7ED74F2F7", 8, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-02-27T00:00:00", "18 47 51 53 58 30", "2" ] -, [ 9, "B4344C81-6048-47EC-BBB2-9BF061A11D1B", 9, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-03T00:00:00", "07 09 14 45 49 23", "4" ] -, [ 10, "07B0351D-6EE2-4673-B8CC-56193D1C84DC", 10, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-06T00:00:00", "10 29 33 41 59 15", "2" ] -, [ 11, "AF990B4F-BFDF-4BE8-8EFB-E10B3F950DB6", 11, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-10T00:00:00", "17 21 37 41 50 01", "2" ] -, [ 12, "633A2A57-92FF-4E58-AAA9-16A826B9647E", 12, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-13T00:00:00", "06 16 20 31 36 08", "5" ] -, [ 13, "2D7F73F5-4E71-4842-9A53-1E0B7C191232", 13, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-17T00:00:00", "24 26 45 48 55 08", "2" ] -, [ 14, "39F91900-3EB5-4889-8C0C-3E943F7AA8A3", 14, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-20T00:00:00", "09 36 39 44 45 09", "2" ] -, [ 15, "6A7E186E-9051-4771-ABA1-0A9849053799", 15, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-24T00:00:00", "14 20 24 39 49 07", "3" ] -, [ 16, "F192902E-D8A7-430B-8040-DA272A7017E0", 16, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-27T00:00:00", "07 21 32 44 52 10", "4" ] -, [ 17, "812663A1-2244-4865-9E7E-2FE73C4B0E33", 17, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-03-31T00:00:00", "05 13 17 45 54 12", "5" ] -, [ 18, "FAB7E07A-27FF-455A-A7F4-C3ED1AB52304", 18, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-03T00:00:00", "10 15 31 52 59 04", "4" ] -, [ 19, "DC7EE076-3EC5-46F7-BF2E-7263E9488B37", 19, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-07T00:00:00", "04 36 40 44 52 33", "2" ] -, [ 20, "7197D3BF-94AB-49EF-B883-AD40A863E3BA", 20, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-10T00:00:00", "21 22 49 52 58 34", "2" ] -, [ 21, "743DF432-2815-4714-863C-66B72F24605D", 21, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-14T00:00:00", "06 14 32 38 52 20", "3" ] -, [ 22, "8C923446-232E-4941-8EB5-A66A17FBEF69", 22, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-17T00:00:00", "05 21 22 41 49 15", "5" ] -, [ 23, "E0E09616-A6C5-4148-A2E5-F1701B6B1F87", 23, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-21T00:00:00", "11 34 41 49 55 20", "2" ] -, [ 24, "248C0E3F-C489-4DD8-BB68-DD38F788BB58", 24, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-24T00:00:00", "01 12 53 56 57 05", "2" ] -, [ 25, "CCE0FC4D-EB6A-4F8F-81FB-6D1DCED64CA4", 25, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-04-28T00:00:00", "12 22 25 28 44 24", "4" ] -, [ 26, "02267C6C-AB6B-4B8B-B9FD-94FCC100A96E", 26, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-01T00:00:00", "16 23 25 49 58 20", "4" ] -, [ 27, "20BC26C5-7FE1-4CED-8644-92759EEE96BD", 27, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-05T00:00:00", "13 34 40 47 57 11", "4" ] -, [ 28, "5A337131-40E0-4867-B5A2-BB52D6AFE369", 28, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-08T00:00:00", "05 22 34 41 57 31", "5" ] -, [ 29, "181CA471-4431-4279-A1BB-B291000D7791", 29, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-12T00:00:00", "37 51 52 53 58 38", "2" ] -, [ 30, "C5C70FE1-BABE-4D8A-829F-854EE7CF0C42", 30, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-15T00:00:00", "15 21 23 28 36 20", "2" ] -, [ 31, "BBF69F84-8CBB-446C-808C-4FFD42F8C697", 31, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-19T00:00:00", "02 07 29 55 58 27", "3" ] -, [ 32, "0D13C24A-2A9A-4474-A2D9-6A289D71BB0A", 32, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-22T00:00:00", "19 20 40 47 57 29", "2" ] -, [ 33, "97A2F181-B8F4-46FC-9B87-B7DA6C1CF2B7", 33, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-26T00:00:00", "01 06 10 13 20 32", "4" ] -, [ 34, "DCA55B5C-1627-4FF1-B9F5-782A5D41D6C9", 34, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-05-29T00:00:00", "01 03 24 28 41 10", "4" ] -, [ 35, "61E4F315-8AC6-4AD6-BA2B-A23560FBEE3D", 35, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-02T00:00:00", "04 09 14 39 43 38", "4" ] -, [ 36, "5640B9E4-7126-493A-B91E-F941668FE470", 36, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-05T00:00:00", "18 34 40 48 59 25", "4" ] -, [ 37, "BD942373-C55F-4C6F-9C0C-DBAAA5CC5559", 37, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-09T00:00:00", "14 22 27 32 49 05", "4" ] -, [ 38, "BC07F54A-7951-44FA-B33B-21BCAE7C6F33", 38, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-12T00:00:00", "09 12 13 35 38 30", "10" ] -, [ 39, "A39DC171-C91E-4968-A687-D0F37244B54E", 39, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-16T00:00:00", "08 11 18 29 36 06", "5" ] -, [ 40, "C84C1A09-5AEA-411D-B206-3A1670812275", 40, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-19T00:00:00", "09 30 31 50 54 39", "3" ] -, [ 41, "5C253151-8A9D-41B4-ADC7-36736C279671", 41, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-23T00:00:00", "11 30 45 47 48 10", "3" ] -, [ 42, "981360DD-CA16-4D2B-9407-DAEB5EBE3267", 42, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-26T00:00:00", "13 30 32 38 57 25", "4" ] -, [ 43, "5C9B4D04-7517-4A59-9811-89CEDB5FC5D3", 43, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-06-30T00:00:00", "06 38 43 47 48 27", "5" ] -, [ 44, "C4C539BC-EBCE-463B-A4EB-F8037476447F", 44, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-03T00:00:00", "03 10 14 52 53 03", "3" ] -, [ 45, "DB9F4D58-B01F-4C7E-9295-79935EC42014", 45, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-07T00:00:00", "10 41 44 48 56 04", "2" ] -, [ 46, "21088D5B-000F-49E6-A1BC-BF6156B06F97", 46, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-10T00:00:00", "20 21 27 28 56 04", "4" ] -, [ 47, "761AB2D4-CC73-430F-898C-3640437C24AC", 47, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-14T00:00:00", "20 21 23 38 42 06", "3" ] -, [ 48, "3E764B7B-0536-4553-B147-CA59F6AD39B6", 48, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-17T00:00:00", "22 27 35 37 45 03", "4" ] -, [ 49, "8BE6755A-CB72-4F4B-BB21-D5144C6B2471", 49, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-21T00:00:00", "16 22 30 51 58 25", "3" ] -, [ 50, "FBD67CC1-FFFE-4992-9072-A3FF87043C6D", 50, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-24T00:00:00", "20 30 38 46 59 27", "2" ] -, [ 51, "A7228EB5-44A6-4221-B277-102266B93E93", 51, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-28T00:00:00", "01 11 20 25 27 02", "5" ] -, [ 52, "6B045B58-CA3F-49D2-9957-0EAF63AD133D", 52, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-07-31T00:00:00", "01 16 17 41 57 15", "3" ] -, [ 53, "06F488E9-9E70-4259-AF65-425399B615B9", 53, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-04T00:00:00", "19 28 30 37 53 36", "4" ] -, [ 54, "6BC3628F-8104-4BAD-87DF-41F85980BA83", 54, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-07T00:00:00", "04 22 26 31 52 30", "5" ] -, [ 55, "B2168ECA-DF36-4193-937B-595A15C3D31D", 55, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-11T00:00:00", "07 10 22 23 52 29", "2" ] -, [ 56, "593DF38C-05F5-4864-B229-0A26D69A6D48", 56, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-14T00:00:00", "09 33 36 50 58 31", "2" ] -, [ 57, "DAE21B1F-F101-48DC-8C00-371F1F7E4DE7", 57, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-18T00:00:00", "04 32 33 47 55 39", "3" ] -, [ 58, "D3F31D49-C789-4C40-A4BC-B747335FD9FA", 58, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-21T00:00:00", "07 10 12 22 27 26", "2" ] -, [ 59, "A2B0E38D-31AF-4EF1-88E7-94ADDF9E3E6F", 59, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-25T00:00:00", "16 17 29 31 36 23", "3" ] -, [ 60, "92ACA79B-9CE4-4F2A-8B1D-14EFBBCD8300", 60, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-08-28T00:00:00", "04 22 27 32 56 13", "4" ] -, [ 61, "5E44F878-B62A-410A-BAE6-5007E0CE51A3", 61, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-01T00:00:00", "17 20 21 40 51 19", "3" ] -, [ 62, "9133B613-6ABF-405F-96CB-3A9EADF71B56", 62, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-04T00:00:00", "11 14 22 33 42 38", "2" ] -, [ 63, "7EE00F05-8B9B-4A55-B7DE-E4D73440D194", 63, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-08T00:00:00", "10 35 39 51 57 20", "5" ] -, [ 64, "5151B097-89FF-4932-8CE4-A7238698B71F", 64, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-11T00:00:00", "07 17 20 36 59 33", "4" ] -, [ 65, "AE464CA3-8876-478A-A442-0C486F8D62CC", 65, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-15T00:00:00", "07 20 21 34 43 34", "5" ] -, [ 66, "DABAC9CC-604A-433D-A9CB-80F33B8DB8F5", 66, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-18T00:00:00", "01 18 37 39 44 13", "4" ] -, [ 67, "ED62E207-E760-4BB2-9BFB-59E9BF4205C0", 67, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-22T00:00:00", "10 24 36 52 55 15", "5" ] -, [ 68, "352BF116-9C83-4DB7-8422-A9F4FEA693BC", 68, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-25T00:00:00", "08 16 27 35 42 30", "2" ] -, [ 69, "72561D26-F116-4C42-B7CD-717D82149C12", 69, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-09-29T00:00:00", "13 44 51 52 55 30", "4" ] -, [ 70, "3FC171C6-8936-4872-90DF-994281F73D02", 70, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-02T00:00:00", "12 20 30 36 47 25", "4" ] -, [ 71, "FFD2A4A9-2BD4-4E89-9EE4-F597B6DDBCC4", 71, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-06T00:00:00", "14 26 37 41 46 24", "5" ] -, [ 72, "C22C5B84-322D-4CBC-9600-F42ADF3163FB", 72, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-09T00:00:00", "02 06 32 42 49 35", "3" ] -, [ 73, "64CC8513-4ABE-484B-A6E3-8C1401B12C4C", 73, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-13T00:00:00", "12 22 32 34 46 02", "4" ] -, [ 74, "3301A17B-CF71-41AB-9787-614EDFE7C4EC", 74, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-16T00:00:00", "11 12 15 16 28 11", "2" ] -, [ 75, "DCBDF086-B73C-4375-B745-21506C9A5DD2", 75, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-20T00:00:00", "07 17 20 39 59 17", "3" ] -, [ 76, "62B84F14-8741-47A2-978C-748A9CD3090F", 76, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-23T00:00:00", "02 07 16 20 46 34", "4" ] -, [ 77, "4EF6C071-1A67-4CB1-8664-B14C8E58CBFC", 77, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-27T00:00:00", "20 24 25 53 59 15", "5" ] -, [ 78, "29F77288-AAE5-40F6-85F1-49034D76394E", 78, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-10-30T00:00:00", "01 07 27 36 49 39", "5" ] -, [ 79, "99BFAC1C-14DD-47A0-A697-F44B76A708AD", 79, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-03T00:00:00", "34 38 39 45 50 33", "2" ] -, [ 80, "6DAC5801-1E01-4D10-86D6-070762A4F50F", 80, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-06T00:00:00", "07 12 23 34 38 33", "4" ] -, [ 81, "0BA8EFBC-E383-4063-82CF-84728365E61E", 81, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-10T00:00:00", "05 08 11 40 44 10", "4" ] -, [ 82, "3F894729-A7A7-4E55-846E-3FD2191B7F88", 82, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-13T00:00:00", "17 30 48 51 54 29", "5" ] -, [ 83, "570CDB2A-E9D5-4375-A611-44D8A5C55C3A", 83, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-17T00:00:00", "14 16 53 54 59 05", "3" ] -, [ 84, "29C3FB4C-5898-4B1B-A07F-A96246DBE40B", 84, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-20T00:00:00", "10 12 38 53 57 01", "5" ] -, [ 85, "0437BD3B-7443-413F-94A6-C311CD043BBC", 85, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-24T00:00:00", "08 20 21 32 37 04", "3" ] -, [ 86, "AA4A70D1-A86A-4A8A-AD80-48129D1FE8E0", 86, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-11-27T00:00:00", "10 30 37 47 54 39", "5" ] -, [ 87, "64361722-B061-4486-940F-6A72800287AC", 87, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-01T00:00:00", "05 10 11 12 20 02", "3" ] -, [ 88, "E93C2325-0FD6-4C7C-8E2B-2B24CB5340C2", 88, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-04T00:00:00", "13 24 27 31 42 22", "5" ] -, [ 89, "C9EC5D1F-BC31-4FE4-B403-1B18057F9E83", 89, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-08T00:00:00", "08 11 25 41 58 16", "4" ] -, [ 90, "97995811-5050-43E9-BC76-D580315CA1EC", 90, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-11T00:00:00", "01 08 10 19 20 23", "2" ] -, [ 91, "92ADBB7A-CA7E-4155-8F25-629BC4925798", 91, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-15T00:00:00", "10 11 18 32 45 18", "5" ] -, [ 92, "7F32B5D0-5ABC-46F5-819D-E469CB5A5EE8", 92, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-18T00:00:00", "04 11 19 33 43 14", "4" ] -, [ 93, "D1C86092-E5F9-4229-A737-F9CD6B6D1EFA", 93, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-22T00:00:00", "11 33 44 46 47 12", "2" ] -, [ 94, "5198F649-642C-4E21-A772-134F09716BA3", 94, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-25T00:00:00", "01 17 38 50 52 24", "2" ] -, [ 95, "4FC247E7-FCB1-4530-9DCE-C52909402E52", 95, 1362743858, "706580", 1362743858, "706580", "{\n}", "2010-12-29T00:00:00", "03 16 18 20 37 30", "2" ] -, [ 96, "93F87258-233E-4B01-A29A-8EFCCE13722C", 96, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-01T00:00:00", "18 22 37 47 54 36", "2" ] -, [ 97, "40038954-8377-494E-944E-908E85973739", 97, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-05T00:00:00", "22 26 32 38 40 07", "5" ] -, [ 98, "C45F6776-46DC-4484-A22D-2710D96F7479", 98, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-08T00:00:00", "06 07 26 33 52 24", "2" ] -, [ 99, "B6356A6B-4369-4138-A6EE-AC710C822F4A", 99, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-12T00:00:00", "19 21 23 40 48 27", "4" ] -, [ 100, "CF901D2A-4E08-4E73-831B-A949AC1141D6", 100, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-15T00:00:00", "09 13 22 23 37 31", "3" ] -, [ 101, "8AE587F8-B4D4-48F1-A5CD-74A2D61965C0", 101, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-19T00:00:00", "22 36 51 56 59 32", "3" ] -, [ 102, "AF143F6E-C97C-400B-B1B4-F2E6D55DD9F3", 102, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-22T00:00:00", "30 31 34 45 51 23", "2" ] -, [ 103, "05BD1A80-DAC2-4877-B98A-85A642530EE5", 103, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-26T00:00:00", "04 05 36 47 58 06", "3" ] -, [ 104, "E016B13D-A0E4-4DA7-BDE3-68CD0F747494", 104, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-01-29T00:00:00", "24 28 45 49 52 02", "4" ] -, [ 105, "B3BCD26B-3E87-49B5-9E32-A944F64853C6", 105, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-02T00:00:00", "03 14 33 53 57 36", "4" ] -, [ 106, "EA37777E-4995-4377-94BD-C63B99CADD29", 106, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-05T00:00:00", "15 37 41 56 59 05", "5" ] -, [ 107, "4FCF4408-9656-46A5-9819-21003BC40254", 107, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-09T00:00:00", "07 11 39 42 51 30", "4" ] -, [ 108, "05A24764-9DEA-4AEF-93A5-AB82E261185D", 108, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-12T00:00:00", "11 32 36 48 52 19", "4" ] -, [ 109, "8F293368-4D17-4AD5-AF5B-C74726FD0434", 109, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-16T00:00:00", "09 13 21 23 48 24", "2" ] -, [ 110, "061296AF-4EFD-41C1-B9CF-E17CD2852137", 110, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-19T00:00:00", "03 12 34 37 42 36", "5" ] -, [ 111, "2A3C62E6-7D95-4563-9AB2-7AE7765DB390", 111, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-23T00:00:00", "29 32 36 39 49 29", "3" ] -, [ 112, "F9220CDF-6C68-4D5D-95F2-8AFC87973920", 112, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-02-26T00:00:00", "04 13 17 21 45 10", "5" ] -, [ 113, "FD1388E7-2747-47FA-949D-05FD678528AB", 113, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-02T00:00:00", "07 31 50 51 58 06", "2" ] -, [ 114, "CC29B3FF-7526-467F-81BB-16E0237C3E0C", 114, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-05T00:00:00", "02 23 31 42 48 21", "2" ] -, [ 115, "FF3AEC1E-2DDC-4C2A-9E7D-3DE77D22C255", 115, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-09T00:00:00", "12 20 28 40 48 08", "2" ] -, [ 116, "557208D2-F86E-4E3F-9FCB-A5BEE7356AFA", 116, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-12T00:00:00", "01 04 12 41 47 03", "4" ] -, [ 117, "533BD995-6463-429B-9958-A9BED29B39D0", 117, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-16T00:00:00", "28 39 40 48 53 09", "3" ] -, [ 118, "F71FBC6A-7F1F-4031-8178-72989CA00D2F", 118, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-19T00:00:00", "03 11 20 27 46 08", "2" ] -, [ 119, "F9CE6E77-CD5F-452A-8F5A-363513D83F62", 119, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-23T00:00:00", "05 15 26 28 32 09", "2" ] -, [ 120, "58851C51-CBA6-4015-ADB3-0632A9458096", 120, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-26T00:00:00", "04 10 11 19 33 27", "4" ] -, [ 121, "98108522-00D3-4187-9D88-800337831326", 121, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-03-30T00:00:00", "19 20 42 56 58 37", "4" ] -, [ 122, "526B953C-4B88-4AE0-8D48-0E74E7A8CF16", 122, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-02T00:00:00", "06 22 34 43 45 23", "2" ] -, [ 123, "5E1119FF-9619-4732-A895-865FE789F558", 123, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-06T00:00:00", "10 18 41 55 56 15", "2" ] -, [ 124, "0CE21D53-C1DC-4C48-A18F-CB4BF10B7F20", 124, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-09T00:00:00", "05 14 32 53 56 11", "4" ] -, [ 125, "7E843BE0-E068-4511-8237-9D5750123BF8", 125, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-13T00:00:00", "04 23 39 49 50 39", "3" ] -, [ 126, "51ED8DC0-6501-40FB-9531-3910843D6BC0", 126, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-16T00:00:00", "21 33 44 45 55 07", "5" ] -, [ 127, "E1AB915B-0D8E-4BBA-9089-37023D54ECBF", 127, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-20T00:00:00", "09 24 34 36 43 27", "3" ] -, [ 128, "287D98E0-5CB1-4EF9-9A57-79BEF03483A7", 128, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-23T00:00:00", "03 11 47 48 58 19", "3" ] -, [ 129, "5230AEAD-648E-4D5E-8F6D-1B64A3E7A1AB", 129, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-27T00:00:00", "04 24 40 44 55 05", "2" ] -, [ 130, "45333360-9131-4043-8852-CB77AA794370", 130, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-04-30T00:00:00", "06 13 15 32 41 03", "2" ] -, [ 131, "79798878-CCD2-453E-9E27-DA9765FD2A3A", 131, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-04T00:00:00", "03 15 27 29 41 24", "4" ] -, [ 132, "B3163D53-EA4D-4386-A43E-EFC60A5AEF26", 132, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-07T00:00:00", "02 11 27 47 55 15", "4" ] -, [ 133, "097C8559-2817-4737-B26D-ECB09BC40AC0", 133, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-11T00:00:00", "09 17 32 43 45 31", "3" ] -, [ 134, "062F616D-0E21-4794-8D63-3E30E3681E44", 134, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-14T00:00:00", "08 17 18 40 44 16", "2" ] -, [ 135, "0D63C006-11D5-40CF-B587-384346C41C25", 135, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-18T00:00:00", "07 12 13 42 49 16", "4" ] -, [ 136, "0FF01D7C-AE37-437E-A5AC-61BAA2508D7D", 136, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-21T00:00:00", "02 08 40 49 50 36", "3" ] -, [ 137, "A2C61ADF-F689-4794-A808-84A75826E743", 137, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-25T00:00:00", "04 23 31 42 50 23", "2" ] -, [ 138, "F3267566-AE83-44F3-8160-789EA1016E1D", 138, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-05-28T00:00:00", "12 20 43 51 55 11", "4" ] -, [ 139, "02B6BE3F-A964-47C4-9697-E29201F09028", 139, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-01T00:00:00", "08 18 38 46 56 31", "4" ] -, [ 140, "CC7942F6-877B-48B6-9181-93A1C98B0359", 140, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-04T00:00:00", "17 19 39 41 58 21", "5" ] -, [ 141, "61378B85-5CAA-4022-B572-B4AE0E2F7777", 141, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-08T00:00:00", "14 37 44 45 53 29", "5" ] -, [ 142, "F91BBF8A-2984-4398-8770-E4CDB5CDC4A4", 142, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-11T00:00:00", "16 18 27 36 50 08", "3" ] -, [ 143, "7D7AC37A-E986-4A6B-B961-922D9EDF1F35", 143, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-15T00:00:00", "19 20 38 41 43 29", "4" ] -, [ 144, "0ED73FCF-199E-45CC-9C97-363AA8FDFDCF", 144, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-18T00:00:00", "12 21 22 38 41 18", "2" ] -, [ 145, "A3F9E171-836B-485E-8CEE-5B98BC033F4E", 145, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-22T00:00:00", "12 15 19 46 59 12", "4" ] -, [ 146, "7D31993D-45DC-41A3-BFD0-9A813652F08E", 146, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-25T00:00:00", "18 36 39 41 57 12", "4" ] -, [ 147, "2F615FCA-77BF-467B-B83F-C8C952A495B1", 147, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-06-29T00:00:00", "24 30 45 57 59 26", "3" ] -, [ 148, "C763B039-97BC-429A-A266-54E676FD9FE8", 148, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-02T00:00:00", "01 11 18 29 51 32", "3" ] -, [ 149, "0CE75BB4-3F14-4A49-A29C-821D5214EEFF", 149, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-06T00:00:00", "11 15 24 50 55 08", "2" ] -, [ 150, "28EC195A-D329-4CD4-8186-830B0B26E986", 150, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-09T00:00:00", "01 09 11 23 31 06", "3" ] -, [ 151, "F01DDCEF-548F-470B-AA4C-64344207CF70", 151, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-13T00:00:00", "08 18 19 32 54 08", "4" ] -, [ 152, "BF59C62F-CE42-46B3-8D53-4BB89C044A0B", 152, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-16T00:00:00", "24 28 48 50 54 25", "3" ] -, [ 153, "F382A07F-8C7F-4421-9787-1F1848CD9495", 153, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-20T00:00:00", "01 04 38 40 42 17", "4" ] -, [ 154, "B816B09A-67CE-4F64-8F46-F40067CDEFB9", 154, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-23T00:00:00", "01 07 27 38 48 30", "3" ] -, [ 155, "C4AE9DAC-E9EF-4D8E-A325-215DD8E9ED66", 155, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-27T00:00:00", "38 40 41 51 59 33", "2" ] -, [ 156, "50A1075C-9262-4B20-8D86-C8D90A4E7752", 156, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-07-30T00:00:00", "20 40 41 47 55 19", "2" ] -, [ 157, "44654407-6D79-4A7B-9289-448842BDFABD", 157, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-03T00:00:00", "13 19 21 28 49 11", "2" ] -, [ 158, "8E9ECF5E-B2FD-4573-B80A-2A1ADCDC4202", 158, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-06T00:00:00", "25 30 54 57 59 06", "3" ] -, [ 159, "8C84603D-A637-400F-885E-83939C95191E", 159, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-10T00:00:00", "11 18 36 41 46 38", "4" ] -, [ 160, "C3DAF6FF-C8EE-4D4D-A6FE-D1B18DD65FF1", 160, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-13T00:00:00", "09 12 35 50 58 04", "2" ] -, [ 161, "0EB476D2-7418-4354-B8A8-205A90DC1DDF", 161, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-17T00:00:00", "18 28 31 48 52 37", "4" ] -, [ 162, "1480D8BB-7D88-4307-83EB-917D7D3D60A6", 162, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-20T00:00:00", "02 17 23 28 47 36", "2" ] -, [ 163, "91FFF0D2-E5F6-46F2-AF8D-530E691E2758", 163, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-24T00:00:00", "09 13 47 49 53 39", "5" ] -, [ 164, "DDE69E16-E29A-44F9-8DF0-B75FC8E5446E", 164, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-27T00:00:00", "02 12 25 54 58 14", "3" ] -, [ 165, "03453461-CFD5-45F8-B8D6-4F4EFC4B3E1D", 165, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-08-31T00:00:00", "13 19 35 47 57 29", "5" ] -, [ 166, "56803DBA-389D-414C-95F1-3F1F4EF87C93", 166, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-03T00:00:00", "15 25 52 53 54 02", "5" ] -, [ 167, "7B8C595B-EAA8-4511-AB8A-22F05D0E1493", 167, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-07T00:00:00", "03 05 18 27 54 13", "4" ] -, [ 168, "9A979EB9-5F95-4313-A115-1D0FDB7B2AA0", 168, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-10T00:00:00", "04 19 22 32 53 24", "4" ] -, [ 169, "9FA4926B-6EEB-4FAB-A6A6-B8A71BF39BCD", 169, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-14T00:00:00", "16 41 42 50 59 05", "3" ] -, [ 170, "7D4EDF40-6655-4D99-A635-66CC7FDAB422", 170, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-17T00:00:00", "06 20 22 32 43 11", "2" ] -, [ 171, "17CEB9C3-945A-4874-BA6F-B9AE7C07FAFC", 171, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-21T00:00:00", "12 47 48 52 55 13", "4" ] -, [ 172, "D074055A-E72B-4DBB-B1FB-E8783EAA0D41", 172, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-24T00:00:00", "03 04 12 27 44 26", "5" ] -, [ 173, "34C73D37-392F-43BC-A494-E0FB5D6B354D", 173, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-09-28T00:00:00", "30 41 50 51 53 08", "2" ] -, [ 174, "8EC47719-C980-4F2D-95A7-6DEA8EBBE49B", 174, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-01T00:00:00", "01 12 23 27 43 31", "3" ] -, [ 175, "7E194E19-56CE-4A82-991B-E623641DDA4B", 175, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-05T00:00:00", "07 20 43 46 54 17", "4" ] -, [ 176, "2E0A35CF-76FC-4AA4-9F59-B69878A66A81", 176, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-08T00:00:00", "03 27 35 37 45 31", "5" ] -, [ 177, "4FE26456-F945-4CA1-9849-5405C5EB0D02", 177, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-12T00:00:00", "10 12 23 43 47 18", "3" ] -, [ 178, "3989F7B0-F975-4456-986E-531A691311D9", 178, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-15T00:00:00", "05 10 24 38 43 01", "4" ] -, [ 179, "36AEAE64-DA73-43F7-85B0-90FD865FFC9B", 179, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-19T00:00:00", "16 26 35 52 58 02", "5" ] -, [ 180, "F14A714F-288C-4A49-80D9-8241C098F089", 180, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-22T00:00:00", "03 08 23 30 58 13", "4" ] -, [ 181, "A3FFE3C7-995D-45D4-91E9-FAEB81FA105A", 181, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-26T00:00:00", "01 18 21 39 55 06", "3" ] -, [ 182, "300213E7-DCFA-44CC-BD61-479DD2E54C11", 182, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-10-29T00:00:00", "11 16 40 51 56 38", "5" ] -, [ 183, "9F7AB101-0EC5-4617-AAD4-FB5DD9810884", 183, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-02T00:00:00", "12 14 34 39 46 36", "4" ] -, [ 184, "F32FB3B1-964E-4D3B-86A3-B39E8A1E44C8", 184, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-05T00:00:00", "02 33 39 40 43 26", "3" ] -, [ 185, "05C290E8-16E5-4171-934E-A81EF8EA7CE4", 185, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-09T00:00:00", "05 35 57 58 59 12", "3" ] -, [ 186, "29DD3DC2-E14B-4EDE-9C30-8216914D6FEA", 186, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-12T00:00:00", "04 35 36 51 56 08", "5" ] -, [ 187, "8D0CE332-1F93-4397-80B5-7EEC36FA54C2", 187, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-16T00:00:00", "13 22 25 39 51 28", "2" ] -, [ 188, "047DBA01-8F50-437D-A8CC-1A8EBB69B7B8", 188, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-19T00:00:00", "09 16 17 28 30 11", "3" ] -, [ 189, "5354A5AD-8C46-4292-922D-061B18AB5D56", 189, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-23T00:00:00", "04 30 35 57 59 25", "2" ] -, [ 190, "4064BDA6-CA03-4989-B90F-43317004BFF5", 190, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-26T00:00:00", "20 37 39 45 55 28", "2" ] -, [ 191, "1AFEF399-4B0D-4F4B-8B78-731594986C57", 191, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-11-30T00:00:00", "02 06 34 35 47 22", "2" ] -, [ 192, "7B2EB6A1-B2C2-410D-B252-880BC27937CD", 192, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-03T00:00:00", "05 18 33 43 45 08", "3" ] -, [ 193, "3DE2C47F-5816-4A66-A1D1-A926FEDC1D96", 193, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-07T00:00:00", "03 14 20 39 40 37", "2" ] -, [ 194, "18FDF2CE-359B-4AE4-ADDD-EE9BA474C3BC", 194, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-10T00:00:00", "04 19 33 41 59 09", "5" ] -, [ 195, "997563CF-3217-4133-BC62-E7C36F38FF0B", 195, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-14T00:00:00", "02 24 46 52 56 19", "5" ] -, [ 196, "583A0BA7-F5C2-4537-A074-F4589AD9ADCB", 196, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-17T00:00:00", "13 28 49 51 59 33", "4" ] -, [ 197, "C1165E24-1C4B-4FB3-936D-3D6EE2FC6EB6", 197, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-21T00:00:00", "10 13 15 31 54 18", "5" ] -, [ 198, "828E2F73-D48C-4C04-A3F1-2BB4E739E0D8", 198, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-24T00:00:00", "14 16 30 51 52 19", "2" ] -, [ 199, "CA3DF9C8-70E1-4A1D-8520-452A0E9E058E", 199, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-28T00:00:00", "16 21 27 41 45 14", "2" ] -, [ 200, "07D40B41-E652-4393-B749-19685DE4579C", 200, 1362743858, "706580", 1362743858, "706580", "{\n}", "2011-12-31T00:00:00", "05 23 25 28 40 34", "4" ] -, [ 201, "6ED79AB6-04B8-48AF-802D-F8940CFC370A", 201, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-04T00:00:00", "21 35 46 47 50 02", "4" ] -, [ 202, "4F718048-E61B-495B-805C-E35624F2182D", 202, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-07T00:00:00", "03 21 24 38 39 24", "5" ] -, [ 203, "99D4B50F-83D9-478D-AA96-B7225A6A0F2B", 203, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-11T00:00:00", "05 19 29 45 47 25", "2" ] -, [ 204, "369DB95A-DE5B-4070-A175-54CEA5043F88", 204, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-14T00:00:00", "10 30 36 38 41 01", "5" ] -, [ 205, "68BFE997-EF24-4FF7-809E-4B98BAD12A33", 205, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-18T00:00:00", "06 29 34 44 50 28", null ] -, [ 206, "73E19009-0F21-46C8-951D-D7BB50ECE5F1", 206, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-21T00:00:00", "12 24 43 44 45 07", null ] -, [ 207, "02C6C142-463F-413B-9005-56E28EC96210", 207, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-25T00:00:00", "04 19 28 29 47 05", null ] -, [ 208, "7B5054A4-2F50-484B-86F6-9F9CF78CC9A5", 208, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-01-28T00:00:00", "05 33 41 54 59 13", null ] -, [ 209, "1EF7C6C9-8B72-48E6-AB36-6BFCFB77B3DE", 209, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-01T00:00:00", "08 13 17 34 59 35", null ] -, [ 210, "A1F66607-2F2B-4C84-AD68-D3AF901A6182", 210, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-04T00:00:00", "15 23 43 45 56 07", null ] -, [ 211, "9A2D1456-8BFB-40DF-A66A-FAF7EF6B4355", 211, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-08T00:00:00", "17 28 38 39 51 33", null ] -, [ 212, "C9F84026-FA64-4891-8FDC-7D91CFAA9773", 212, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-11T00:00:00", "01 10 37 52 57 11", null ] -, [ 213, "35B6335E-90F5-406F-9417-9ECA5F4ED28E", 213, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-15T00:00:00", "11 12 32 52 56 11", null ] -, [ 214, "0D5BCFD5-88FC-46D0-ACD6-54C967456941", 214, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-18T00:00:00", "23 28 50 56 59 05", null ] -, [ 215, "8F769561-C534-46EF-8DC9-0CD5F69FCD7C", 215, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-22T00:00:00", "07 16 17 39 51 32", null ] -, [ 216, "F72A4C8C-E83F-4623-B0A8-AC4170F711BC", 216, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-25T00:00:00", "06 11 42 53 54 07", null ] -, [ 217, "C6FD7554-ACF3-45A5-8B06-06DC1DF30BB2", 217, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-02-29T00:00:00", "01 04 11 23 26 14", null ] -, [ 218, "222E59E8-FFD7-4CC5-BC7C-B757746CAF8D", 218, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-03T00:00:00", "29 30 45 47 49 35", null ] -, [ 219, "D2A8DF68-9343-49F2-8705-FD28B2CC3A90", 219, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-07T00:00:00", "12 35 45 46 47 12", null ] -, [ 220, "A36FEF9D-2D5B-4DEC-8A5E-58497A21241A", 220, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-10T00:00:00", "05 14 17 20 41 05", null ] -, [ 221, "6BBE1009-6381-419A-88CC-F4DCCDF5AEEE", 221, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-14T00:00:00", "01 08 41 46 59 24", null ] -, [ 222, "6340B968-9772-46AA-A489-0928359C5E72", 222, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-17T00:00:00", "11 14 49 55 58 30", null ] -, [ 223, "28FCDA38-FE5D-4F76-8E81-91D7C46AEE36", 223, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-21T00:00:00", "32 43 53 55 56 06", null ] -, [ 224, "C13FB396-7E85-4D9D-84E7-8F31BBE3953D", 224, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-24T00:00:00", "01 15 35 37 47 08", null ] -, [ 225, "77D4E5AC-74EF-49E1-8D14-E1F3C85235C8", 225, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-28T00:00:00", "11 16 29 50 58 33", null ] -, [ 226, "892B6304-F1C9-4968-BEFB-1D518B238C0A", 226, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-03-31T00:00:00", "05 14 36 54 58 27", null ] -, [ 227, "0540775F-6648-4FEA-8444-5573749AE140", 227, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-04T00:00:00", "01 24 33 45 49 06", null ] -, [ 228, "E63BE891-43F0-4910-8EE4-5EDA1FBB719F", 228, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-07T00:00:00", "05 13 17 20 30 18", null ] -, [ 229, "82DD4C26-AA7D-4C11-BEA8-9899EF5FF86A", 229, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-11T00:00:00", "16 23 42 44 47 02", null ] -, [ 230, "DAB9D612-C187-4B13-BCBC-36E33A22250B", 230, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-14T00:00:00", "14 15 16 19 24 02", null ] -, [ 231, "82FC523B-BD1D-4A5B-925C-488764025F63", 231, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-18T00:00:00", "20 22 39 46 49 29", null ] -, [ 232, "08E109BC-46CD-405D-B55B-D63C8EF1E88E", 232, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-21T00:00:00", "06 08 20 42 51 16", null ] -, [ 233, "25732E04-4CEA-481A-BBBD-BB706A4822A2", 233, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-25T00:00:00", "04 25 29 34 43 29", null ] -, [ 234, "84D6DF1E-2850-48D6-81C8-BA6813947093", 234, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-04-28T00:00:00", "31 39 40 57 58 33", null ] -, [ 235, "CE62EC65-4B54-424B-AF1E-9DA89A23AC3B", 235, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-02T00:00:00", "07 08 33 38 50 29", null ] -, [ 236, "247DF1DB-7140-4F4E-BAA8-82D44151B697", 236, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-05T00:00:00", "09 12 20 44 59 23", null ] -, [ 237, "1D2FD83C-6F5D-4D0E-84F6-DBEBA73226FB", 237, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-09T00:00:00", "01 07 11 55 56 01", null ] -, [ 238, "9F497756-5D8C-44F9-BCA9-32C85F24C7B4", 238, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-12T00:00:00", "10 24 35 53 58 22", null ] -, [ 239, "CDC9826E-CAA4-4851-BA89-40F94C43640F", 239, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-16T00:00:00", "03 07 21 28 43 02", null ] -, [ 240, "38ED6B08-4AE8-4D03-9CA3-F6CEEE7AD5EA", 240, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-19T00:00:00", "08 13 35 46 51 30", null ] -, [ 241, "DC69454E-7153-42B1-80C0-B782FE2947C6", 241, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-23T00:00:00", "04 07 26 53 59 32", null ] -, [ 242, "37DC3FAB-1784-4A7F-8175-12BF55F9F707", 242, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-26T00:00:00", "13 14 41 49 59 14", null ] -, [ 243, "8841334C-6681-4C95-A2D1-E98368995E74", 243, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-05-30T00:00:00", "09 10 24 52 56 14", null ] -, [ 244, "BC98C758-2146-4840-B56D-F558C6DFC597", 244, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-02T00:00:00", "09 10 17 29 45 33", null ] -, [ 245, "8745C895-057D-425C-8AC4-3893B1217811", 245, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-06T00:00:00", "19 30 33 48 59 27", null ] -, [ 246, "7ADA588B-6072-453B-83D3-3121A766E766", 246, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-09T00:00:00", "18 22 45 56 57 27", null ] -, [ 247, "EE8DA13A-D8D2-4E45-AB14-F582E01B1890", 247, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-13T00:00:00", "07 10 14 33 57 18", null ] -, [ 248, "131CCCCE-98B4-4508-BBE4-D1DAF52D24C1", 248, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-16T00:00:00", "08 14 15 16 27 26", null ] -, [ 249, "E485B061-0AB2-480C-83DD-CDD20DAF53A9", 249, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-20T00:00:00", "11 17 29 56 57 14", null ] -, [ 250, "64752403-F193-4E6C-8DAB-426B915D324C", 250, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-23T00:00:00", "01 03 41 44 53 30", null ] -, [ 251, "5A9F43EF-49A3-4775-B5D4-01FB399BDBA0", 251, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-27T00:00:00", "06 34 40 46 58 06", null ] -, [ 252, "187F3244-451C-44C4-9E2E-F6148EBD5486", 252, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-06-30T00:00:00", "07 15 20 41 44 22", null ] -, [ 253, "0520D56E-49E1-4437-883A-BEA8549177E9", 253, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-04T00:00:00", "14 19 35 39 56 33", null ] -, [ 254, "289BFBF7-9899-4318-8FA9-248D0D2DD6BE", 254, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-07T00:00:00", "03 05 29 39 59 29", null ] -, [ 255, "5A74A68D-4FE4-47CF-A30E-FD00A448556C", 255, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-11T00:00:00", "05 22 36 49 55 23", null ] -, [ 256, "68724EFF-9945-4B64-8703-C3885EEBF72A", 256, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-14T00:00:00", "04 16 32 37 46 13", null ] -, [ 257, "E97770CF-2D5B-4E50-AD4E-DA908CB1A65D", 257, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-18T00:00:00", "02 05 20 23 57 03", null ] -, [ 258, "94CE7B77-0577-441F-AEB8-21C06FB72FB1", 258, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-21T00:00:00", "09 31 38 54 56 20", null ] -, [ 259, "EF93A1EE-E937-46EE-BE45-93144E3B018A", 259, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-25T00:00:00", "03 14 35 38 46 16", null ] -, [ 260, "E6E27C61-9F67-4435-B056-6C9E11E05396", 260, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-07-28T00:00:00", "05 06 13 36 50 13", null ] -, [ 261, "DFF18A33-7D8D-49DE-8811-13A0E2D2C846", 261, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-01T00:00:00", "03 16 48 56 58 04", null ] -, [ 262, "98DBB22C-0155-4F72-A68B-179D47A1C9BA", 262, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-04T00:00:00", "19 30 48 53 55 18", null ] -, [ 263, "3BCB7B3F-E4B8-4AB7-A071-82998C6274EF", 263, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-08T00:00:00", "03 07 11 15 28 12", null ] -, [ 264, "BD63131D-D862-4186-A0EF-4A290455A282", 264, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-11T00:00:00", "04 13 39 46 51 01", null ] -, [ 265, "06C0AA9D-39A8-4928-8C8F-61DA329BCC7F", 265, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-15T00:00:00", "06 27 46 51 56 21", null ] -, [ 266, "4BE3F65C-4B6A-4081-B75D-9280C8367C17", 266, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-18T00:00:00", "14 26 41 55 59 01", null ] -, [ 267, "9A0B6856-C420-4411-84EA-99AC6BBF0015", 267, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-22T00:00:00", "22 29 31 47 55 19", null ] -, [ 268, "BF067455-0051-4B07-8A18-CAC7AA537C02", 268, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-25T00:00:00", "01 06 07 20 49 23", null ] -, [ 269, "BE75088A-CED8-44AC-AFB8-19C09D6FE196", 269, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-08-29T00:00:00", "25 28 49 54 56 28", null ] -, [ 270, "CEECAF38-CF6B-4715-8EE1-37C5206F1C2C", 270, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-01T00:00:00", "08 11 21 44 49 22", null ] -, [ 271, "CE3C7F39-5D43-4AFF-9761-7CE56DB9D923", 271, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-05T00:00:00", "04 19 26 42 51 29", null ] -, [ 272, "9D59886E-17B3-4947-90D9-2D3901D57C71", 272, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-08T00:00:00", "06 20 34 44 48 29", null ] -, [ 273, "49C909B5-17D3-4790-9665-6C8030223DB0", 273, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-12T00:00:00", "24 33 36 48 56 06", null ] -, [ 274, "AD1E516B-00D1-45E2-910C-1440D98CB95B", 274, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-15T00:00:00", "03 20 26 43 48 01", null ] -, [ 275, "B5ACAEA4-1D1F-43F9-BC05-A0248EB5BE8B", 275, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-19T00:00:00", "01 05 08 39 50 23", null ] -, [ 276, "5DDD7687-0420-45D4-9B0F-1A1BAC9E7B1D", 276, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-22T00:00:00", "02 16 18 40 42 33", null ] -, [ 277, "30FAC46C-67D1-4517-B9C1-C45A66ECD4AD", 277, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-26T00:00:00", "13 26 39 41 42 10", null ] -, [ 278, "085D6278-8169-45F2-8139-5AE139D49584", 278, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-09-29T00:00:00", "14 18 28 29 57 08", null ] -, [ 279, "26ECC80A-B310-4A53-92CE-202F7B197214", 279, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-03T00:00:00", "17 23 36 55 59 10", null ] -, [ 280, "914519F9-A8B7-434F-B0D4-907038C71E5A", 280, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-06T00:00:00", "15 26 34 36 59 35", null ] -, [ 281, "6636BBF0-8EBC-418F-A550-FA95CACC0619", 281, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-10T00:00:00", "18 26 29 35 43 28", null ] -, [ 282, "5365107E-2287-48CA-AD58-6C9A023C714C", 282, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-13T00:00:00", "02 05 25 26 49 18", null ] -, [ 283, "E417DA4F-11BE-4903-ADAF-8FDD30355EF5", 283, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-17T00:00:00", "01 07 10 23 42 35", null ] -, [ 284, "B4D90A89-0789-4D09-BDDC-03C9DF67DC6F", 284, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-20T00:00:00", "04 21 28 31 44 10", null ] -, [ 285, "9BF840BF-31FE-4089-99F6-9A011979ABEE", 285, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-24T00:00:00", "03 18 21 23 50 04", null ] -, [ 286, "B6575F0B-D385-47EA-9332-D106904A702A", 286, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-27T00:00:00", "22 32 34 36 56 33", null ] -, [ 287, "57B7ED0C-5CC1-4081-9590-E199DF5FA176", 287, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-10-31T00:00:00", "01 27 31 45 48 05", null ] -, [ 288, "C41607D3-580C-43BB-ADAD-9CC43C5819D0", 288, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-03T00:00:00", "04 07 09 30 54 25", null ] -, [ 289, "00DF4287-E311-4041-803D-50CD8CF730F8", 289, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-07T00:00:00", "32 34 45 52 58 20", null ] -, [ 290, "26EF36DB-6E16-4504-99D7-586EF63C5BFD", 290, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-10T00:00:00", "32 42 50 54 55 32", null ] -, [ 291, "2DFD63FF-F496-4915-ADBE-CFC7B2F020E4", 291, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-14T00:00:00", "08 10 30 44 58 13", null ] -, [ 292, "79A650AF-912E-4C50-A912-22D6CE48C74C", 292, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-17T00:00:00", "03 15 27 58 59 20", null ] -, [ 293, "79919921-AEE6-48DF-9450-BB91C923FFB4", 293, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-21T00:00:00", "08 18 24 30 39 26", null ] -, [ 294, "347CD937-33FD-40DF-B30A-2926AB462E46", 294, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-24T00:00:00", "22 32 37 44 50 34", null ] -, [ 295, "42030C9D-944B-4CA6-ACF9-491121D867AC", 295, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-11-28T00:00:00", "05 16 22 23 29 06", null ] -, [ 296, "1F2CCE2B-0EB4-4866-A863-4E0F6AF4C137", 296, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-01T00:00:00", "03 10 19 36 46 03", null ] -, [ 297, "BAF2D745-7C18-4FFA-BDCE-9335B51B3044", 297, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-05T00:00:00", "13 17 19 27 38 12", null ] -, [ 298, "2923720E-CC6D-4FA4-9D78-D0D1EA8EB401", 298, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-08T00:00:00", "07 23 26 40 53 21", null ] -, [ 299, "08BF1FF1-5F06-47B9-BE7D-B256988D55E3", 299, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-12T00:00:00", "08 10 25 36 44 28", null ] -, [ 300, "C471CB03-D137-4D02-A38B-17D3DD24AB61", 300, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-15T00:00:00", "15 23 40 44 55 14", null ] -, [ 301, "8D72164F-DC14-4C2D-B905-2236F6D766A0", 301, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-19T00:00:00", "05 08 20 23 30 03", null ] -, [ 302, "3751AF81-0687-4D2D-88E3-6394361D18E4", 302, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-22T00:00:00", "01 18 35 39 44 11", null ] -, [ 303, "4E4D1611-40FC-4F76-8D11-814B0230E9E9", 303, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-26T00:00:00", "11 13 23 43 54 04", null ] -, [ 304, "E8AD7A64-CBF3-41E0-8841-57A88A8A9CEA", 304, 1362743858, "706580", 1362743858, "706580", "{\n}", "2012-12-29T00:00:00", "36 46 50 52 55 14", null ] -, [ 305, "EA310D55-EA1A-4AD5-AEC4-2D906D578237", 305, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-02T00:00:00", "18 20 28 35 53 20", null ] -, [ 306, "5B6740CB-25FE-4096-952A-22B8FD71049F", 306, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-05T00:00:00", "26 30 49 51 54 25", null ] -, [ 307, "2D2B2571-BCB7-43F9-903F-A95BC9352549", 307, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-09T00:00:00", "11 13 20 27 59 26", null ] -, [ 308, "B6955E33-CFE9-470E-B016-CCA4037F7E8F", 308, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-12T00:00:00", "10 14 21 23 47 07", null ] -, [ 309, "7D7ADFD8-0AD5-4D8D-BB5C-54B54BAB15F1", 309, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-16T00:00:00", "09 21 28 32 51 35", null ] -, [ 310, "F135EEBF-2581-4D4B-B30D-405AC997C32F", 310, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-19T00:00:00", "08 28 29 34 38 35", null ] -, [ 311, "9826E37F-19B7-499C-84FD-9FF396B106A4", 311, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-23T00:00:00", "11 12 24 43 45 09", null ] -, [ 312, "397246CE-545F-4119-A29C-07BC53CFDA27", 312, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-26T00:00:00", "03 22 26 41 49 18", null ] -, [ 313, "738F1EC3-A68F-437A-B9F8-A3E7DB8A259F", 313, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-01-30T00:00:00", "14 16 32 47 52 16", null ] -, [ 314, "A1A3F5C7-97C7-4C9D-A694-2C0EE2A68760", 314, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-02T00:00:00", "11 16 33 40 41 34", null ] -, [ 315, "333E4589-A54E-49D7-91D6-1FEC76CC953B", 315, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-06T00:00:00", "05 27 36 38 41 12", null ] -, [ 316, "3FC6D439-3147-4484-8519-4440B8FE2A89", 316, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-09T00:00:00", "05 06 16 36 58 03", null ] -, [ 317, "0C92A9B8-FEDC-40D7-A407-A791143CDDBE", 317, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-13T00:00:00", "12 23 25 27 43 29", null ] -, [ 318, "BAEC5F53-D2F9-48B8-8FAF-84F32B265069", 318, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-16T00:00:00", "15 16 46 50 58 29", null ] -, [ 319, "9DC15E1B-DDDC-4404-92CB-B5DE148175E0", 319, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-20T00:00:00", "03 17 19 25 32 17", null ] -, [ 320, "508D9E18-9F15-4104-ABBD-86B5461522A7", 320, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-23T00:00:00", "02 05 31 39 41 29", null ] -, [ 321, "46951F5E-AB70-43CF-A18F-8FAB450CBFC0", 321, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-02-27T00:00:00", "03 14 20 34 48 21", null ] -, [ 322, "8AD80678-E48D-45AB-8DB9-E2389662D851", 322, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-03-02T00:00:00", "03 08 13 41 56 16", null ] -, [ 323, "3422EF9A-9136-486B-8DBE-71ABA6D1996C", 323, 1362743858, "706580", 1362743858, "706580", "{\n}", "2013-03-06T00:00:00", "06 10 23 41 45 01", null ] -, [ 325, "9860B5F7-D7E7-4DFF-B95D-34032B4BEDF8", 325, 1363349314, "708543", 1363349314, "708543", "{\n}", "2013-03-09T00:00:00", "10 37 40 46 52 12", null ] -, [ 326, "0439154C-78D1-4996-8CAD-B1B954931675", 326, 1363349314, "708543", 1363349314, "708543", "{\n}", "2013-03-13T00:00:00", "05 09 28 32 38 29", null ] -, [ 328, "FCF75212-D9E5-4AFF-87BC-66189B89CB98", 328, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-03-16T00:00:00", "03 07 21 44 53 16", null ] -, [ 329, "48D32A7D-B346-4710-8BB8-42B2272FFC14", 329, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-03-20T00:00:00", "13 14 17 43 54 15", null ] -, [ 330, "F5BE3238-68A7-4A8C-9965-AB377594A587", 330, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-03-23T00:00:00", "17 29 31 52 53 31", null ] -, [ 331, "149CB1DF-EE7B-4E15-A8C8-5F1F0BFB48FC", 331, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-03-27T00:00:00", "07 37 43 48 52 16", null ] -, [ 332, "4BD3AEAF-A4B7-41DB-80E3-29A84EBD1530", 332, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-03-30T00:00:00", "11 23 26 46 55 27", null ] -, [ 333, "DC250164-F16B-448C-86BB-1552B8E73D78", 333, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-04-03T00:00:00", "01 06 08 12 35 03", null ] -, [ 334, "BB9F041B-A32F-4CEB-AFEB-469174780DFA", 334, 1365512935, "708543", 1365512935, "708543", "{\n}", "2013-04-06T00:00:00", "04 07 08 29 39 24", null ] -, [ 336, "D1BA6B1C-1971-4840-8744-146C6EA3CE93", 336, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-04-10T00:00:00", "01 36 40 52 53 20", null ] -, [ 337, "D4C28FAA-6BF6-4DCD-9E92-A7CC09C7D397", 337, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-04-13T00:00:00", "10 12 31 56 57 33", null ] -, [ 338, "0C60CBC5-7E4B-41EC-B5C2-0F22CB589A92", 338, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-04-17T00:00:00", "13 18 36 48 58 28", null ] -, [ 339, "C8DC82C1-3976-4093-94F5-3951D031210C", 339, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-04-20T00:00:00", "06 08 30 39 48 20", null ] -, [ 340, "072ED3B5-42D2-453F-866E-BA3719910A6C", 340, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-04-24T00:00:00", "09 19 31 56 59 02", null ] -, [ 341, "41B7A123-CEDC-44E9-B022-C1BABEAAEC0F", 341, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-04-27T00:00:00", "03 23 48 54 55 05", null ] -, [ 342, "EA1593AF-D20C-484F-B5FB-B12BE0C79F74", 342, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-01T00:00:00", "22 26 31 54 55 18", null ] -, [ 343, "B7035D34-88EA-49E3-B987-9BAE3D16BE1A", 343, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-04T00:00:00", "07 12 26 36 40 17", null ] -, [ 344, "31F614CE-1B8B-43F3-9365-925D7243374C", 344, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-08T00:00:00", "21 22 26 30 57 27", null ] -, [ 345, "FAC6FECB-953A-4257-9AD0-6C4A35D5783E", 345, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-11T00:00:00", "06 13 19 23 43 16", null ] -, [ 346, "AFE17066-CCB0-41AA-800C-4D02902505A5", 346, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-15T00:00:00", "02 11 26 34 41 32", null ] -, [ 347, "E86DAD23-CDEE-4116-AD03-101D8C0296E5", 347, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-18T00:00:00", "10 13 14 22 52 11", null ] -, [ 348, "F5D88A28-5B42-469C-BF81-FEA8E4C18C53", 348, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-22T00:00:00", "09 31 35 41 57 26", null ] -, [ 349, "AF3B89F6-3B42-4947-B342-3723FCDE5308", 349, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-25T00:00:00", "02 06 19 21 27 25", null ] -, [ 350, "AB777365-B121-43E3-A731-32EF418AE1C3", 350, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-05-29T00:00:00", "09 14 17 49 57 02", null ] -, [ 351, "C903B823-813C-43E0-AF7E-74DE8E5561B6", 351, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-01T00:00:00", "22 28 33 53 59 14", null ] -, [ 352, "80798224-1817-432D-89DB-DE18DFB1468E", 352, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-05T00:00:00", "04 26 33 36 55 32", null ] -, [ 353, "859F250B-4CE8-40CD-85A4-2DC7CD13012A", 353, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-08T00:00:00", "02 11 22 26 32 19", null ] -, [ 354, "837CB330-52CE-44F8-B889-32B6BAA00852", 354, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-12T00:00:00", "16 22 23 42 55 32", null ] -, [ 355, "92C7D5C3-E3F8-4AFE-88D4-462D3BCE2272", 355, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-15T00:00:00", "28 36 40 48 55 01", null ] -, [ 356, "FE49F2F1-95AC-4B43-8B2F-F07BDF89CEB3", 356, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-19T00:00:00", "07 46 47 52 57 17", null ] -, [ 357, "5D40380C-DD65-4532-AC21-CF401894B317", 357, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-22T00:00:00", "13 19 23 33 57 28", null ] -, [ 358, "0B2FCAF5-4E29-4F8F-9280-97BF0EC3D0BD", 358, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-26T00:00:00", "01 18 33 39 46 33", null ] -, [ 359, "57D0A633-35B9-451E-9620-4E26808DE6A0", 359, 1373464425, "708543", 1373464425, "708543", "{\n}", "2013-06-29T00:00:00", "08 28 30 53 56 16", null ] -, [ 361, "04AEA4EE-4D45-49C6-B20F-6A2B8F537C0F", 361, 1373960512, "708543", 1373960512, "708543", "{\n}", "2013-07-03T00:00:00", "03 06 29 40 51 04", null ] -, [ 362, "978F0309-7452-430C-B61E-08844FEA7A48", 362, 1373960512, "708543", 1373960512, "708543", "{\n}", "2013-07-06T00:00:00", "02 13 35 36 52 11", null ] -, [ 363, "063879CE-DB8E-461E-AE83-AF99A8E8DE11", 363, 1373960512, "708543", 1373960512, "708543", "{\n}", "2013-07-10T00:00:00", "30 31 45 55 59 27", null ] -, [ 365, "F9F6AE36-65EB-4ED5-9C13-18CC98C7DA23", 365, 1375427681, "708543", 1375427681, "708543", "{\n}", "2013-07-13T00:00:00", "02 08 22 35 37 06", null ] -, [ 366, "2DD53C13-565A-499E-99AB-73F43680F6A8", 366, 1375427681, "708543", 1375427681, "708543", "{\n}", "2013-07-17T00:00:00", "01 22 34 38 42 17", null ] -, [ 367, "6752A041-C2DB-49F4-A8B4-FE9B4F32A190", 367, 1375427681, "708543", 1375427681, "708543", "{\n}", "2013-07-20T00:00:00", "14 25 27 38 58 06", null ] -, [ 368, "9705E491-5DB5-4F82-8F41-E206CB414B29", 368, 1375427681, "708543", 1375427681, "708543", "{\n}", "2013-07-24T00:00:00", "09 29 40 44 54 07", null ] -, [ 369, "51ED9563-D5E9-47A3-A39F-E32B58AB4BFE", 369, 1375427681, "708543", 1375427681, "708543", "{\n}", "2013-07-27T00:00:00", "09 23 40 53 58 06", null ] -, [ 370, "48E88999-FBEB-4FDE-965C-BC6B7ABDC946", 370, 1375427681, "708543", 1375427681, "708543", "{\n}", "2013-07-31T00:00:00", "08 24 39 49 59 05", null ] -, [ 372, "74E7FBC1-422D-4B2B-9B31-BE468A39AA04", 372, 1375712128, "708543", 1375712128, "708543", "{\n}", "2013-08-03T00:00:00", "21 24 36 42 45 15", null ] -, [ 374, "CCB64CFF-4955-4BF4-88EB-CF475FDCBF6B", 374, 1376034828, "708543", 1376034828, "708543", "{\n}", "2013-08-07T00:00:00", "05 25 30 58 59 32", null ] -, [ 376, "3A5B135F-7CF4-4F6C-AC7B-D9B87997C9F5", 376, 1376312350, "708543", 1376312350, "708543", "{\n}", "2013-08-10T00:00:00", "04 12 14 37 58 13", null ] -, [ 378, "DB91BB61-FE4B-4AC7-B79B-CB62F5BFE967", 378, 1376636929, "708543", 1376636929, "708543", "{\n}", "2013-08-14T00:00:00", "04 11 17 43 51 20", null ] -, [ 380, "35791B1C-33AB-472D-80D3-4CF9A6BE30EF", 380, 1376921117, "708543", 1376921117, "708543", "{\n}", "2013-08-17T00:00:00", "18 21 46 54 56 23", null ] -, [ 382, "3DADF8FA-B273-422A-8DD2-E3DF108CCDCD", 382, 1377152900, "708543", 1377152900, "708543", "{\n}", "2013-08-21T00:00:00", "30 40 42 46 48 23", null ] -, [ 384, "C61E59C5-F18C-45A7-A9F3-1D6B69C69312", 384, 1377508995, "708543", 1377508995, "708543", "{\n}", "2013-08-24T00:00:00", "12 17 25 45 59 19", null ] -, [ 386, "E316A2A9-0932-4553-B9A2-3F4ED3AB256E", 386, 1377778238, "708543", 1377778238, "708543", "{\n}", "2013-08-28T00:00:00", "06 07 09 19 32 13", null ] -, [ 388, "CBB2374D-6251-421E-AEAA-D57E0B1C98A1", 388, 1378004467, "708543", 1378004467, "708543", "{\n}", "2013-08-31T00:00:00", "02 07 25 40 56 20", null ] -, [ 390, "B0677941-4C55-43C8-8994-5059357CF266", 390, 1378350069, "708543", 1378350069, "708543", "{\n}", "2013-09-04T00:00:00", "02 09 26 45 47 11", null ] -, [ 392, "5270488F-C21B-4969-8E2A-C452EC7F052D", 392, 1378609358, "708543", 1378609358, "708543", "{\n}", "2013-09-07T00:00:00", "02 19 22 26 45 24", null ] -, [ 396, "F3E5C8E3-49CC-4833-90B5-7A48A90BF043", 396, 1378954855, "708543", 1378954855, "708543", "{\n}", "2013-09-11T00:00:00", "11 19 33 42 52 33", null ] -, [ 398, "3281F22C-24FC-47A0-B08B-C8F7C007EA64", 398, 1379214065, "708543", 1379214065, "708543", "{\n}", "2013-09-14T00:00:00", "01 17 25 37 44 20", null ] -, [ 400, "03D572D2-4D3B-4576-A2C8-D09C7B640839", 400, 1379559676, "708543", 1379559676, "708543", "{\n}", "2013-09-18T00:00:00", "07 10 22 32 35 19", null ] -, [ 402, "F0A0B8DD-B47E-4396-81C0-6ACED79548F2", 402, 1379818889, "708543", 1379818889, "708543", "{\n}", "2013-09-21T00:00:00", "12 17 45 54 58 13", null ] -, [ 404, "AA19E8C5-B164-47E6-A4B2-11F301B635DF", 404, 1380164455, "708543", 1380164455, "708543", "{\n}", "2013-09-25T00:00:00", "02 07 17 49 53 23", null ] -, [ 406, "5C8930B7-59A9-495E-9CD9-EDA4F114190C", 406, 1380423676, "708543", 1380423676, "708543", "{\n}", "2013-09-28T00:00:00", "14 47 52 53 54 05", null ] -, [ 408, "AAB2E771-B827-45A1-8C4C-5FF4247E54A2", 408, 1380769256, "708543", 1380769256, "708543", "{\n}", "2013-10-02T00:00:00", "04 06 25 42 51 17", null ] -, [ 410, "A11A6AD2-571D-4E68-9531-D7613C9AC5D4", 410, 1381028464, "708543", 1381028464, "708543", "{\n}", "2013-10-05T00:00:00", "11 12 17 39 40 05", null ] -, [ 412, "BE0D91A1-302C-426D-A891-BCC716FF77F4", 412, 1381374055, "708543", 1381374055, "708543", "{\n}", "2013-10-09T00:00:00", "03 09 19 33 38 18", null ] -, [ 414, "D088796F-DED4-4512-A6CD-965D62DFCD46", 414, 1381633254, "708543", 1381633254, "708543", "{\n}", "2013-10-12T00:00:00", "08 10 26 57 58 04", null ] -, [ 416, "A1F81DDE-1222-482A-9797-99BDE4C680B7", 416, 1381978865, "708543", 1381978865, "708543", "{\n}", "2013-10-16T00:00:00", "03 26 28 34 42 28", null ] -, [ 418, "B3EB04B8-0EB0-4863-A062-BDC74A5B55F8", 418, 1382238075, "708543", 1382238075, "708543", "{\n}", "2013-10-19T00:00:00", "09 33 54 56 57 05", null ] -, [ 420, "81A24BED-C113-41DB-A8D7-BFA00A811E52", 420, 1382583677, "708543", 1382583677, "708543", "{\n}", "2013-10-23T00:00:00", "03 23 31 34 47 13", null ] -, [ 422, "DA233102-CFC8-488A-9878-D4DA316E1FEE", 422, 1382842854, "708543", 1382842854, "708543", "{\n}", "2013-10-26T00:00:00", "04 06 34 49 56 29", null ] -, [ 424, "BCD1777E-78BF-42AE-9F75-051E8AB6D526", 424, 1383188463, "708543", 1383188463, "708543", "{\n}", "2013-10-30T00:00:00", "02 36 40 49 54 10", null ] -, [ 426, "3C980E92-DBA6-43EA-9C2F-6A357D8C198B", 426, 1383447654, "708543", 1383447654, "708543", "{\n}", "2013-11-02T00:00:00", "13 23 24 27 40 17", null ] -, [ 428, "C6F8ACA9-A326-4CAF-9A5B-0D1848566D1A", 428, 1383793266, "708543", 1383793266, "708543", "{\n}", "2013-11-06T00:00:00", "01 05 10 15 49 22", null ] -, [ 430, "A1AA1335-1304-41B6-9143-325B91A54538", 430, 1384052454, "708543", 1384052454, "708543", "{\n}", "2013-11-09T00:00:00", "03 09 37 49 56 32", null ] -, [ 432, "875C9020-62D2-4C17-B5EE-E82B2ED215F0", 432, 1384398377, "708543", 1384398377, "708543", "{\n}", "2013-11-13T00:00:00", "05 31 50 55 56 09", null ] -, [ 434, "A663C837-573A-4100-A04D-32D154358CEF", 434, 1384657257, "708543", 1384657257, "708543", "{\n}", "2013-11-16T00:00:00", "10 29 37 44 59 10", null ] -, [ 436, "EF0B5D0B-6670-4ED1-BD05-7F753D7BD99E", 436, 1385002844, "708543", 1385002844, "708543", "{\n}", "2013-11-20T00:00:00", "04 18 23 32 45 07", null ] -, [ 438, "6E46D30A-E623-4F9E-AE38-A28FF69C700D", 438, 1385262044, "708543", 1385262044, "708543", "{\n}", "2013-11-23T00:00:00", "05 12 43 52 55 10", null ] -, [ 440, "84BFA534-38CC-4912-A4BE-6C5718E04989", 440, 1385607655, "708543", 1385607655, "708543", "{\n}", "2013-11-27T00:00:00", "18 25 50 55 57 17", null ] -, [ 442, "4FDC7B73-BC13-4F98-9DD5-00B40EEF893A", 442, 1385866854, "708543", 1385866854, "708543", "{\n}", "2013-11-30T00:00:00", "05 26 44 45 57 29", null ] -, [ 444, "325D02BB-4FC5-4A32-A398-3A68C9C2DB69", 444, 1386212457, "708543", 1386212457, "708543", "{\n}", "2013-12-04T00:00:00", "06 09 11 31 44 25", null ] -, [ 446, "50AD8F90-A9BE-4390-8C78-FC00C4A81C76", 446, 1386471654, "708543", 1386471654, "708543", "{\n}", "2013-12-07T00:00:00", "13 20 32 45 48 17", null ] -, [ 448, "CC93F4A9-00A4-4525-BC38-9DE756831B28", 448, 1386817266, "708543", 1386817266, "708543", "{\n}", "2013-12-11T00:00:00", "01 10 13 18 19 27", null ] -, [ 450, "C003B8B1-CDB9-498C-9C7D-C4ECC78ED256", 450, 1387076495, "708543", 1387076495, "708543", "{\n}", "2013-12-14T00:00:00", "14 25 32 33 41 34", null ] -, [ 452, "C538153A-1685-4B6C-9A6E-A08F40474590", 452, 1387422065, "708543", 1387422065, "708543", "{\n}", "2013-12-18T00:00:00", "07 24 37 39 40 01", null ] -, [ 454, "393859FA-4F84-4694-9404-8373A0A70B92", 454, 1387724454, "708543", 1387724454, "708543", "{\n}", "2013-12-21T00:00:00", "25 36 40 45 51 08", null ] -, [ 456, "DEA4DB56-E3E5-492D-8F26-8F121A050F39", 456, 1388026855, "708543", 1388026855, "708543", "{\n}", "2013-12-25T00:00:00", "23 28 38 39 56 32", null ] -, [ 458, "2E898FF5-500D-46BB-B25E-715243B6D85F", 458, 1388286097, "708543", 1388286097, "708543", "{\n}", "2013-12-28T00:00:00", "08 35 44 51 56 18", null ] -, [ 460, "869B299A-CB43-42BA-96B5-0C52C7B2948B", 460, 1388631654, "708543", 1388631654, "708543", "{\n}", "2014-01-01T00:00:00", "15 24 40 48 52 23", null ] -, [ 462, "6992200D-6A41-45F0-B6CE-D0DBB8C067F3", 462, 1388890864, "708543", 1388890864, "708543", "{\n}", "2014-01-04T00:00:00", "19 20 37 41 58 14", null ] -, [ 464, "CB8287E5-7897-4CFA-8EA7-364CDE173A5C", 464, 1389236455, "708543", 1389236455, "708543", "{\n}", "2014-01-08T00:00:00", "10 28 39 47 58 22", null ] -, [ 466, "06973D85-FD1A-4DB3-95B0-56A307538275", 466, 1389495704, "708543", 1389495704, "708543", "{\n}", "2014-01-11T00:00:00", "10 15 33 48 54 34", null ] -, [ 468, "8FD5794D-0FD0-4164-AB47-EA69A2726DA2", 468, 1389841276, "708543", 1389841276, "708543", "{\n}", "2014-01-15T00:00:00", "07 08 09 24 29 25", null ] -, [ 470, "632FA9B1-6504-4745-A858-A4AD77142A73", 470, 1390100458, "708543", 1390100458, "708543", "{\n}", "2014-01-18T00:00:00", "13 14 19 31 38 25", null ] -, [ 472, "6B5C814C-3778-4C08-A8E8-14A2690DB4E1", 472, 1390446076, "708543", 1390446076, "708543", "{\n}", "2014-01-22T00:00:00", "01 02 07 09 55 29", "3" ] -, [ 474, "959EED5C-40DB-46A6-BA50-8C7F18F12B9B", 474, 1390705283, "708543", 1390705283, "708543", "{\n}", "2014-01-25T00:00:00", "08 12 18 55 57 02", "2" ] -, [ 476, "CF00D567-AD20-4773-98F0-D6F59CEBEB0A", 476, 1391050868, "708543", 1391050868, "708543", "{\n}", "2014-01-29T00:00:00", "11 23 28 32 47 20", "2" ] -, [ 478, "16039CD5-5D97-462D-80B9-C7E57C4219E1", 478, 1391310055, "708543", 1391310055, "708543", "{\n}", "2014-02-01T00:00:00", "05 12 15 27 38 07", "2" ] -, [ 480, "7662D28E-81B6-4F64-9D1D-928B22ADAAD8", 480, 1391655655, "708543", 1391655655, "708543", "{\n}", "2014-02-05T00:00:00", "08 17 32 57 59 24", "3" ] -, [ 482, "E2CD3E79-8E4D-49A1-AC4E-75678402B48D", 482, 1391914866, "708543", 1391914866, "708543", "{\n}", "2014-02-08T00:00:00", "24 25 34 37 54 29", "2" ] -, [ 484, "3F39F11A-2E74-44CF-BDD9-7E456C37AC50", 484, 1392260446, "708543", 1392260446, "708543", "{\n}", "2014-02-12T00:00:00", "36 44 49 52 57 01", "2" ] -, [ 486, "38A5578D-6E92-430E-9674-0255200D4928", 486, 1392519644, "708543", 1392519644, "708543", "{\n}", "2014-02-15T00:00:00", "02 09 14 21 23 03", "3" ] -, [ 488, "5A0B4133-BE25-4EDE-9686-3F3939CE78B1", 488, 1392865281, "708543", 1392865281, "708543", "{\n}", "2014-02-19T00:00:00", "01 17 35 49 54 34", "3" ] -, [ 490, "72286024-9A34-4F95-85BD-71C9ABFD2765", 490, 1393124475, "708543", 1393124475, "708543", "{\n}", "2014-02-22T00:00:00", "02 03 13 14 54 04", "5" ] -, [ 492, "06333392-9CB1-4436-B6DB-E0A8A264B065", 492, 1393470054, "708543", 1393470054, "708543", "{\n}", "2014-02-26T00:00:00", "11 12 17 38 42 02", "2" ] -, [ 494, "A96E282B-1D16-443C-9506-FE865E27E0BF", 494, 1393729254, "708543", 1393729254, "708543", "{\n}", "2014-03-01T00:00:00", "03 08 25 30 47 13", "4" ] -, [ 496, "DF678B5A-F304-494C-AEC5-39922FA6FB03", 496, 1394074812, "708543", 1394074812, "708543", "{\n}", "2014-03-05T00:00:00", "03 07 09 26 54 19", "2" ] -, [ 498, "B5F25102-9FFD-4696-B916-73870F17DFBA", 498, 1394334054, "708543", 1394334054, "708543", "{\n}", "2014-03-08T00:00:00", "10 14 24 32 41 30", "2" ] -, [ 500, "C38A2D61-6CC5-430E-BB3A-37446F6C7263", 500, 1394679655, "708543", 1394679655, "708543", "{\n}", "2014-03-12T00:00:00", "14 15 28 37 54 10", "2" ] -, [ 502, "079EA7C4-965C-4E3D-9836-9B92C6BE73E5", 502, 1394938854, "708543", 1394938854, "708543", "{\n}", "2014-03-15T00:00:00", "02 05 34 51 58 09", "4" ] -, [ 504, "FD32D0FB-4D24-4317-B944-784A4EC18BF5", 504, 1395284455, "708543", 1395284455, "708543", "{\n}", "2014-03-19T00:00:00", "02 19 23 34 43 14", "2" ] -, [ 506, "2B7067E1-A09E-48C4-9798-5A8FCF035ACE", 506, 1395543655, "708543", 1395543655, "708543", "{\n}", "2014-03-22T00:00:00", "13 28 31 55 58 15", "2" ] -, [ 508, "30FF8647-C283-41A2-9DCC-A8D7384F1EB7", 508, 1395889255, "708543", 1395889255, "708543", "{\n}", "2014-03-26T00:00:00", "28 33 41 44 59 21", "2" ] -, [ 510, "739C3709-5735-4AF0-A580-719A06580CCB", 510, 1396148444, "708543", 1396148444, "708543", "{\n}", "2014-03-29T00:00:00", "02 03 12 27 38 17", "2" ] -, [ 512, "3CF1F0CA-F90D-48A7-96BB-FAD65E3CC086", 512, 1396494070, "708543", 1396494070, "708543", "{\n}", "2014-04-02T00:00:00", "08 13 19 22 53 24", "2" ] -, [ 514, "9F59ED34-C239-4AE8-8678-09B3D2D039B1", 514, 1396753245, "708543", 1396753245, "708543", "{\n}", "2014-04-05T00:00:00", "11 21 26 33 34 29", "5" ] -, [ 516, "6D64F1A9-4039-4193-A9D2-951048F7C1AC", 516, 1397098855, "708543", 1397098855, "708543", "{\n}", "2014-04-09T00:00:00", "09 14 44 48 49 29", "2" ] -, [ 518, "C20FBD64-77FB-497C-86D6-9C66C29AA034", 518, 1397358054, "708543", 1397358054, "708543", "{\n}", "2014-04-12T00:00:00", "14 26 45 54 55 20", "2" ] -, [ 520, "82F04093-BAEB-4764-9D9C-575EA9E17E3E", 520, 1397703676, "708543", 1397703676, "708543", "{\n}", "2014-04-16T00:00:00", "34 39 42 44 59 08", "3" ] -, [ 522, "C0C4BB31-08F9-4FC8-8A5C-D3CD57B7A5C9", 522, 1397962855, "708543", 1397962855, "708543", "{\n}", "2014-04-19T00:00:00", "05 06 29 35 51 21", "5" ] -, [ 524, "4AB21E57-4F08-48A7-BAAE-E39DE7770947", 524, 1398308454, "708543", 1398308454, "708543", "{\n}", "2014-04-23T00:00:00", "19 25 29 36 48 12", "4" ] -, [ 526, "1B2FF91E-4DF8-45F7-9983-CCBF68599DD0", 526, 1398567654, "708543", 1398567654, "708543", "{\n}", "2014-04-26T00:00:00", "03 07 22 30 33 20", "3" ] -, [ 528, "41BBC522-A603-4A2D-BFBD-F45B00F2D96A", 528, 1398913245, "708543", 1398913245, "708543", "{\n}", "2014-04-30T00:00:00", "02 09 11 19 50 32", "3" ] -, [ 530, "487D1FF3-303E-4D43-BD9F-7FBCEEA53A78", 530, 1399172525, "708543", 1399172525, "708543", "{\n}", "2014-05-03T00:00:00", "05 15 16 46 49 26", "4" ] -, [ 532, "C096BBA0-25ED-4CAF-9872-27CDF41C3AB2", 532, 1399518165, "708543", 1399518165, "708543", "{\n}", "2014-05-07T00:00:00", "17 29 31 48 49 34", "2" ] -, [ 534, "5A46495E-2CB7-4C99-A3FF-6B829658680B", 534, 1399777318, "708543", 1399777318, "708543", "{\n}", "2014-05-10T00:00:00", "04 31 41 47 55 01", "2" ] -, [ 536, "44B9F291-72B1-4456-B88A-AF46130AB86A", 536, 1400122951, "708543", 1400122951, "708543", "{\n}", "2014-05-14T00:00:00", "07 33 39 52 55 33", "3" ] -, [ 538, "3BA9206D-AA33-4EED-8E23-3B022B7E06EC", 538, 1400382119, "708543", 1400382119, "708543", "{\n}", "2014-05-17T00:00:00", "23 32 39 47 49 22", "3" ] -, [ 540, "10E769B9-E7B7-4048-9302-B596CD6278DD", 540, 1400727781, "708543", 1400727781, "708543", "{\n}", "2014-05-21T00:00:00", "04 20 34 39 58 31", "5" ] -, [ 542, "1F143612-927F-4772-8B81-B62E2F26990C", 542, 1400986845, "708543", 1400986845, "708543", "{\n}", "2014-05-24T00:00:00", "15 16 28 49 55 18", "2" ] -, [ 544, "75647DDC-DE92-4874-A22C-453F73FBC94F", 544, 1401332519, "708543", 1401332519, "708543", "{\n}", "2014-05-28T00:00:00", "02 24 28 32 59 25", "3" ] -, [ 546, "07092E27-EB7F-4781-A41C-56FC4509332C", 546, 1401591729, "708543", 1401591729, "708543", "{\n}", "2014-05-31T00:00:00", "15 27 31 34 48 01", "2" ] -, [ 548, "DBB2A4CA-C19A-4E21-9934-3774E0CCED88", 548, 1402024048, "708543", 1402024048, "708543", "{\n}", "2014-06-04T00:00:00", "01 07 10 22 49 24", "3" ] -, [ 550, "D18F3C84-81FD-46FB-A1FC-16090A6305AC", 550, 1402196528, "708543", 1402196528, "708543", "{\n}", "2014-06-07T00:00:00", "28 30 35 58 59 15", "2" ] -, [ 552, "3B509634-0F92-481A-8A92-B3DCD47BDB27", 552, 1402542055, "708543", 1402542055, "708543", "{\n}", "2014-06-11T00:00:00", "14 18 25 33 49 23", "5" ] -, [ 554, "913D60FF-B8B0-400A-91CB-8C588A4D0BB3", 554, 1402844528, "708543", 1402844528, "708543", "{\n}", "2014-06-14T00:00:00", "09 33 42 45 54 30", "3" ] -, [ 556, "54661135-06E8-401F-92FD-07186ACC9C1B", 556, 1403233446, "708543", 1403233446, "708543", "{\n}", "2014-06-18T00:00:00", "06 09 29 52 59 07", "3" ] -, [ 558, "FD92596C-A65C-4C4D-B1BF-79E9E47619A9", 558, 1403406138, "708543", 1403406138, "708543", "{\n}", "2014-06-21T00:00:00", "05 06 37 41 54 26", "3" ] -, [ 560, "4003D691-5309-4F30-B2B0-E19E03AAC642", 560, 1403751739, "708543", 1403751739, "708543", "{\n}", "2014-06-25T00:00:00", "10 20 25 50 53 35", "4" ] -, [ 562, "52E50253-BF74-40B5-9581-682B443841D2", 562, 1404356454, "708543", 1404356454, "708543", "{\n}", "2014-07-02T00:00:00", "08 18 45 53 58 35", "2" ] -, [ 564, "8CB66308-6F25-476F-95DE-A7C8E1D621CD", 564, 1404615645, "708543", 1404615645, "708543", "{\n}", "2014-07-05T00:00:00", "24 34 36 57 58 11", "4" ] -, [ 566, "0D0AAA69-2F7A-4D5F-9DF3-C9701C7BAC22", 566, 1404961255, "708543", 1404961255, "708543", "{\n}", "2014-07-09T00:00:00", "09 25 42 55 57 14", "2" ] -, [ 568, "55FE34B2-623D-4241-A89E-308A84B4C74B", 568, 1405220454, "708543", 1405220454, "708543", "{\n}", "2014-07-12T00:00:00", "02 03 07 23 51 26", "2" ] -, [ 570, "FCFDF56B-4E14-49E5-867F-C2E4AB445A9F", 570, 1405582531, "708543", 1405582531, "708543", "{\n}", "2014-07-16T00:00:00", "05 15 18 26 32 35", "3" ] -, [ 572, "1716855F-F638-4C7E-8B8D-8EF7F73B5B06", 572, 1405825244, "708543", 1405825244, "708543", "{\n}", "2014-07-19T00:00:00", "10 17 25 45 53 09", "2" ] -, [ 574, "7D6898C6-01D5-4782-95BA-C2749ADFE9BC", 574, 1406170855, "708543", 1406170855, "708543", "{\n}", "2014-07-23T00:00:00", "04 10 12 22 31 03", "5" ] -, [ 576, "D62285D6-7C01-4C90-B7A9-C4D14752E119", 576, 1406430095, "708543", 1406430095, "708543", "{\n}", "2014-07-26T00:00:00", "24 28 30 38 39 16", "2" ] -, [ 578, "394E9921-468B-4E29-B772-59A0C54F5492", 578, 1406775657, "708543", 1406775657, "708543", "{\n}", "2014-07-30T00:00:00", "13 30 42 49 53 29", "3" ] -, [ 580, "284B0E05-5283-488D-AFE0-5B256E9D81C0", 580, 1407034866, "708543", 1407034866, "708543", "{\n}", "2014-08-02T00:00:00", "12 26 44 46 47 29", "2" ] -, [ 582, "62B6DC77-A166-4553-8D32-8A8F7840EC9F", 582, 1407380456, "708543", 1407380456, "708543", "{\n}", "2014-08-06T00:00:00", "01 08 24 28 49 24", "5" ] -, [ 584, "B5ACA65E-F5FE-4764-8138-2C700D050E05", 584, 1407639655, "708543", 1407639655, "708543", "{\n}", "2014-08-09T00:00:00", "03 12 31 34 51 24", "2" ] -, [ 586, "FB356DBD-E3D3-465F-8A17-C7465009E078", 586, 1407985265, "708543", 1407985265, "708543", "{\n}", "2014-08-13T00:00:00", "08 37 39 40 52 24", "2" ] -, [ 588, "1AADCEC8-EF2A-47A0-9508-69E2D0A25C21", 588, 1408244445, "708543", 1408244445, "708543", "{\n}", "2014-08-16T00:00:00", "07 08 17 48 59 09", "2" ] -, [ 590, "ADB2B268-7B1F-4A3C-B252-DF4298ED22F6", 590, 1408590066, "708543", 1408590066, "708543", "{\n}", "2014-08-20T00:00:00", "04 08 21 38 40 03", "2" ] -, [ 592, "F1DB5012-8A45-4E79-B123-79C3F17AE2DA", 592, 1408849266, "708543", 1408849266, "708543", "{\n}", "2014-08-23T00:00:00", "28 32 35 36 52 31", "3" ] -, [ 594, "B33326D6-1FA2-4719-9888-9C6E88EBFFEA", 594, 1409194865, "708543", 1409194865, "708543", "{\n}", "2014-08-27T00:00:00", "17 24 26 45 46 19", "3" ] -, [ 596, "4A22925B-EB06-46B1-BB68-407C5E31D5E7", 596, 1409454066, "708543", 1409454066, "708543", "{\n}", "2014-08-30T00:00:00", "05 28 31 52 59 27", "2" ] -, [ 598, "7858F42B-EB4E-408A-A84B-5AEBA66AA3DF", 598, 1409886079, "708543", 1409886079, "708543", "{\n}", "2014-09-03T00:00:00", "02 16 43 45 51 35", "3" ] -, [ 600, "97430822-1C96-46B9-92BF-86AB1BA10905", 600, 1410058856, "708543", 1410058856, "708543", "{\n}", "2014-09-06T00:00:00", "09 29 31 43 50 18", "2" ] -, [ 602, "CABB0AFD-C37C-4E49-B8C6-7D5F86DCE1A7", 602, 1410404493, "708543", 1410404493, "708543", "{\n}", "2014-09-10T00:00:00", "02 14 39 40 43 13", "5" ] -, [ 604, "D1EB641C-B9E7-4958-BFA3-6A6E353EA51A", 604, 1410857379, "708543", 1410857379, "708543", "{\n}", "2014-09-13T00:00:00", "01 06 16 37 53 27", "3" ] -, [ 606, "68358BCC-7ACC-4505-91BA-33741DE045AA", 606, 1411009291, "708543", 1411009291, "708543", "{\n}", "2014-09-17T00:00:00", "18 25 36 48 50 23", "2" ] -, [ 608, "58DCE448-E60B-4D6A-A67C-0B31304E01D4", 608, 1411484653, "708543", 1411484653, "708543", "{\n}", "2014-09-20T00:00:00", "22 23 30 37 39 16", "4" ] -, [ 610, "A125446B-3200-4E26-8E30-D3E0D11AEEA8", 610, 1411741517, "708543", 1411741517, "708543", "{\n}", "2014-09-24T00:00:00", "07 14 21 24 41 26", "4" ] -, [ 612, "44FDD0E0-D854-4CBB-A674-4E748BB851E6", 612, 1411873297, "708543", 1411873297, "708543", "{\n}", "2014-09-27T00:00:00", "02 11 35 52 54 13", "3" ] -, [ 614, "833921F3-DA63-4F64-8435-FE0FF6907174", 614, 1412218893, "708543", 1412218893, "708543", "{\n}", "2014-10-01T00:00:00", "01 04 18 20 45 07", "2" ] -, [ 616, "EE6B6F59-37D7-45CC-BE81-AA2F1F308F2C", 616, 1412521327, "708543", 1412521327, "708543", "{\n}", "2014-10-04T00:00:00", "13 18 24 25 33 31", "2" ] -, [ 618, "F8E7AC21-2BDD-4DEE-97A9-7228CF621E0A", 618, 1412823672, "708543", 1412823672, "708543", "{\n}", "2014-10-08T00:00:00", "05 16 31 46 50 18", "3" ] -, [ 620, "E8BE2206-8EF5-4CBA-BC14-97458F655875", 620, 1413082889, "708543", 1413082889, "708543", "{\n}", "2014-10-11T00:00:00", "10 19 37 38 39 28", "2" ] -, [ 622, "36FCC416-19AC-49D7-A6A5-6F2B02B14037", 622, 1413428491, "708543", 1413428491, "708543", "{\n}", "2014-10-15T00:00:00", "05 07 19 27 28 20", "2" ] -, [ 624, "4DB598EB-4512-4085-AB52-B31451700CE4", 624, 1413687689, "708543", 1413687689, "708543", "{\n}", "2014-10-18T00:00:00", "20 26 27 36 54 19", "2" ] -, [ 626, "D8A3E583-5FAB-4687-9C12-DF66BC25D1A1", 626, 1414033290, "708543", 1414033290, "708543", "{\n}", "2014-10-22T00:00:00", "29 30 40 42 50 16", "2" ] -, [ 628, "94A238A4-0D81-4904-93F0-94206E2A507D", 628, 1414292491, "708543", 1414292491, "708543", "{\n}", "2014-10-25T00:00:00", "06 10 51 54 57 12", "2" ] -, [ 630, "6A101A82-36BA-47CD-965F-CD0E9DC46DA1", 630, 1414638069, "708543", 1414638069, "708543", "{\n}", "2014-10-29T00:00:00", "25 28 48 57 59 16", "3" ] -, [ 632, "C216F750-2E31-4F60-9188-F2412BF65C5C", 632, 1414897288, "708543", 1414897288, "708543", "{\n}", "2014-11-01T00:00:00", "01 03 13 25 38 17", "2" ] -, [ 634, "C2DD204C-8C36-4F3A-826C-93A4B5FDA4B9", 634, 1415329396, "708543", 1415329396, "708543", "{\n}", "2014-11-05T00:00:00", "02 11 19 21 42 34", "3" ] -, [ 636, "10664F33-06F4-44A8-ACFC-B4577D5EC5EA", 636, 1415502092, "708543", 1415502092, "708543", "{\n}", "2014-11-08T00:00:00", "09 19 33 38 54 15", "3" ] -, [ 638, "412214CC-C4CC-4993-AA11-7F6FAE4060AF", 638, 1415847687, "708543", 1415847687, "708543", "{\n}", "2014-11-12T00:00:00", "37 39 51 52 55 11", "3" ] -, [ 640, "8590E6C5-15BF-42B1-A4F6-6C15C6C21B8B", 640, 1416193376, "708543", 1416193376, "708543", "{\n}", "2014-11-15T00:00:00", "13 16 33 35 51 28", "2" ] -, [ 642, "A8BAE147-EA3C-4252-ABE0-06641E9414C2", 642, 1416452533, "708543", 1416452533, "708543", "{\n}", "2014-11-19T00:00:00", "06 36 38 48 51 17", "2" ] -, [ 644, "8856B080-2BF0-4C94-919F-CAD7D14D394B", 644, 1416711688, "708543", 1416711688, "708543", "{\n}", "2014-11-22T00:00:00", "23 49 53 54 57 35", "2" ] -, [ 646, "EDE28D34-E74E-4EB6-AA31-B7E291380862", 646, 1417057290, "708543", 1417057290, "708543", "{\n}", "2014-11-26T00:00:00", "16 17 22 46 54 35", "5" ] -, [ 648, "492FE8DB-DF45-46CC-98A2-75020B7AE310", 648, 1417316490, "708543", 1417316490, "708543", "{\n}", "2014-11-29T00:00:00", "13 24 30 42 48 27", "2" ] -, [ 650, "8A284F29-40F3-4934-80C2-DEC138E688C4", 650, 1417662093, "708543", 1417662093, "708543", "{\n}", "2014-12-03T00:00:00", "25 30 32 46 54 26", "3" ] -, [ 652, "6B8C9416-B679-4062-AE0E-2F5D4DE63AAB", 652, 1417921272, "708543", 1417921272, "708543", "{\n}", "2014-12-06T00:00:00", "12 15 22 43 49 14", "2" ] -, [ 654, "B5E65633-5DC5-41A9-A777-47BF48B5694F", 654, 1418266870, "708543", 1418266870, "708543", "{\n}", "2014-12-10T00:00:00", "34 44 48 54 55 10", "2" ] -, [ 656, "2078DFB3-E426-458F-B76C-8CF659E96CDD", 656, 1418526094, "708543", 1418526094, "708543", "{\n}", "2014-12-13T00:00:00", "05 13 28 43 55 33", "3" ] -, [ 658, "576E343A-594A-49F4-BAF2-320389AED2C8", 658, 1418871699, "708543", 1418871699, "708543", "{\n}", "2014-12-17T00:00:00", "22 31 38 47 48 15", "3" ] -, [ 660, "C5AF5FF2-DA14-4056-865F-7C7F55E705CB", 660, 1419130892, "708543", 1419130892, "708543", "{\n}", "2014-12-20T00:00:00", "14 15 19 31 56 05", "5" ] -, [ 662, "5E6A6652-C161-4DA4-9D8E-1791C9D0DDA5", 662, 1419476499, "708543", 1419476499, "708543", "{\n}", "2014-12-24T00:00:00", "11 12 46 47 50 22", "4" ] -, [ 664, "A973E6CD-C592-490A-A8B9-99597CFB0166", 664, 1419735679, "708543", 1419735679, "708543", "{\n}", "2014-12-27T00:00:00", "07 10 11 14 36 15", "2" ] -, [ 666, "852D9F3D-2D01-456C-97B3-323697723F5F", 666, 1420081293, "708543", 1420081293, "708543", "{\n}", "2014-12-31T00:00:00", "17 27 37 40 53 35", "2" ] -, [ 668, "3F7A2659-CCCC-4C35-BD86-0E3C025C9311", 668, 1420340499, "708543", 1420340499, "708543", "{\n}", "2015-01-03T00:00:00", "04 18 43 46 55 25", "3" ] -, [ 670, "434CE58A-723C-4C47-9D33-67064A0081B4", 670, 1420686097, "708543", 1420686097, "708543", "{\n}", "2015-01-07T00:00:00", "14 15 47 49 59 10", "2" ] -, [ 672, "C9C20E1B-B660-43F9-80EE-BFA56EB5ADFF", 672, 1420945292, "708543", 1420945292, "708543", "{\n}", "2015-01-10T00:00:00", "02 09 19 28 29 19", "5" ] -, [ 674, "60D4CBA8-C33C-4F8D-9A5F-A091A06EEE39", 674, 1421290892, "708543", 1421290892, "708543", "{\n}", "2015-01-14T00:00:00", "02 04 10 41 53 22", "5" ] -, [ 676, "96C3084D-A699-477E-940E-7540D2E079DD", 676, 1421550089, "708543", 1421550089, "708543", "{\n}", "2015-01-17T00:00:00", "15 16 23 27 36 09", "2" ] -, [ 678, "64D16892-1A8F-4BD3-AD08-0F12AF37DC5B", 678, 1421895752, "708543", 1421895752, "708543", "{\n}", "2015-01-21T00:00:00", "11 12 15 28 57 23", "4" ] -, [ 680, "9B98D299-2E89-45CC-9C20-CA9A9858401C", 680, 1422154888, "708543", 1422154888, "708543", "{\n}", "2015-01-24T00:00:00", "16 19 20 29 33 10", "2" ] -, [ 682, "C8B9F03E-D092-4B68-A882-060CC9A3D5A4", 682, 1422500493, "708543", 1422500493, "708543", "{\n}", "2015-01-28T00:00:00", "12 24 35 36 49 01", "5" ] -, [ 684, "2031E7C9-B0FA-43E5-A952-25686F49FE00", 684, 1422759691, "708543", 1422759691, "708543", "{\n}", "2015-01-31T00:00:00", "05 11 16 26 50 34", "2" ] -, [ 686, "B7216262-139E-4F1A-BA84-5DB845271DAE", 686, 1423105293, "708543", 1423105293, "708543", "{\n}", "2015-02-04T00:00:00", "24 36 51 52 56 22", "2" ] -, [ 688, "08D2F580-1207-45F6-A29F-7FE66620CD90", 688, 1423364488, "708543", 1423364488, "708543", "{\n}", "2015-02-07T00:00:00", "05 10 21 34 58 33", "5" ] -, [ 690, "DDF1543E-9A9B-4ACE-BAFE-8AB37973E90C", 690, 1423710069, "708543", 1423710069, "708543", "{\n}", "2015-02-11T00:00:00", "11 13 25 39 54 19", "3" ] -, [ 692, "435F62B2-DF03-4FB8-A8B8-52E5A75666D3", 692, 1423969290, "708543", 1423969290, "708543", "{\n}", "2015-02-14T00:00:00", "01 24 44 45 51 28", "2" ] -, [ 694, "3156E6C0-2C89-45D1-9CD4-26C73005A7B3", 694, 1424314889, "708543", 1424314889, "708543", "{\n}", "2015-02-18T00:00:00", "01 09 29 32 49 22", "2" ] -, [ 696, "78AFD76F-A532-4015-821A-A6052893850A", 696, 1424574090, "708543", 1424574090, "708543", "{\n}", "2015-02-21T00:00:00", "10 14 18 34 51 26", "2" ] -, [ 698, "1958CB7F-4F9B-461B-9304-89D6C516BF36", 698, 1424919689, "708543", 1424919689, "708543", "{\n}", "2015-02-25T00:00:00", "17 19 21 32 39 08", "3" ] -, [ 700, "EDCD1F4D-DF40-4372-A354-00A3F20BA52E", 700, 1425178891, "708543", 1425178891, "708543", "{\n}", "2015-02-28T00:00:00", "11 17 25 28 46 12", "2" ] -, [ 702, "F1546B7C-472E-4965-8CF5-A60A2F488AEE", 702, 1425524491, "708543", 1425524491, "708543", "{\n}", "2015-03-04T00:00:00", "08 12 15 35 50 32", "2" ] -, [ 704, "B79C61A2-F6BE-45C7-A8E2-AF96CAF6BCA8", 704, 1425783779, "708543", 1425783779, "708543", "{\n}", "2015-03-07T00:00:00", "34 36 38 42 50 33", "4" ] -, [ 706, "65C41C93-2669-45C8-BF86-9583480708E0", 706, 1426129290, "708543", 1426129290, "708543", "{\n}", "2015-03-11T00:00:00", "11 24 31 40 44 27", "2" ] -, [ 708, "21E7CFAA-5C8C-4714-B690-23C86D9DD12F", 708, 1426388488, "708543", 1426388488, "708543", "{\n}", "2015-03-14T00:00:00", "08 14 39 46 47 18", "2" ] -, [ 710, "82F2F807-EC9F-42E1-B804-AEEABBC72D9E", 710, 1426734087, "708543", 1426734087, "708543", "{\n}", "2015-03-18T00:00:00", "14 25 30 33 47 08", "2" ] -, [ 712, "47FE9CA5-F869-4345-A69D-5E941CF5FFBB", 712, 1426993286, "708543", 1426993286, "708543", "{\n}", "2015-03-21T00:00:00", "11 16 30 38 42 07", "4" ] -, [ 714, "54EE26F7-D934-48B1-8BA1-B3285B3FBC19", 714, 1427338886, "708543", 1427338886, "708543", "{\n}", "2015-03-25T00:00:00", "07 19 23 50 54 14", "2" ] -, [ 716, "9934E265-895E-421B-8ACC-BDE393F70FF3", 716, 1427598086, "708543", 1427598086, "708543", "{\n}", "2015-03-28T00:00:00", "02 04 06 12 38 17", "3" ] -, [ 718, "36663E0C-0277-4255-B11C-2F697A9B8525", 718, 1427943687, "708543", 1427943687, "708543", "{\n}", "2015-04-01T00:00:00", "02 30 33 39 44 01", "3" ] -, [ 720, "C0E1AACD-A900-4A28-AA88-B712DB48FCC0", 720, 1428202890, "708543", 1428202890, "708543", "{\n}", "2015-04-04T00:00:00", "33 39 40 41 54 28", "3" ] -, [ 722, "92E8465A-5CDF-4BED-83FA-7BD027280751", 722, 1428548489, "708543", 1428548489, "708543", "{\n}", "2015-04-08T00:00:00", "01 19 45 46 58 29", "2" ] -, [ 724, "E6490D86-EF2D-4C79-A2E1-DCD02F7215BF", 724, 1428807687, "708543", 1428807687, "708543", "{\n}", "2015-04-11T00:00:00", "01 12 32 42 58 12", "2" ] -, [ 726, "02CAC888-050D-48A5-868C-B37CC88EEC42", 726, 1429153308, "708543", 1429153308, "708543", "{\n}", "2015-04-15T00:00:00", "01 16 21 29 40 30", "3" ] -, [ 728, "81E5718B-6F5D-49A2-B3A6-E8C5A8C49458", 728, 1429412486, "708543", 1429412486, "708543", "{\n}", "2015-04-18T00:00:00", "13 22 23 29 31 17", "3" ] -, [ 730, "4ED36D51-0CD1-403B-BF6F-474E76D12866", 730, 1429758092, "708543", 1429758092, "708543", "{\n}", "2015-04-22T00:00:00", "10 14 25 39 53 18", "2" ] -, [ 732, "1E602E88-5A04-4E97-81F4-1AC8E0F65593", 732, 1430017289, "708543", 1430017289, "708543", "{\n}", "2015-04-25T00:00:00", "21 33 35 38 45 12", "2" ] -, [ 734, "7E163D25-1D6C-41EC-98F3-FCB6323BBE21", 734, 1430362890, "708543", 1430362890, "708543", "{\n}", "2015-04-29T00:00:00", "01 26 34 38 51 06", "3" ] -, [ 736, "6AE4172D-2045-4718-875A-B5FF15FF15D7", 736, 1430622097, "708543", 1430622097, "708543", "{\n}", "2015-05-02T00:00:00", "02 06 11 30 31 33", "3" ] -, [ 738, "C36A8A54-82C5-48FE-AA7E-570DB8ED39AD", 738, 1430967717, "708543", 1430967717, "708543", "{\n}", "2015-05-06T00:00:00", "23 24 27 39 41 30", "5" ] -, [ 740, "3CF64B67-5986-4A6E-86D2-3D3A75006C2D", 740, 1431226891, "708543", 1431226891, "708543", "{\n}", "2015-05-09T00:00:00", "04 15 17 35 58 17", "3" ] -, [ 742, "21A93C94-A9CF-4C66-8752-DB70A3C877E9", 742, 1431572489, "708543", 1431572489, "708543", "{\n}", "2015-05-13T00:00:00", "01 25 29 31 47 07", "3" ] -, [ 744, "852204B9-3070-4BB2-93D6-89525B2A6A88", 744, 1431831689, "708543", 1431831689, "708543", "{\n}", "2015-05-16T00:00:00", "24 29 38 48 52 32", "2" ] -, [ 746, "C58E93C9-ED63-4A6B-8E70-DB0E572779DF", 746, 1432177299, "708543", 1432177299, "708543", "{\n}", "2015-05-20T00:00:00", "01 12 28 35 44 25", "3" ] -, [ 748, "4BA1309D-2E3A-47C7-BCB0-D5E8AACF8A23", 748, 1432436488, "708543", 1432436488, "708543", "{\n}", "2015-05-23T00:00:00", "09 15 17 31 43 16", "4" ] -, [ 750, "1BFBA543-A31E-4A61-9EE2-842B252E1A49", 750, 1432782091, "708543", 1432782091, "708543", "{\n}", "2015-05-27T00:00:00", "08 15 34 53 59 23", "2" ] -, [ 752, "A176D8B7-2B06-4638-B917-DFF229554FC5", 752, 1433041293, "708543", 1433041293, "708543", "{\n}", "2015-05-30T00:00:00", "08 09 25 56 57 22", "2" ] -, [ 754, "9B16EFF0-1C1A-43E1-89D0-0A138591BF89", 754, 1433386892, "708543", 1433386892, "708543", "{\n}", "2015-06-03T00:00:00", "06 08 13 37 40 11", "2" ] -, [ 756, "D2B7FDF6-0C3C-4BA6-8AE3-3EDD2D3554B9", 756, 1433646129, "708543", 1433646129, "708543", "{\n}", "2015-06-06T00:00:00", "08 13 18 27 43 15", "4" ] -, [ 758, "7535E4D2-583F-4096-8C62-BF639B1F0C4F", 758, 1433991688, "708543", 1433991688, "708543", "{\n}", "2015-06-10T00:00:00", "31 32 48 49 53 25", "2" ] -, [ 760, "87226083-EDDC-40D5-AC6E-2E17E8F7DAF1", 760, 1434250895, "708543", 1434250895, "708543", "{\n}", "2015-06-13T00:00:00", "29 41 48 52 54 29", "2" ] -, [ 762, "D9A556D7-FAF0-4451-A6D9-8E7ABAAF75F1", 762, 1434596511, "708543", 1434596511, "708543", "{\n}", "2015-06-17T00:00:00", "20 21 22 41 54 07", "3" ] -, [ 764, "0B4B4E43-2914-4252-9B4D-445656DD001E", 764, 1434855712, "708543", 1434855712, "708543", "{\n}", "2015-06-20T00:00:00", "09 10 16 20 57 15", "2" ] -, [ 766, "402F6B05-3B40-4839-B20E-4C86605592EA", 766, 1435201309, "708543", 1435201309, "708543", "{\n}", "2015-06-24T00:00:00", "03 05 10 22 32 07", "4" ] -, [ 768, "85C14851-24B0-4482-8610-DB5318822E47", 768, 1435460508, "708543", 1435460508, "708543", "{\n}", "2015-06-27T00:00:00", "18 28 35 46 49 27", "5" ] -, [ 770, "F917646C-C9E4-4DD0-9705-1AE52C0DBEE2", 770, 1435806142, "708543", 1435806142, "708543", "{\n}", "2015-07-01T00:00:00", "07 24 26 31 41 25", "2" ] -, [ 772, "F39FD4CD-D959-462E-B398-9A813FA9128A", 772, 1436065288, "708543", 1436065288, "708543", "{\n}", "2015-07-04T00:00:00", "03 06 14 18 24 21", "3" ] -, [ 774, "53124F7D-90C3-4B9D-B7BB-A5DD90478C00", 774, 1436410928, "708543", 1436410928, "708543", "{\n}", "2015-07-08T00:00:00", "04 15 25 27 30 18", "3" ] -, [ 776, "3B86E5CC-7CFA-4329-A914-E0BCBA3B017F", 776, 1436670069, "708543", 1436670069, "708543", null, "2015-07-11T00:00:00", "11 39 46 52 54 03", "2" ] -, [ 777, "4D234C5C-F376-4344-BD6D-A5770CD56A1F", 777, 1437015729, "708543", 1437015729, "708543", null, "2015-07-15T00:00:00", "13 16 34 45 50 11", "2" ] -, [ 778, "24EE016C-7F9D-4E0D-AA08-C4AF54E66F11", 778, 1437274885, "708543", 1437274885, "708543", null, "2015-07-18T00:00:00", "06 37 39 45 55 33", "3" ] -, [ 779, "C9C2B6CC-06CB-4F01-9281-7E4A8C43FB8E", 779, 1437620486, "708543", 1437620486, "708543", null, "2015-07-22T00:00:00", "12 31 43 44 57 11", "2" ] -, [ 780, "CC90B341-400A-4806-BBAF-E8E327598BD2", 780, 1437879687, "708543", 1437879687, "708543", null, "2015-07-25T00:00:00", "27 29 34 41 44 02", "3" ] -, [ 781, "E512BA46-7C58-41C7-9DBD-2457E9029D67", 781, 1438225285, "708543", 1438225285, "708543", null, "2015-07-29T00:00:00", "04 22 27 28 52 35", "3" ] -, [ 782, "10064E9F-AD64-429D-84F8-E8D410526A6F", 782, 1438484508, "708543", 1438484508, "708543", null, "2015-08-01T00:00:00", "07 13 24 49 57 15", "3" ] -, [ 783, "C787A37A-573D-4859-87E7-119575F1D112", 783, 1438830107, "708543", 1438830107, "708543", null, "2015-08-05T00:00:00", "09 11 14 16 42 19", "2" ] -, [ 784, "DD6C5E0E-BD8D-4290-AA73-94E40E188200", 784, 1439089330, "708543", 1439089330, "708543", null, "2015-08-08T00:00:00", "09 34 48 52 54 15", "4" ] -, [ 785, "A3D0D844-6B97-4671-87DA-693740D7D8AF", 785, 1439434947, "708543", 1439434947, "708543", null, "2015-08-12T00:00:00", "08 13 29 38 52 28", "2" ] -, [ 786, "3728F12A-F565-4B44-8176-2EEF0D165955", 786, 1439694118, "708543", 1439694118, "708543", null, "2015-08-15T00:00:00", "03 13 17 42 52 24", "4" ] -, [ 787, "298DD735-4622-4189-8EE7-F86F90B5AFCE", 787, 1440039778, "708543", 1440039778, "708543", null, "2015-08-19T00:00:00", "06 08 43 48 50 07", "2" ] -, [ 788, "DA91602B-3A63-4F41-A4E9-2CBF1168AE59", 788, 1440298930, "708543", 1440298930, "708543", null, "2015-08-22T00:00:00", "04 12 14 21 55 07", "4" ] -, [ 789, "2529F7C9-6E07-4C91-B535-DF2BEFDE2D56", 789, 1440644516, "708543", 1440644516, "708543", null, "2015-08-26T00:00:00", "02 22 32 45 56 12", "5" ] -, [ 790, "97C9829B-CEEE-4118-A38B-F7B7F79C31EF", 790, 1440959254, "708543", 1440959254, "708543", null, "2015-08-29T00:00:00", "18 21 25 28 29 16", "2" ] -, [ 791, "3EF82611-85F8-4A8A-8E3A-AA1FD0317354", 791, 1441249319, "708543", 1441249319, "708543", null, "2015-09-02T00:00:00", "17 22 30 46 56 16", "3" ] -, [ 792, "63CC0BFD-0878-4D37-9699-69D02473AA08", 792, 1441508507, "708543", 1441508507, "708543", null, "2015-09-05T00:00:00", "10 16 18 29 45 19", "2" ] -, [ 793, "73962F5A-8EC6-41F9-B0D0-13D7E9F944C4", 793, 1441854115, "708543", 1441854115, "708543", null, "2015-09-09T00:00:00", "44 45 47 50 51 08", "2" ] -, [ 794, "42753DF4-07BE-4C30-A721-B2CF0CCDB7CD", 794, 1442113307, "708543", 1442113307, "708543", null, "2015-09-12T00:00:00", "02 03 13 16 35 27", "3" ] -, [ 795, "56B46B8A-B108-42E4-9A38-24C56DE66CE6", 795, 1442458906, "708543", 1442458906, "708543", null, "2015-09-16T00:00:00", "05 07 24 31 39 07", "3" ] -, [ 796, "CDF7063C-D520-4F5D-861A-96755805F6F4", 796, 1442847785, "708543", 1442847785, "708543", null, "2015-09-19T00:00:00", "12 17 26 43 48 24", "2" ] -, [ 797, "1A936092-357A-40DD-B18B-4747851BBE87", 797, 1443063706, "708543", 1443063706, "708543", null, "2015-09-23T00:00:00", "08 29 41 51 58 05", "2" ] -, [ 798, "A06BDED2-3FEB-40F0-89A4-2CAF9B0A2858", 798, 1443322914, "708543", 1443322914, "708543", null, "2015-09-26T00:00:00", "23 31 42 50 57 05", "3" ] -, [ 799, "DB03982B-C76B-4404-977C-C9EEA3200274", 799, 1443668505, "708543", 1443668505, "708543", null, "2015-09-30T00:00:00", "21 39 40 55 59 17", "3" ] -, [ 800, "FABF6C69-E0F5-4F46-8BE0-3CA7766831D0", 800, 1443927709, "708543", 1443927709, "708543", null, "2015-10-03T00:00:00", "06 26 33 44 46 04", "2" ] -, [ 801, "43CA547E-F47A-453C-B0A9-26381E38A410", 801, 1444273306, "708543", 1444273306, "708543", null, "2015-10-07T00:00:00", "18 30 40 48 52 09", "3" ] -, [ 802, "400812A5-A956-48A9-91B1-F3D056E2F5C9", 802, 1444532485, "708543", 1444532485, "708543", null, "2015-10-10T00:00:00", "12 27 29 43 68 01", "2" ] -, [ 803, "7ABCEB8C-820F-4379-ADFA-0D590640A30C", 803, 1444878105, "708543", 1444878105, "708543", null, "2015-10-14T00:00:00", "15 20 29 31 40 01", "2" ] -, [ 804, "8B64AF93-027A-4027-A217-5D9DB0ED22AB", 804, 1445137286, "708543", 1445137286, "708543", null, "2015-10-17T00:00:00", "48 49 57 62 69 19", "3" ] -, [ 805, "465C206D-BEB3-4F5C-AF45-B7C60F736D1E", 805, 1445482905, "708543", 1445482905, "708543", null, "2015-10-21T00:00:00", "30 32 42 56 57 11", "4" ] -, [ 806, "0ECE9623-21D9-4E2B-B9F9-D67A3C284E73", 806, 1445742085, "708543", 1445742085, "708543", null, "2015-10-24T00:00:00", "20 31 56 60 64 02", "3" ] -, [ 807, "C22995CB-CBF3-4958-B80C-F9B1F8F9B9C5", 807, 1446087727, "708543", 1446087727, "708543", null, "2015-10-28T00:00:00", "04 54 56 62 63 10", "2" ] -, [ 808, "9DB950E1-1439-4B85-91F3-2D73EBECD6D4", 808, 1446346927, "708543", 1446346927, "708543", null, "2015-10-31T00:00:00", "09 20 25 47 68 07", "2" ] -, [ 809, "2C693FFD-694C-4DF3-AA8E-73C92ACD38AF", 809, 1446692509, "708543", 1446692509, "708543", null, "2015-11-04T00:00:00", "02 12 17 20 65 17", "4" ] -, [ 810, "D655D04B-E21B-4342-BD5D-C027CA362005", 810, 1446951708, "708543", 1446951708, "708543", null, "2015-11-07T00:00:00", "07 16 25 50 53 15", "2" ] -, [ 811, "7ECA2F66-0B64-493A-9FED-BC107E02287C", 811, 1447297309, "708543", 1447297309, "708543", null, "2015-11-11T00:00:00", "04 26 32 55 64 18", "3" ] -, [ 812, "1D579B1E-10CC-407E-B78A-9C5569D7A2F8", 812, 1447556507, "708543", 1447556507, "708543", null, "2015-11-14T00:00:00", "14 22 37 45 66 05", "3" ] -, [ 813, "5D32E728-9113-4C09-A8CD-BDAC99661DFD", 813, 1447902130, "708543", 1447902130, "708543", null, "2015-11-18T00:00:00", "17 40 41 46 69 06", "2" ] -, [ 814, "FCB4536B-1006-4F05-BC8D-AAFB9DF95A93", 814, 1448161306, "708543", 1448161306, "708543", null, "2015-11-21T00:00:00", "37 47 50 52 57 21", "3" ] -, [ 815, "21E5D4E6-B471-4928-9385-4CE1ECF18792", 815, 1448506906, "708543", 1448506906, "708543", null, "2015-11-25T00:00:00", "16 29 53 58 69 21", "2" ] -, [ 816, "B18D454A-B143-47CE-A4E8-EA78D6778190", 816, 1448766107, "708543", 1448766107, "708543", null, "2015-11-28T00:00:00", "02 06 47 66 67 02", "3" ] -, [ 817, "5F02EEC4-4E7F-49AD-A4AA-9BB594D1A47F", 817, 1449111727, "708543", 1449111727, "708543", null, "2015-12-02T00:00:00", "14 18 19 32 64 09", "2" ] -, [ 818, "FA5ECE8D-2868-4AA2-AE84-8272D4C1C3D9", 818, 1449370908, "708543", 1449370908, "708543", null, "2015-12-05T00:00:00", "13 27 33 47 68 13", "2" ] -, [ 819, "6655127F-8D2F-493B-8BE8-8A3D3073C305", 819, 1449716510, "708543", 1449716510, "708543", null, "2015-12-09T00:00:00", "07 10 16 46 56 01", "2" ] -, [ 820, "0B0D036D-AAA7-4012-98DA-45227548BADF", 820, 1449975728, "708543", 1449975728, "708543", null, "2015-12-12T00:00:00", "02 14 19 30 62 22", "2" ] -, [ 821, "DFA266CA-6A2B-4D42-8D07-283712CE541B", 821, 1450321306, "708543", 1450321306, "708543", null, "2015-12-16T00:00:00", "09 10 32 42 55 06", "2" ] -, [ 822, "D0D8AE46-E6E2-40BF-8C54-8E58523CC68A", 822, 1450580489, "708543", 1450580489, "708543", null, "2015-12-19T00:00:00", "28 30 41 59 68 10", "2" ] -, [ 823, "B473C73C-19F4-4C65-82A6-0E614998234A", 823, 1450926106, "708543", 1450926106, "708543", null, "2015-12-23T00:00:00", "16 38 55 63 67 25", "4" ] -, [ 824, "0525C88E-D2C8-46A4-8408-BA8E786DA09D", 824, 1451185308, "708543", 1451185308, "708543", null, "2015-12-26T00:00:00", "27 40 44 59 65 20", "2" ] -, [ 825, "C6064586-54E3-4309-8B9B-446C6041CB02", 825, 1451530913, "708543", 1451530913, "708543", null, "2015-12-30T00:00:00", "12 36 38 54 61 22", "3" ] -, [ 826, "F961863C-78F0-401C-9743-1D3791C3490A", 826, 1451790150, "708543", 1451790150, "708543", null, "2016-01-02T00:00:00", "05 06 15 29 42 10", "2" ] -, [ 827, "9D501501-D06D-46B2-9CAD-211B2F995F7A", 827, 1452135747, "708543", 1452135747, "708543", null, "2016-01-06T00:00:00", "02 11 47 62 63 17", "3" ] -, [ 828, "F5DBEFA5-54A6-4B9A-B2FB-267CD56F9835", 828, 1452394927, "708543", 1452394927, "708543", null, "2016-01-09T00:00:00", "16 19 32 34 57 13", "3" ] -, [ 829, "FDF34E6A-BA25-4D92-9DB7-7985BA3DCC2D", 829, 1452740568, "708543", 1452740568, "708543", null, "2016-01-13T00:00:00", "04 08 19 27 34 10", "2" ] -, [ 830, "7EE2F9FB-7673-4DDE-AB72-3651B3AF0444", 830, 1453042908, "708543", 1453042908, "708543", null, "2016-01-16T00:00:00", "03 51 52 61 64 06", "2" ] -, [ 831, "FACC0343-646E-4CA2-8974-C6A298077671", 831, 1453345367, "708543", 1453345367, "708543", null, "2016-01-20T00:00:00", "05 39 44 47 69 24", "5" ] -, [ 832, "F93CCC4F-D69B-4AAB-91EB-9D7446F7A2A0", 832, 1453604572, "708543", 1453604572, "708543", null, "2016-01-23T00:00:00", "22 32 34 40 69 19", "4" ] -, [ 833, "21149184-5031-4CDD-A832-1D34A2C7B623", 833, 1453950088, "708543", 1453950088, "708543", null, "2016-01-27T00:00:00", "03 12 40 52 67 21", "2" ] -, [ 834, "CEA18644-71EA-460A-B8E4-A93CF3581107", 834, 1454209328, "708543", 1454209328, "708543", null, "2016-01-30T00:00:00", "05 12 16 31 43 18", "4" ] -, [ 835, "8D0A23AA-4646-44B2-9A9E-4C25B15DB9E2", 835, 1454554910, "708543", 1454554910, "708543", null, "2016-02-03T00:00:00", "26 28 31 60 67 23", "3" ] -, [ 836, "A1E03B5F-A887-48BA-94AF-8BA6F270AA8A", 836, 1454814130, "708543", 1454814130, "708543", null, "2016-02-06T00:00:00", "04 13 31 36 52 08", "3" ] -, [ 837, "41D48664-EBDB-4E7E-8FAC-CD8F09739F73", 837, 1455159687, "708543", 1455159687, "708543", null, "2016-02-10T00:00:00", "02 03 40 50 62 05", "2" ] -, [ 838, "7AEB4B66-7747-46CC-9BEA-F25ACAE6C3C9", 838, 1455418987, "708543", 1455418987, "708543", null, "2016-02-13T00:00:00", "07 15 18 19 36 20", "2" ] -, [ 839, "6B8BE743-F22C-4A50-B2B5-380FD1D2F8EE", 839, 1455764517, "708543", 1455764517, "708543", null, "2016-02-17T00:00:00", "07 17 27 29 40 25", "2" ] -, [ 840, "C2CCCF1C-3F1A-405F-B70F-4C6C86655FEA", 840, 1456023770, "708543", 1456023770, "708543", null, "2016-02-20T00:00:00", "11 12 15 16 54 25", "5" ] -, [ 841, "94B1F83F-79A0-41B3-8482-9FC6C233E98B", 841, 1456369306, "708543", 1456369306, "708543", null, "2016-02-24T00:00:00", "21 31 64 65 67 05", "3" ] -, [ 842, "026D1654-83BA-4BF3-9C2E-66FD17B5357F", 842, 1456628570, "708543", 1456628570, "708543", null, "2016-02-27T00:00:00", "10 11 21 22 53 18", "3" ] -, [ 843, "32A2DD81-B860-4FCB-84AA-2CC4C5A2E4C6", 843, 1456974110, "708543", 1456974110, "708543", null, "2016-03-02T00:00:00", "12 13 44 52 62 06", "2" ] -, [ 844, "59C142D9-3DAB-4426-9AE6-CE628E5A454E", 844, 1457233373, "708543", 1457233373, "708543", null, "2016-03-05T00:00:00", "03 27 34 59 69 19", "2" ] -, [ 845, "3F050CD8-2598-4E91-8EB0-6672BE274C30", 845, 1457578898, "708543", 1457578898, "708543", null, "2016-03-09T00:00:00", "14 23 32 34 68 03", "3" ] -, [ 846, "D6246154-1A79-49D1-8AE3-D588EEF93CAD", 846, 1457838158, "708543", 1457838158, "708543", null, "2016-03-12T00:00:00", "11 28 50 57 62 23", "2" ] -, [ 847, "B4ADA05D-A321-4010-A151-3E00A3EC9E27", 847, 1458183687, "708543", 1458183687, "708543", null, "2016-03-16T00:00:00", "10 12 13 46 50 21", "3" ] -, [ 848, "C44AC758-6188-4C66-889E-0C11B69B3F5A", 848, 1458442886, "708543", 1458442886, "708543", null, "2016-03-19T00:00:00", "11 23 43 54 60 03", "3" ] -, [ 849, "F76B28BE-B8CC-4333-B8C2-8038FA04A5D7", 849, 1458788506, "708543", 1458788506, "708543", null, "2016-03-23T00:00:00", "05 08 15 22 49 25", "3" ] -, [ 850, "DAC76276-F82B-4521-8B22-2D77AE8B65DD", 850, 1459047769, "708543", 1459047769, "708543", null, "2016-03-26T00:00:00", "11 23 42 52 68 06", "3" ] -, [ 851, "AFA36766-0E68-4370-AF47-008B6ED8071E", 851, 1459393289, "708543", 1459393289, "708543", null, "2016-03-30T00:00:00", "24 44 53 55 63 19", "2" ] -, [ 852, "0638F190-3A0F-43C2-8688-ED2D07E85386", 852, 1459652500, "708543", 1459652500, "708543", null, "2016-04-02T00:00:00", "09 28 30 40 61 03", "2" ] -, [ 853, "538BA672-7387-4BB6-B077-DECC618EE0DA", 853, 1459998107, "708543", 1459998107, "708543", null, "2016-04-06T00:00:00", "04 28 49 60 65 25", "2" ] -, [ 854, "D292DAB1-F656-478B-9776-4307D1D2E9F6", 854, 1460257309, "708543", 1460257309, "708543", null, "2016-04-09T00:00:00", "14 22 23 41 61 09", "3" ] -, [ 855, "806C3A3C-F727-443D-AA51-A0B6FD55392C", 855, 1460602907, "708543", 1460602907, "708543", null, "2016-04-13T00:00:00", "30 33 35 38 64 22", "3" ] -, [ 856, "6C513E67-72D5-49DC-9339-8855AE411D23", 856, 1460862109, "708543", 1460862109, "708543", null, "2016-04-16T00:00:00", "03 18 25 32 51 03", "2" ] -, [ 857, "3CC889C1-BC6D-4AB3-9703-EDB0B0993D25", 857, 1461207686, "708543", 1461207686, "708543", null, "2016-04-20T00:00:00", "12 25 30 52 62 08", "3" ] -, [ 858, "66E2C834-3EE5-417A-9333-8CD4C4BDDC0D", 858, 1461466948, "708543", 1461466948, "708543", null, "2016-04-23T00:00:00", "19 35 46 59 62 13", "5" ] -, [ 859, "FB0E502B-4C20-40F1-9191-02932FFEFC20", 859, 1461812486, "708543", 1461812486, "708543", null, "2016-04-27T00:00:00", "02 25 33 39 64 17", "2" ] -, [ 860, "EFC02B54-5324-4CEA-A33B-F13F2792B866", 860, 1462071708, "708543", 1462071708, "708543", null, "2016-04-30T00:00:00", "03 12 16 32 34 14", "3" ] -, [ 861, "B343B51F-4E61-4B9A-8D32-4A6872B2B45D", 861, 1462417308, "708543", 1462417308, "708543", null, "2016-05-04T00:00:00", "30 47 57 66 69 03", "3" ] -, [ 862, "27B6967E-B5D2-46D0-B7BC-DA91059FFCDB", 862, 1462676507, "708543", 1462676507, "708543", null, "2016-05-07T00:00:00", "05 25 26 44 66 09", "2" ] -, [ 863, "A4B7173B-5E0C-4E9D-BCA4-618A323FB42D", 863, 1463022106, "708543", 1463022106, "708543", null, "2016-05-11T00:00:00", "20 32 52 66 69 23", "3" ] -, [ 864, "CE5AB6A5-25F9-4388-9467-BD0445459BC4", 864, 1463281288, "708543", 1463281288, "708543", null, "2016-05-14T00:00:00", "13 27 47 64 65 09", "3" ] -, [ 865, "3F367781-B30A-47AE-B947-B0D2AE4FFB10", 865, 1463626906, "708543", 1463626906, "708543", null, "2016-05-18T00:00:00", "23 25 39 54 67 11", "3" ] -, [ 866, "2B6846C3-B065-4EEB-B321-68C75294F7C9", 866, 1463886110, "708543", 1463886110, "708543", null, "2016-05-21T00:00:00", "05 07 09 23 32 26", "4" ] -, [ 867, "0774E3AA-3772-43E0-B98B-05EAB69847A1", 867, 1464231708, "708543", 1464231708, "708543", null, "2016-05-25T00:00:00", "11 24 41 59 64 15", "3" ] -, [ 868, "3796D800-4922-4280-8B88-E85ED906B4DF", 868, 1464490907, "708543", 1464490907, "708543", null, "2016-05-28T00:00:00", "06 33 34 58 59 12", "2" ] -, [ 869, "EEB99A68-457E-4AFF-A13F-427EEE2D4EB1", 869, 1464836507, "708543", 1464836507, "708543", null, "2016-06-01T00:00:00", "23 30 33 40 69 12", "5" ] -, [ 870, "74D58C48-7E89-4118-BD99-6DBD5043656D", 870, 1465095690, "708543", 1465095690, "708543", null, "2016-06-04T00:00:00", "16 20 22 43 64 17", "2" ] -, [ 871, "0E17BFD1-5263-4495-9CFD-817A48C251A4", 871, 1465441306, "708543", 1465441306, "708543", null, "2016-06-08T00:00:00", "12 25 37 60 69 20", "3" ] -, [ 872, "5324C432-0CA5-46C6-8980-F6D6516D07A3", 872, 1465700507, "708543", 1465700507, "708543", null, "2016-06-11T00:00:00", "20 27 36 41 58 07", "2" ] -, [ 873, "424D6940-1854-4E17-A840-FB6E3EFB0BC7", 873, 1466046088, "708543", 1466046088, "708543", null, "2016-06-15T00:00:00", "04 22 24 31 33 10", "2" ] -, [ 874, "801FF99A-39BA-44A5-B34F-7A40CCC981F4", 874, 1466305308, "708543", 1466305308, "708543", null, "2016-06-18T00:00:00", "02 23 41 53 63 11", "2" ] -, [ 875, "32B8607F-979E-4C0E-846D-5074E00DFEAB", 875, 1466650887, "708543", 1466650887, "708543", null, "2016-06-22T00:00:00", "14 40 42 43 52 17", "3" ] -, [ 876, "FDFEF46C-8E7E-4BF8-B000-C0D8C5749D4E", 876, 1466910089, "708543", 1466910089, "708543", null, "2016-06-25T00:00:00", "03 27 36 56 69 25", "2" ] -, [ 877, "A1087993-4142-44E5-8FF3-F8A77DEFFB06", 877, 1467255707, "708543", 1467255707, "708543", null, "2016-06-29T00:00:00", "23 29 37 60 64 06", "2" ] -, [ 878, "4BF9DA07-A878-4846-A461-B8B46ABD9792", 878, 1467514914, "708543", 1467514914, "708543", null, "2016-07-02T00:00:00", "10 34 39 59 63 04", "2" ] -, [ 879, "81D9BD05-0115-4833-A484-F5F5764AE5B1", 879, 1467860567, "708543", 1467860567, "708543", null, "2016-07-06T00:00:00", "02 24 31 57 66 18", "3" ] -, [ 880, "1B7693CA-B277-4943-AC44-DBDDFE46E05B", 880, 1468119706, "708543", 1468119706, "708543", null, "2016-07-09T00:00:00", "10 28 32 61 64 12", "3" ] -, [ 881, "82FEF08C-D90C-4582-B8C9-9703FEB75A77", 881, 1468465309, "708543", 1468465309, "708543", null, "2016-07-13T00:00:00", "03 15 29 54 57 10", "3" ] -, [ 882, "DEF18268-C8D4-428E-A79B-A0E0AF3CBD4B", 882, 1468724507, "708543", 1468724507, "708543", null, "2016-07-16T00:00:00", "11 17 40 50 62 26", "2" ] -, [ 883, "45A8B2F3-217E-4D2B-90A3-AE8D1B4C6174", 883, 1469070107, "708543", 1469070107, "708543", null, "2016-07-20T00:00:00", "06 25 35 58 66 05", "2" ] -, [ 884, "B58A1782-C764-46F1-B9B9-3BFE1D6B4E52", 884, 1469329307, "708543", 1469329307, "708543", null, "2016-07-23T00:00:00", "05 07 23 35 39 11", "2" ] -, [ 885, "7D4F8200-DF95-4382-8748-33E050967A9D", 885, 1469674886, "708543", 1469674886, "708543", null, "2016-07-27T00:00:00", "10 47 50 65 68 24", "2" ] -, [ 886, "79F3C5B3-FD8F-49A9-A796-60542668C200", 886, 1469934107, "708543", 1469934107, "708543", null, "2016-07-30T00:00:00", "11 17 21 23 32 05", "2" ] -, [ 887, "A5A0BD2D-64AB-4811-82AB-D61EEF1AF7B1", 887, 1470279686, "708543", 1470279686, "708543", null, "2016-08-03T00:00:00", "09 11 27 66 67 02", "3" ] -, [ 888, "BD4C1208-94E5-4D63-9D5A-586C1A3822B7", 888, 1470538909, "708543", 1470538909, "708543", null, "2016-08-06T00:00:00", "20 33 36 47 52 12", "3" ] -, [ 889, "A9CAA420-DE01-412C-A756-F1A663F4AA29", 889, 1470884507, "708543", 1470884507, "708543", null, "2016-08-10T00:00:00", "23 56 61 64 67 12", "5" ] -, [ 890, "8E27E501-E185-4712-BCDC-F3FB1230EDF8", 890, 1471143709, "708543", 1471143709, "708543", null, "2016-08-13T00:00:00", "38 44 60 64 69 06", "2" ] -, [ 891, "BD66F02B-64EE-4CC2-BD17-556CA0E719C7", 891, 1471489307, "708543", 1471489307, "708543", null, "2016-08-17T00:00:00", "33 44 49 50 52 08", "3" ] -, [ 892, "A479CB83-1789-467D-B719-50667324A737", 892, 1471773690, "708543", 1471773690, "708543", null, "2016-08-20T00:00:00", "03 06 21 60 68 24", "2" ] -, [ 893, "9839668D-4E14-477E-9048-78609B14F262", 893, 1472119267, "708543", 1472119267, "708543", null, "2016-08-24T00:00:00", "09 11 25 64 65 16", "3" ] -, [ 894, "7BE65F8C-50FB-4760-B95B-5AA9C7D7BDEB", 894, 1472378508, "708543", 1472378508, "708543", null, "2016-08-27T00:00:00", "04 32 48 49 63 20", "2" ] -, [ 895, "64CEEEC0-29D4-4F27-BAB1-A71CA938691D", 895, 1472724066, "708543", 1472724066, "708543", null, "2016-08-31T00:00:00", "05 10 24 56 61 12", "2" ] -, [ 896, "29B26B2B-D58E-44AD-A903-DBEBE05E2B0B", 896, 1472983266, "708543", 1472983266, "708543", null, "2016-09-03T00:00:00", "07 39 50 59 67 25", "3" ] -, [ 897, "D37CF53F-C59C-41D3-9C80-6FF81CE73730", 897, 1473363020, "708543", 1473363020, "708543", null, "2016-09-07T00:00:00", "22 23 29 33 55 21", "2" ] -, [ 898, "22706198-5E98-4646-987C-26275EA758CA", 898, 1473588064, "708543", 1473588064, "708543", null, "2016-09-10T00:00:00", "03 17 49 55 68 08", "2" ] -, [ 899, "BC2D6956-1D23-4DB9-9286-BB5EEAEF83A4", 899, 1473933706, "708543", 1473933706, "708543", null, "2016-09-14T00:00:00", "10 11 23 28 31 14", "2" ] -, [ 900, "3CAD5A54-A6F9-43B5-A212-1D9B57C576B0", 900, 1474192866, "708543", 1474192866, "708543", null, "2016-09-17T00:00:00", "09 19 51 55 62 14", "4" ] -, [ 901, "6BAC9382-FE49-4853-80FB-52C1A70CD422", 901, 1474538472, "708543", 1474538472, "708543", null, "2016-09-21T00:00:00", "01 28 63 67 69 17", "4" ] -, [ 902, "ACB5DEF7-15F4-45FD-B2E9-242C8B909E9D", 902, 1474797668, "708543", 1474797668, "708543", null, "2016-09-24T00:00:00", "07 15 20 29 41 22", "2" ] -, [ 903, "8FD3E76A-DEED-458A-A9CA-D6CAA1AA7A6B", 903, 1475143268, "708543", 1475143268, "708543", null, "2016-09-28T00:00:00", "30 38 52 53 62 01", "3" ] -, [ 904, "BB31C897-1552-494E-B27E-BEC1B7D72C29", 904, 1475402464, "708543", 1475402464, "708543", null, "2016-10-01T00:00:00", "02 12 50 61 64 01", "2" ] -, [ 905, "DB9A260F-8EDD-4D7E-B6F4-D24AD0FF3A4C", 905, 1475748063, "708543", 1475748063, "708543", null, "2016-10-05T00:00:00", "08 18 27 29 60 15", "2" ] -, [ 906, "7CC48100-C232-464E-9A23-034B8F0B4147", 906, 1476007263, "708543", 1476007263, "708543", null, "2016-10-08T00:00:00", "03 54 61 64 68 09", "2" ] -, [ 907, "D88F9F9B-B5D0-464F-BF4A-B08BABF3D7B3", 907, 1476352884, "708543", 1476352884, "708543", null, "2016-10-12T00:00:00", "16 30 34 37 44 16", "2" ] -, [ 908, "963109BF-96C7-4BAC-8F60-B825FAE4A346", 908, 1476612067, "708543", 1476612067, "708543", null, "2016-10-15T00:00:00", "23 49 57 64 67 20", "2" ] -, [ 909, "6A69340B-A601-40C8-99AB-D4E8E8742B08", 909, 1476957664, "708543", 1476957664, "708543", null, "2016-10-19T00:00:00", "10 16 38 43 63 23", "2" ] -, [ 910, "C336DBED-7B5B-41B0-8662-E6E71F97730E", 910, 1477216866, "708543", 1477216866, "708543", null, "2016-10-22T00:00:00", "01 28 33 55 56 22", "2" ] -, [ 911, "5F475ADD-6DC7-4259-B794-980960C64696", 911, 1477562508, "708543", 1477562508, "708543", null, "2016-10-26T00:00:00", "02 03 16 48 56 24", "2" ] -, [ 912, "1913132B-72F1-4BBB-BFC5-B6F920804656", 912, 1477821707, "708543", 1477821707, "708543", null, "2016-10-29T00:00:00", "19 20 21 42 48 23", "3" ] -, [ 913, "E3F60567-F814-45BC-BD16-548B5B430BED", 913, 1478167263, "708543", 1478167263, "708543", null, "2016-11-02T00:00:00", "13 18 37 54 61 05", "2" ] -, [ 914, "DA422B46-9D32-4BA3-8400-68B1AD0215E9", 914, 1478430063, "708543", 1478430063, "708543", null, "2016-11-05T00:00:00", "21 31 50 51 69 08", "3" ] -, [ 915, "268D2F3C-7C91-462C-8ECC-6E8E3DF20A22", 915, 1478775664, "708543", 1478775664, "708543", null, "2016-11-09T00:00:00", "01 25 28 31 54 02", "2" ] -, [ 916, "98AC28EB-755D-42C9-A445-3F6285AD7196", 916, 1479034863, "708543", 1479034863, "708543", null, "2016-11-12T00:00:00", "08 17 20 27 52 24", "2" ] -, [ 917, "7B229FE5-AC63-4D4A-91A6-0A7CB86DD532", 917, 1479380463, "708543", 1479380463, "708543", null, "2016-11-16T00:00:00", "28 41 61 63 65 07", "2" ] -, [ 918, "431C3CF5-B68F-4457-889F-49B20F9CF1C4", 918, 1479639663, "708543", 1479639663, "708543", null, "2016-11-19T00:00:00", "16 24 28 43 61 21", "2" ] -, [ 919, "E0432E50-E19E-4DC3-9A18-36806C7A88C1", 919, 1479985514, "708543", 1479985514, "708543", null, "2016-11-23T00:00:00", "07 32 41 47 61 03", "2" ] -, [ 920, "B6B9C15A-C30F-4CC0-B1BD-CA3920340503", 920, 1480244703, "708543", 1480244703, "708543", null, "2016-11-26T00:00:00", "17 19 21 37 44 16", "2" ] -, [ 921, "D40A1619-0832-4A6E-9EAF-3844B23092F0", 921, 1480590068, "708543", 1480590068, "708543", null, "2016-11-30T00:00:00", "03 14 18 25 45 07", "2" ] -, [ 922, "CBE0E3C4-72D7-446F-B787-B9A04E347C3C", 922, 1480849263, "708543", 1480849263, "708543", null, "2016-12-03T00:00:00", "08 10 26 27 33 22", "2" ] -, [ 923, "C75F0236-8827-4F14-ADA7-7061AFE4AA04", 923, 1481194864, "708543", 1481194864, "708543", null, "2016-12-07T00:00:00", "41 48 49 53 64 20", "2" ] -, [ 924, "B9908F6E-3EA8-4093-8210-E306D05F1BD2", 924, 1481583706, "708543", 1481583706, "708543", null, "2016-12-10T00:00:00", "12 21 32 44 66 15", "2" ] -, [ 925, "542E365D-8B02-4B55-AF96-8592595E12BD", 925, 1481799665, "708543", 1481799665, "708543", null, "2016-12-14T00:00:00", "18 26 37 39 66 15", "3" ] -, [ 926, "C7997154-C315-455F-AACB-B172F622C6C4", 926, 1482058866, "708543", 1482058866, "708543", null, "2016-12-17T00:00:00", "01 08 16 40 48 10", "2" ] -, [ 927, "30F782F6-E623-453A-BB19-1BF9A649CDD0", 927, 1482404464, "708543", 1482404464, "708543", null, "2016-12-21T00:00:00", "25 33 40 54 68 03", "5" ] -, [ 928, "1BCFE588-BF10-4E9E-8B10-A1508D2A3E38", 928, 1482663674, "708543", 1482663674, "708543", null, "2016-12-24T00:00:00", "28 38 42 51 52 21", "2" ] -, [ 929, "7DC520AF-2E56-4939-94EB-B17EA2DEF8B9", 929, 1483009263, "708543", 1483009263, "708543", null, "2016-12-28T00:00:00", "16 23 30 44 58 04", "2" ] -, [ 930, "C3C90ACB-7ADE-46A9-80C2-5A06431C7568", 930, 1483268548, "708543", 1483268548, "708543", null, "2016-12-31T00:00:00", "01 03 28 57 67 09", "2" ] -, [ 931, "ABE7162C-2AB8-4CF1-B7DD-00D473BC7960", 931, 1483614084, "708543", 1483614084, "708543", null, "2017-01-04T00:00:00", "16 17 29 41 42 04", "3" ] -, [ 932, "2D90D0BC-7841-4342-87DE-8CC03B2262BD", 932, 1483873291, "708543", 1483873291, "708543", null, "2017-01-07T00:00:00", "03 12 24 37 63 10", "2" ] -, [ 933, "15E71373-4AA1-4CF4-AC87-5DA454A0CAC6", 933, 1484218864, "708543", 1484218864, "708543", null, "2017-01-11T00:00:00", "01 03 13 16 43 24", "2" ] -, [ 934, "49050BC6-0AF3-421D-8F0E-D1F98D18B740", 934, 1484478065, "708543", 1484478065, "708543", null, "2017-01-14T00:00:00", "23 55 59 64 69 13", "5" ] -, [ 935, "4CF6D807-30BD-4EFE-9C6C-1858F45CCB7C", 935, 1484823665, "708543", 1484823665, "708543", null, "2017-01-18T00:00:00", "09 40 41 53 58 12", "2" ] -, [ 936, "557F2798-865C-4016-99BC-C5B9EC0E528C", 936, 1485342103, "708543", 1485342103, "708543", null, "2017-01-21T00:00:00", "23 25 45 52 67 02", "2" ] -, [ 937, "8FF07805-7014-4F6C-91D3-8240564F1F00", 937, 1485428466, "708543", 1485428466, "708543", null, "2017-01-25T00:00:00", "18 28 62 66 68 22", "2" ] -, [ 938, "B68D2427-E10F-472C-96BA-71FD05A3823C", 938, 1485687664, "708543", 1485687664, "708543", null, "2017-01-28T00:00:00", "12 20 39 49 69 17", "2" ] -, [ 939, "5E2A695D-EBAD-494B-8EDC-E97501635708", 939, 1486033265, "708543", 1486033265, "708543", null, "2017-02-01T00:00:00", "09 43 57 60 64 10", "2" ] -, [ 940, "71AF5B59-A1DF-4E4C-88D6-88E85D019C7E", 940, 1486292464, "708543", 1486292464, "708543", null, "2017-02-04T00:00:00", "06 13 16 17 52 25", "3" ] -, [ 941, "BB1F871B-84F6-4A98-9DFA-C09389B4AC6D", 941, 1486638064, "708543", 1486638064, "708543", null, "2017-02-08T00:00:00", "14 20 42 49 66 05", "2" ] -, [ 942, "124D9420-F9FB-4E51-8302-CF6997D70053", 942, 1486897266, "708543", 1486897266, "708543", null, "2017-02-11T00:00:00", "05 09 17 37 64 02", "2" ] -, [ 943, "34C29F3D-DC81-4AD4-9942-E65828561FA9", 943, 1487242864, "708543", 1487242864, "708543", null, "2017-02-15T00:00:00", "05 28 33 38 42 19", "2" ] -, [ 944, "BB3B4322-B5BA-4647-9877-9F6D4C59D91D", 944, 1487502064, "708543", 1487502064, "708543", null, "2017-02-18T00:00:00", "03 07 09 31 33 20", "3" ] -, [ 945, "3BE3ADB4-4BC2-4905-8E2B-24AB6C37F11A", 945, 1487847663, "708543", 1487847663, "708543", null, "2017-02-22T00:00:00", "10 13 28 52 61 02", "2" ] -, [ 946, "136928E1-7518-42CE-B39B-8B7ED5B0D8DD", 946, 1488106865, "708543", 1488106865, "708543", null, "2017-02-25T00:00:00", "06 32 47 62 65 19", "2" ] -, [ 947, "8B2F46F7-EFF2-4A56-B800-54CF2B0360CA", 947, 1488452443, "708543", 1488452443, "708543", null, "2017-03-01T00:00:00", "10 16 40 52 55 17", "10" ] -, [ 948, "E5C90653-DA50-490A-B98C-97A181AE0A02", 948, 1488495663, "708543", 1488495663, "708543", null, "2017-03-01T00:00:00", "10 16 40 52 55 17", "10" ] -, [ 949, "BC492FFD-A7B3-4529-9EDB-4C6F0E5BF617", 949, 1488711665, "708543", 1488711665, "708543", null, "2017-03-04T00:00:00", "02 18 19 22 63 19", "3" ] -, [ 950, "BBD64C58-81CB-43B1-90F5-304A7C892D7B", 950, 1489057264, "708543", 1489057264, "708543", null, "2017-03-08T00:00:00", "23 33 42 46 59 04", "2" ] -, [ 951, "B904A0CA-EA0D-4B49-99CB-5178E6201491", 951, 1489312863, "708543", 1489312863, "708543", null, "2017-03-11T00:00:00", "01 26 41 50 57 11", "2" ] -, [ 952, "81F3E52B-1A76-487E-BBD0-D8711CBD083B", 952, 1489658465, "708543", 1489658465, "708543", null, "2017-03-15T00:00:00", "16 30 41 48 53 16", "3" ] -, [ 953, "E73A1F78-9908-4DCA-9125-D40CE4EC5EAB", 953, 1489917663, "708543", 1489917663, "708543", null, "2017-03-18T00:00:00", "13 25 44 54 67 05", "3" ] -, [ 954, "6122F4BB-2ACA-4F48-86A1-E6A482D02BF9", 954, 1490263262, "708543", 1490263262, "708543", null, "2017-03-22T00:00:00", "02 09 27 29 42 09", "2" ] -, [ 955, "23640056-0969-4331-ACAA-001E96789E90", 955, 1490522463, "708543", 1490522463, "708543", null, "2017-03-25T00:00:00", "18 31 32 45 48 16", "4" ] -, [ 956, "7B9AB081-962E-40DD-9C0F-6C974AE5997D", 956, 1490868063, "708543", 1490868063, "708543", null, "2017-03-29T00:00:00", "08 15 31 36 62 11", "3" ] -, [ 957, "F20FEE86-0911-4C09-A1DB-290609482563", 957, 1491127263, "708543", 1491127263, "708543", null, "2017-04-01T00:00:00", "09 32 36 44 65 01", "3" ] -, [ 958, "AF7C0244-1CBA-4A9C-A238-4D47750567F7", 958, 1491472863, "708543", 1491472863, "708543", null, "2017-04-05T00:00:00", "08 20 46 53 54 13", "2" ] -, [ 959, "256878FD-772B-48D3-B7A4-4FE86DFAC088", 959, 1491732063, "708543", 1491732063, "708543", null, "2017-04-08T00:00:00", "23 36 51 53 60 15", "2" ] -, [ 960, "F114AF8A-05DB-47BA-9B9E-53ABC867CCFE", 960, 1492077663, "708543", 1492077663, "708543", null, "2017-04-12T00:00:00", "08 14 61 63 68 24", "2" ] -, [ 961, "6F58C329-42D3-4512-8117-203CECC2ECDF", 961, 1492336863, "708543", 1492336863, "708543", null, "2017-04-15T00:00:00", "05 22 26 45 61 13", "3" ] -, [ 962, "7473DF48-9E9C-4557-90FE-239C749A5B8B", 962, 1492682463, "708543", 1492682463, "708543", null, "2017-04-19T00:00:00", "01 19 37 40 52 15", "3" ] -, [ 963, "7664B507-4ADA-4AF4-A7E6-8AA8D000F05B", 963, 1492941664, "708543", 1492941664, "708543", null, "2017-04-22T00:00:00", "21 39 41 48 63 06", "3" ] -, [ 964, "4C556EA2-12CB-4C4D-B80E-E635D3413A69", 964, 1493287265, "708543", 1493287265, "708543", null, "2017-04-26T00:00:00", "01 15 18 26 51 26", "4" ] -, [ 965, "B32D3AED-6C68-4330-B70C-2B6859EBB1FB", 965, 1493546465, "708543", 1493546465, "708543", null, "2017-04-29T00:00:00", "22 23 24 45 62 05", "2" ] -, [ 966, "A6F5C3ED-3225-4FAF-8D27-01E7068A50F0", 966, 1493892066, "708543", 1493892066, "708543", null, "2017-05-03T00:00:00", "17 18 49 59 66 09", "2" ] -, [ 967, "BDFF5C57-C2CE-4439-AFA2-3FDC539BF791", 967, 1494151264, "708543", 1494151264, "708543", null, "2017-05-06T00:00:00", "11 21 31 41 59 21", "3" ] -, [ 968, "3E057E13-4199-4445-A7A1-344AAF197C36", 968, 1494496865, "708543", 1494496865, "708543", null, "2017-05-10T00:00:00", "29 31 46 56 62 08", "2" ] -, [ 969, "0C104D21-34FC-42D7-8632-40E67B3522F6", 969, 1494756065, "708543", 1494756065, "708543", null, "2017-05-13T00:00:00", "17 20 32 63 68 19", "5" ] -, [ 970, "7194A14E-F3A2-4FAB-9E38-16E88E8B5A23", 970, 1495101664, "708543", 1495101664, "708543", null, "2017-05-17T00:00:00", "04 11 39 45 48 09", "3" ] -, [ 971, "08FE9220-F04E-42BB-85FC-0D50107BE201", 971, 1495360866, "708543", 1495360866, "708543", null, "2017-05-20T00:00:00", "05 22 45 47 54 03", "2" ] -, [ 972, "6160C9E9-ACE0-44B7-9AAA-B2DDA2C83C45", 972, 1495706464, "708543", 1495706464, "708543", null, "2017-05-24T00:00:00", "28 32 33 38 62 15", "2" ] -, [ 973, "D27C5ED7-46A0-4864-ADF6-E490F3CE4F36", 973, 1495965664, "708543", 1495965664, "708543", null, "2017-05-27T00:00:00", "05 10 28 55 67 09", "3" ] -, [ 974, "C7B5F47C-2EA8-44BB-B04C-B19D4794BBA9", 974, 1496311265, "708543", 1496311265, "708543", null, "2017-05-31T00:00:00", "04 33 39 46 60 06", "2" ] -, [ 975, "F69D8094-D1AB-4E64-873F-046ED5867980", 975, 1496570464, "708543", 1496570464, "708543", null, "2017-06-03T00:00:00", "03 09 21 41 54 25", "4" ] -, [ 976, "A3F85596-082C-4FF9-BF20-3E51FF9A98F9", 976, 1496916064, "708543", 1496916064, "708543", null, "2017-06-07T00:00:00", "05 21 57 66 69 13", "3" ] -, [ 977, "0C90284F-764D-483A-B4E9-AD1C0FEDB6DA", 977, 1497520864, "708543", 1497520864, "708543", null, "2017-06-14T00:00:00", "05 22 43 57 63 24", "2" ] -, [ 978, "8167BC74-6790-4223-A42B-2CC3739EB537", 978, 1497780063, "708543", 1497780063, "708543", null, "2017-06-17T00:00:00", "10 13 32 53 62 21", "2" ] -, [ 979, "73CA9EB8-79D6-40B3-A8FE-8470793B4E4B", 979, 1498125664, "708543", 1498125664, "708543", null, "2017-06-21T00:00:00", "14 46 61 65 68 13", "2" ] -, [ 980, "F77798EC-77A9-4A22-B06B-DB617FA70AAA", 980, 1498384863, "708543", 1498384863, "708543", null, "2017-06-24T00:00:00", "10 22 32 36 58 10", "4" ] -, [ 981, "029B1864-680A-4388-9C25-CD03A2AEFCAC", 981, 1498730464, "708543", 1498730464, "708543", null, "2017-06-28T00:00:00", "29 37 46 53 68 08", "2" ] -, [ 982, "61DB0FF6-A6E6-4A2F-84D8-9DEF8670EB8F", 982, 1498989663, "708543", 1498989663, "708543", null, "2017-07-01T00:00:00", "19 42 45 48 53 16", "3" ] -, [ 983, "1C831F5D-3977-47E0-AB0A-84CBF17D0EAF", 983, 1499335263, "708543", 1499335263, "708543", null, "2017-07-05T00:00:00", "04 09 16 54 68 21", "2" ] -, [ 984, "80CBBECD-4E5A-41A1-A75C-791756039A6F", 984, 1499594464, "708543", 1499594464, "708543", null, "2017-07-08T00:00:00", "08 10 29 40 59 26", "2" ] -, [ 985, "93717B8E-CA86-4447-B74E-095E20FB5C9C", 985, 1499940064, "708543", 1499940064, "708543", null, "2017-07-12T00:00:00", "01 02 18 23 61 09", "2" ] -, [ 986, "B66C4317-9207-433C-A498-BABB79D8D144", 986, 1500199263, "708543", 1500199263, "708543", null, "2017-07-15T00:00:00", "09 40 63 64 66 17", "2" ] -, [ 987, "8724EA9E-C2EE-4F63-8CCD-2A572EBE09BB", 987, 1500544863, "708543", 1500544863, "708543", null, "2017-07-19T00:00:00", "50 51 59 61 63 04", "5" ] -, [ 988, "D19EE0BA-A71F-457E-AD3F-64AC41202A57", 988, 1500804063, "708543", 1500804063, "708543", null, "2017-07-22T00:00:00", "05 32 44 53 60 09", "3" ] -, [ 989, "78BCC11D-0F1F-46B5-A18C-847558335E13", 989, 1501149663, "708543", 1501149663, "708543", null, "2017-07-26T00:00:00", "07 19 21 42 69 12", "2" ] - ] -} \ No newline at end of file + }, + "data": [ + [ + 1, + "473F0579-3060-42E8-95C6-671B43230276", + 1, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-03T00:00:00Z", + "17 22 36 37 52 24", + "2" + ], + [ + 2, + "13ED019C-14C2-48A1-9B40-43AEEF313BCC", + 2, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-06T00:00:00Z", + "14 22 52 54 59 04", + "3" + ], + [ + 3, + "9AEDC183-E503-4F83-A0D9-A0F9C6571E33", + 3, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-10T00:00:00Z", + "05 08 29 37 38 34", + "5" + ], + [ + 4, + "E67834B5-BF1F-4867-A457-8E26E87E9554", + 4, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-13T00:00:00Z", + "10 14 30 40 51 01", + "4" + ], + [ + 5, + "ECD06EF9-3D48-4A32-BEEA-B9D0A8E1499A", + 5, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-17T00:00:00Z", + "07 08 19 26 36 15", + "3" + ], + [ + 6, + "6A36058B-0D5F-4A4B-90C7-D37ED9754BCD", + 6, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-20T00:00:00Z", + "13 27 37 41 54 32", + "2" + ], + [ + 7, + "5D95F0A8-F691-45BD-837B-0ACC5722C724", + 7, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-24T00:00:00Z", + "04 17 35 50 57 12", + "2" + ], + [ + 8, + "7CDC9A40-0062-44DE-A33E-FCF7ED74F2F7", + 8, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-02-27T00:00:00Z", + "18 47 51 53 58 30", + "2" + ], + [ + 9, + "B4344C81-6048-47EC-BBB2-9BF061A11D1B", + 9, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-03T00:00:00Z", + "07 09 14 45 49 23", + "4" + ], + [ + 10, + "07B0351D-6EE2-4673-B8CC-56193D1C84DC", + 10, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-06T00:00:00Z", + "10 29 33 41 59 15", + "2" + ], + [ + 11, + "AF990B4F-BFDF-4BE8-8EFB-E10B3F950DB6", + 11, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-10T00:00:00Z", + "17 21 37 41 50 01", + "2" + ], + [ + 12, + "633A2A57-92FF-4E58-AAA9-16A826B9647E", + 12, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-13T00:00:00Z", + "06 16 20 31 36 08", + "5" + ], + [ + 13, + "2D7F73F5-4E71-4842-9A53-1E0B7C191232", + 13, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-17T00:00:00Z", + "24 26 45 48 55 08", + "2" + ], + [ + 14, + "39F91900-3EB5-4889-8C0C-3E943F7AA8A3", + 14, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-20T00:00:00Z", + "09 36 39 44 45 09", + "2" + ], + [ + 15, + "6A7E186E-9051-4771-ABA1-0A9849053799", + 15, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-24T00:00:00Z", + "14 20 24 39 49 07", + "3" + ], + [ + 16, + "F192902E-D8A7-430B-8040-DA272A7017E0", + 16, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-27T00:00:00Z", + "07 21 32 44 52 10", + "4" + ], + [ + 17, + "812663A1-2244-4865-9E7E-2FE73C4B0E33", + 17, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-03-31T00:00:00Z", + "05 13 17 45 54 12", + "5" + ], + [ + 18, + "FAB7E07A-27FF-455A-A7F4-C3ED1AB52304", + 18, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-03T00:00:00Z", + "10 15 31 52 59 04", + "4" + ], + [ + 19, + "DC7EE076-3EC5-46F7-BF2E-7263E9488B37", + 19, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-07T00:00:00Z", + "04 36 40 44 52 33", + "2" + ], + [ + 20, + "7197D3BF-94AB-49EF-B883-AD40A863E3BA", + 20, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-10T00:00:00Z", + "21 22 49 52 58 34", + "2" + ], + [ + 21, + "743DF432-2815-4714-863C-66B72F24605D", + 21, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-14T00:00:00Z", + "06 14 32 38 52 20", + "3" + ], + [ + 22, + "8C923446-232E-4941-8EB5-A66A17FBEF69", + 22, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-17T00:00:00Z", + "05 21 22 41 49 15", + "5" + ], + [ + 23, + "E0E09616-A6C5-4148-A2E5-F1701B6B1F87", + 23, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-21T00:00:00Z", + "11 34 41 49 55 20", + "2" + ], + [ + 24, + "248C0E3F-C489-4DD8-BB68-DD38F788BB58", + 24, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-24T00:00:00Z", + "01 12 53 56 57 05", + "2" + ], + [ + 25, + "CCE0FC4D-EB6A-4F8F-81FB-6D1DCED64CA4", + 25, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-04-28T00:00:00Z", + "12 22 25 28 44 24", + "4" + ], + [ + 26, + "02267C6C-AB6B-4B8B-B9FD-94FCC100A96E", + 26, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-01T00:00:00Z", + "16 23 25 49 58 20", + "4" + ], + [ + 27, + "20BC26C5-7FE1-4CED-8644-92759EEE96BD", + 27, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-05T00:00:00Z", + "13 34 40 47 57 11", + "4" + ], + [ + 28, + "5A337131-40E0-4867-B5A2-BB52D6AFE369", + 28, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-08T00:00:00Z", + "05 22 34 41 57 31", + "5" + ], + [ + 29, + "181CA471-4431-4279-A1BB-B291000D7791", + 29, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-12T00:00:00Z", + "37 51 52 53 58 38", + "2" + ], + [ + 30, + "C5C70FE1-BABE-4D8A-829F-854EE7CF0C42", + 30, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-15T00:00:00Z", + "15 21 23 28 36 20", + "2" + ], + [ + 31, + "BBF69F84-8CBB-446C-808C-4FFD42F8C697", + 31, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-19T00:00:00Z", + "02 07 29 55 58 27", + "3" + ], + [ + 32, + "0D13C24A-2A9A-4474-A2D9-6A289D71BB0A", + 32, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-22T00:00:00Z", + "19 20 40 47 57 29", + "2" + ], + [ + 33, + "97A2F181-B8F4-46FC-9B87-B7DA6C1CF2B7", + 33, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-26T00:00:00Z", + "01 06 10 13 20 32", + "4" + ], + [ + 34, + "DCA55B5C-1627-4FF1-B9F5-782A5D41D6C9", + 34, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-05-29T00:00:00Z", + "01 03 24 28 41 10", + "4" + ], + [ + 35, + "61E4F315-8AC6-4AD6-BA2B-A23560FBEE3D", + 35, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-02T00:00:00Z", + "04 09 14 39 43 38", + "4" + ], + [ + 36, + "5640B9E4-7126-493A-B91E-F941668FE470", + 36, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-05T00:00:00Z", + "18 34 40 48 59 25", + "4" + ], + [ + 37, + "BD942373-C55F-4C6F-9C0C-DBAAA5CC5559", + 37, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-09T00:00:00Z", + "14 22 27 32 49 05", + "4" + ], + [ + 38, + "BC07F54A-7951-44FA-B33B-21BCAE7C6F33", + 38, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-12T00:00:00Z", + "09 12 13 35 38 30", + "10" + ], + [ + 39, + "A39DC171-C91E-4968-A687-D0F37244B54E", + 39, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-16T00:00:00Z", + "08 11 18 29 36 06", + "5" + ], + [ + 40, + "C84C1A09-5AEA-411D-B206-3A1670812275", + 40, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-19T00:00:00Z", + "09 30 31 50 54 39", + "3" + ], + [ + 41, + "5C253151-8A9D-41B4-ADC7-36736C279671", + 41, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-23T00:00:00Z", + "11 30 45 47 48 10", + "3" + ], + [ + 42, + "981360DD-CA16-4D2B-9407-DAEB5EBE3267", + 42, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-26T00:00:00Z", + "13 30 32 38 57 25", + "4" + ], + [ + 43, + "5C9B4D04-7517-4A59-9811-89CEDB5FC5D3", + 43, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-06-30T00:00:00Z", + "06 38 43 47 48 27", + "5" + ], + [ + 44, + "C4C539BC-EBCE-463B-A4EB-F8037476447F", + 44, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-03T00:00:00Z", + "03 10 14 52 53 03", + "3" + ], + [ + 45, + "DB9F4D58-B01F-4C7E-9295-79935EC42014", + 45, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-07T00:00:00Z", + "10 41 44 48 56 04", + "2" + ], + [ + 46, + "21088D5B-000F-49E6-A1BC-BF6156B06F97", + 46, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-10T00:00:00Z", + "20 21 27 28 56 04", + "4" + ], + [ + 47, + "761AB2D4-CC73-430F-898C-3640437C24AC", + 47, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-14T00:00:00Z", + "20 21 23 38 42 06", + "3" + ], + [ + 48, + "3E764B7B-0536-4553-B147-CA59F6AD39B6", + 48, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-17T00:00:00Z", + "22 27 35 37 45 03", + "4" + ], + [ + 49, + "8BE6755A-CB72-4F4B-BB21-D5144C6B2471", + 49, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-21T00:00:00Z", + "16 22 30 51 58 25", + "3" + ], + [ + 50, + "FBD67CC1-FFFE-4992-9072-A3FF87043C6D", + 50, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-24T00:00:00Z", + "20 30 38 46 59 27", + "2" + ], + [ + 51, + "A7228EB5-44A6-4221-B277-102266B93E93", + 51, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-28T00:00:00Z", + "01 11 20 25 27 02", + "5" + ], + [ + 52, + "6B045B58-CA3F-49D2-9957-0EAF63AD133D", + 52, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-07-31T00:00:00Z", + "01 16 17 41 57 15", + "3" + ], + [ + 53, + "06F488E9-9E70-4259-AF65-425399B615B9", + 53, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-04T00:00:00Z", + "19 28 30 37 53 36", + "4" + ], + [ + 54, + "6BC3628F-8104-4BAD-87DF-41F85980BA83", + 54, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-07T00:00:00Z", + "04 22 26 31 52 30", + "5" + ], + [ + 55, + "B2168ECA-DF36-4193-937B-595A15C3D31D", + 55, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-11T00:00:00Z", + "07 10 22 23 52 29", + "2" + ], + [ + 56, + "593DF38C-05F5-4864-B229-0A26D69A6D48", + 56, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-14T00:00:00Z", + "09 33 36 50 58 31", + "2" + ], + [ + 57, + "DAE21B1F-F101-48DC-8C00-371F1F7E4DE7", + 57, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-18T00:00:00Z", + "04 32 33 47 55 39", + "3" + ], + [ + 58, + "D3F31D49-C789-4C40-A4BC-B747335FD9FA", + 58, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-21T00:00:00Z", + "07 10 12 22 27 26", + "2" + ], + [ + 59, + "A2B0E38D-31AF-4EF1-88E7-94ADDF9E3E6F", + 59, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-25T00:00:00Z", + "16 17 29 31 36 23", + "3" + ], + [ + 60, + "92ACA79B-9CE4-4F2A-8B1D-14EFBBCD8300", + 60, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-08-28T00:00:00Z", + "04 22 27 32 56 13", + "4" + ], + [ + 61, + "5E44F878-B62A-410A-BAE6-5007E0CE51A3", + 61, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-01T00:00:00Z", + "17 20 21 40 51 19", + "3" + ], + [ + 62, + "9133B613-6ABF-405F-96CB-3A9EADF71B56", + 62, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-04T00:00:00Z", + "11 14 22 33 42 38", + "2" + ], + [ + 63, + "7EE00F05-8B9B-4A55-B7DE-E4D73440D194", + 63, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-08T00:00:00Z", + "10 35 39 51 57 20", + "5" + ], + [ + 64, + "5151B097-89FF-4932-8CE4-A7238698B71F", + 64, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-11T00:00:00Z", + "07 17 20 36 59 33", + "4" + ], + [ + 65, + "AE464CA3-8876-478A-A442-0C486F8D62CC", + 65, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-15T00:00:00Z", + "07 20 21 34 43 34", + "5" + ], + [ + 66, + "DABAC9CC-604A-433D-A9CB-80F33B8DB8F5", + 66, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-18T00:00:00Z", + "01 18 37 39 44 13", + "4" + ], + [ + 67, + "ED62E207-E760-4BB2-9BFB-59E9BF4205C0", + 67, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-22T00:00:00Z", + "10 24 36 52 55 15", + "5" + ], + [ + 68, + "352BF116-9C83-4DB7-8422-A9F4FEA693BC", + 68, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-25T00:00:00Z", + "08 16 27 35 42 30", + "2" + ], + [ + 69, + "72561D26-F116-4C42-B7CD-717D82149C12", + 69, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-09-29T00:00:00Z", + "13 44 51 52 55 30", + "4" + ], + [ + 70, + "3FC171C6-8936-4872-90DF-994281F73D02", + 70, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-02T00:00:00Z", + "12 20 30 36 47 25", + "4" + ], + [ + 71, + "FFD2A4A9-2BD4-4E89-9EE4-F597B6DDBCC4", + 71, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-06T00:00:00Z", + "14 26 37 41 46 24", + "5" + ], + [ + 72, + "C22C5B84-322D-4CBC-9600-F42ADF3163FB", + 72, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-09T00:00:00Z", + "02 06 32 42 49 35", + "3" + ], + [ + 73, + "64CC8513-4ABE-484B-A6E3-8C1401B12C4C", + 73, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-13T00:00:00Z", + "12 22 32 34 46 02", + "4" + ], + [ + 74, + "3301A17B-CF71-41AB-9787-614EDFE7C4EC", + 74, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-16T00:00:00Z", + "11 12 15 16 28 11", + "2" + ], + [ + 75, + "DCBDF086-B73C-4375-B745-21506C9A5DD2", + 75, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-20T00:00:00Z", + "07 17 20 39 59 17", + "3" + ], + [ + 76, + "62B84F14-8741-47A2-978C-748A9CD3090F", + 76, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-23T00:00:00Z", + "02 07 16 20 46 34", + "4" + ], + [ + 77, + "4EF6C071-1A67-4CB1-8664-B14C8E58CBFC", + 77, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-27T00:00:00Z", + "20 24 25 53 59 15", + "5" + ], + [ + 78, + "29F77288-AAE5-40F6-85F1-49034D76394E", + 78, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-10-30T00:00:00Z", + "01 07 27 36 49 39", + "5" + ], + [ + 79, + "99BFAC1C-14DD-47A0-A697-F44B76A708AD", + 79, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-03T00:00:00Z", + "34 38 39 45 50 33", + "2" + ], + [ + 80, + "6DAC5801-1E01-4D10-86D6-070762A4F50F", + 80, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-06T00:00:00Z", + "07 12 23 34 38 33", + "4" + ], + [ + 81, + "0BA8EFBC-E383-4063-82CF-84728365E61E", + 81, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-10T00:00:00Z", + "05 08 11 40 44 10", + "4" + ], + [ + 82, + "3F894729-A7A7-4E55-846E-3FD2191B7F88", + 82, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-13T00:00:00Z", + "17 30 48 51 54 29", + "5" + ], + [ + 83, + "570CDB2A-E9D5-4375-A611-44D8A5C55C3A", + 83, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-17T00:00:00Z", + "14 16 53 54 59 05", + "3" + ], + [ + 84, + "29C3FB4C-5898-4B1B-A07F-A96246DBE40B", + 84, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-20T00:00:00Z", + "10 12 38 53 57 01", + "5" + ], + [ + 85, + "0437BD3B-7443-413F-94A6-C311CD043BBC", + 85, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-24T00:00:00Z", + "08 20 21 32 37 04", + "3" + ], + [ + 86, + "AA4A70D1-A86A-4A8A-AD80-48129D1FE8E0", + 86, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-11-27T00:00:00Z", + "10 30 37 47 54 39", + "5" + ], + [ + 87, + "64361722-B061-4486-940F-6A72800287AC", + 87, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-01T00:00:00Z", + "05 10 11 12 20 02", + "3" + ], + [ + 88, + "E93C2325-0FD6-4C7C-8E2B-2B24CB5340C2", + 88, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-04T00:00:00Z", + "13 24 27 31 42 22", + "5" + ], + [ + 89, + "C9EC5D1F-BC31-4FE4-B403-1B18057F9E83", + 89, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-08T00:00:00Z", + "08 11 25 41 58 16", + "4" + ], + [ + 90, + "97995811-5050-43E9-BC76-D580315CA1EC", + 90, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-11T00:00:00Z", + "01 08 10 19 20 23", + "2" + ], + [ + 91, + "92ADBB7A-CA7E-4155-8F25-629BC4925798", + 91, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-15T00:00:00Z", + "10 11 18 32 45 18", + "5" + ], + [ + 92, + "7F32B5D0-5ABC-46F5-819D-E469CB5A5EE8", + 92, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-18T00:00:00Z", + "04 11 19 33 43 14", + "4" + ], + [ + 93, + "D1C86092-E5F9-4229-A737-F9CD6B6D1EFA", + 93, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-22T00:00:00Z", + "11 33 44 46 47 12", + "2" + ], + [ + 94, + "5198F649-642C-4E21-A772-134F09716BA3", + 94, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-25T00:00:00Z", + "01 17 38 50 52 24", + "2" + ], + [ + 95, + "4FC247E7-FCB1-4530-9DCE-C52909402E52", + 95, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2010-12-29T00:00:00Z", + "03 16 18 20 37 30", + "2" + ], + [ + 96, + "93F87258-233E-4B01-A29A-8EFCCE13722C", + 96, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-01T00:00:00Z", + "18 22 37 47 54 36", + "2" + ], + [ + 97, + "40038954-8377-494E-944E-908E85973739", + 97, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-05T00:00:00Z", + "22 26 32 38 40 07", + "5" + ], + [ + 98, + "C45F6776-46DC-4484-A22D-2710D96F7479", + 98, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-08T00:00:00Z", + "06 07 26 33 52 24", + "2" + ], + [ + 99, + "B6356A6B-4369-4138-A6EE-AC710C822F4A", + 99, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-12T00:00:00Z", + "19 21 23 40 48 27", + "4" + ], + [ + 100, + "CF901D2A-4E08-4E73-831B-A949AC1141D6", + 100, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-15T00:00:00Z", + "09 13 22 23 37 31", + "3" + ], + [ + 101, + "8AE587F8-B4D4-48F1-A5CD-74A2D61965C0", + 101, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-19T00:00:00Z", + "22 36 51 56 59 32", + "3" + ], + [ + 102, + "AF143F6E-C97C-400B-B1B4-F2E6D55DD9F3", + 102, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-22T00:00:00Z", + "30 31 34 45 51 23", + "2" + ], + [ + 103, + "05BD1A80-DAC2-4877-B98A-85A642530EE5", + 103, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-26T00:00:00Z", + "04 05 36 47 58 06", + "3" + ], + [ + 104, + "E016B13D-A0E4-4DA7-BDE3-68CD0F747494", + 104, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-01-29T00:00:00Z", + "24 28 45 49 52 02", + "4" + ], + [ + 105, + "B3BCD26B-3E87-49B5-9E32-A944F64853C6", + 105, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-02T00:00:00Z", + "03 14 33 53 57 36", + "4" + ], + [ + 106, + "EA37777E-4995-4377-94BD-C63B99CADD29", + 106, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-05T00:00:00Z", + "15 37 41 56 59 05", + "5" + ], + [ + 107, + "4FCF4408-9656-46A5-9819-21003BC40254", + 107, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-09T00:00:00Z", + "07 11 39 42 51 30", + "4" + ], + [ + 108, + "05A24764-9DEA-4AEF-93A5-AB82E261185D", + 108, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-12T00:00:00Z", + "11 32 36 48 52 19", + "4" + ], + [ + 109, + "8F293368-4D17-4AD5-AF5B-C74726FD0434", + 109, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-16T00:00:00Z", + "09 13 21 23 48 24", + "2" + ], + [ + 110, + "061296AF-4EFD-41C1-B9CF-E17CD2852137", + 110, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-19T00:00:00Z", + "03 12 34 37 42 36", + "5" + ], + [ + 111, + "2A3C62E6-7D95-4563-9AB2-7AE7765DB390", + 111, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-23T00:00:00Z", + "29 32 36 39 49 29", + "3" + ], + [ + 112, + "F9220CDF-6C68-4D5D-95F2-8AFC87973920", + 112, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-02-26T00:00:00Z", + "04 13 17 21 45 10", + "5" + ], + [ + 113, + "FD1388E7-2747-47FA-949D-05FD678528AB", + 113, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-02T00:00:00Z", + "07 31 50 51 58 06", + "2" + ], + [ + 114, + "CC29B3FF-7526-467F-81BB-16E0237C3E0C", + 114, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-05T00:00:00Z", + "02 23 31 42 48 21", + "2" + ], + [ + 115, + "FF3AEC1E-2DDC-4C2A-9E7D-3DE77D22C255", + 115, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-09T00:00:00Z", + "12 20 28 40 48 08", + "2" + ], + [ + 116, + "557208D2-F86E-4E3F-9FCB-A5BEE7356AFA", + 116, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-12T00:00:00Z", + "01 04 12 41 47 03", + "4" + ], + [ + 117, + "533BD995-6463-429B-9958-A9BED29B39D0", + 117, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-16T00:00:00Z", + "28 39 40 48 53 09", + "3" + ], + [ + 118, + "F71FBC6A-7F1F-4031-8178-72989CA00D2F", + 118, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-19T00:00:00Z", + "03 11 20 27 46 08", + "2" + ], + [ + 119, + "F9CE6E77-CD5F-452A-8F5A-363513D83F62", + 119, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-23T00:00:00Z", + "05 15 26 28 32 09", + "2" + ], + [ + 120, + "58851C51-CBA6-4015-ADB3-0632A9458096", + 120, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-26T00:00:00Z", + "04 10 11 19 33 27", + "4" + ], + [ + 121, + "98108522-00D3-4187-9D88-800337831326", + 121, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-03-30T00:00:00Z", + "19 20 42 56 58 37", + "4" + ], + [ + 122, + "526B953C-4B88-4AE0-8D48-0E74E7A8CF16", + 122, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-02T00:00:00Z", + "06 22 34 43 45 23", + "2" + ], + [ + 123, + "5E1119FF-9619-4732-A895-865FE789F558", + 123, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-06T00:00:00Z", + "10 18 41 55 56 15", + "2" + ], + [ + 124, + "0CE21D53-C1DC-4C48-A18F-CB4BF10B7F20", + 124, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-09T00:00:00Z", + "05 14 32 53 56 11", + "4" + ], + [ + 125, + "7E843BE0-E068-4511-8237-9D5750123BF8", + 125, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-13T00:00:00Z", + "04 23 39 49 50 39", + "3" + ], + [ + 126, + "51ED8DC0-6501-40FB-9531-3910843D6BC0", + 126, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-16T00:00:00Z", + "21 33 44 45 55 07", + "5" + ], + [ + 127, + "E1AB915B-0D8E-4BBA-9089-37023D54ECBF", + 127, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-20T00:00:00Z", + "09 24 34 36 43 27", + "3" + ], + [ + 128, + "287D98E0-5CB1-4EF9-9A57-79BEF03483A7", + 128, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-23T00:00:00Z", + "03 11 47 48 58 19", + "3" + ], + [ + 129, + "5230AEAD-648E-4D5E-8F6D-1B64A3E7A1AB", + 129, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-27T00:00:00Z", + "04 24 40 44 55 05", + "2" + ], + [ + 130, + "45333360-9131-4043-8852-CB77AA794370", + 130, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-04-30T00:00:00Z", + "06 13 15 32 41 03", + "2" + ], + [ + 131, + "79798878-CCD2-453E-9E27-DA9765FD2A3A", + 131, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-04T00:00:00Z", + "03 15 27 29 41 24", + "4" + ], + [ + 132, + "B3163D53-EA4D-4386-A43E-EFC60A5AEF26", + 132, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-07T00:00:00Z", + "02 11 27 47 55 15", + "4" + ], + [ + 133, + "097C8559-2817-4737-B26D-ECB09BC40AC0", + 133, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-11T00:00:00Z", + "09 17 32 43 45 31", + "3" + ], + [ + 134, + "062F616D-0E21-4794-8D63-3E30E3681E44", + 134, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-14T00:00:00Z", + "08 17 18 40 44 16", + "2" + ], + [ + 135, + "0D63C006-11D5-40CF-B587-384346C41C25", + 135, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-18T00:00:00Z", + "07 12 13 42 49 16", + "4" + ], + [ + 136, + "0FF01D7C-AE37-437E-A5AC-61BAA2508D7D", + 136, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-21T00:00:00Z", + "02 08 40 49 50 36", + "3" + ], + [ + 137, + "A2C61ADF-F689-4794-A808-84A75826E743", + 137, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-25T00:00:00Z", + "04 23 31 42 50 23", + "2" + ], + [ + 138, + "F3267566-AE83-44F3-8160-789EA1016E1D", + 138, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-05-28T00:00:00Z", + "12 20 43 51 55 11", + "4" + ], + [ + 139, + "02B6BE3F-A964-47C4-9697-E29201F09028", + 139, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-01T00:00:00Z", + "08 18 38 46 56 31", + "4" + ], + [ + 140, + "CC7942F6-877B-48B6-9181-93A1C98B0359", + 140, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-04T00:00:00Z", + "17 19 39 41 58 21", + "5" + ], + [ + 141, + "61378B85-5CAA-4022-B572-B4AE0E2F7777", + 141, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-08T00:00:00Z", + "14 37 44 45 53 29", + "5" + ], + [ + 142, + "F91BBF8A-2984-4398-8770-E4CDB5CDC4A4", + 142, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-11T00:00:00Z", + "16 18 27 36 50 08", + "3" + ], + [ + 143, + "7D7AC37A-E986-4A6B-B961-922D9EDF1F35", + 143, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-15T00:00:00Z", + "19 20 38 41 43 29", + "4" + ], + [ + 144, + "0ED73FCF-199E-45CC-9C97-363AA8FDFDCF", + 144, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-18T00:00:00Z", + "12 21 22 38 41 18", + "2" + ], + [ + 145, + "A3F9E171-836B-485E-8CEE-5B98BC033F4E", + 145, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-22T00:00:00Z", + "12 15 19 46 59 12", + "4" + ], + [ + 146, + "7D31993D-45DC-41A3-BFD0-9A813652F08E", + 146, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-25T00:00:00Z", + "18 36 39 41 57 12", + "4" + ], + [ + 147, + "2F615FCA-77BF-467B-B83F-C8C952A495B1", + 147, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-06-29T00:00:00Z", + "24 30 45 57 59 26", + "3" + ], + [ + 148, + "C763B039-97BC-429A-A266-54E676FD9FE8", + 148, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-02T00:00:00Z", + "01 11 18 29 51 32", + "3" + ], + [ + 149, + "0CE75BB4-3F14-4A49-A29C-821D5214EEFF", + 149, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-06T00:00:00Z", + "11 15 24 50 55 08", + "2" + ], + [ + 150, + "28EC195A-D329-4CD4-8186-830B0B26E986", + 150, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-09T00:00:00Z", + "01 09 11 23 31 06", + "3" + ], + [ + 151, + "F01DDCEF-548F-470B-AA4C-64344207CF70", + 151, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-13T00:00:00Z", + "08 18 19 32 54 08", + "4" + ], + [ + 152, + "BF59C62F-CE42-46B3-8D53-4BB89C044A0B", + 152, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-16T00:00:00Z", + "24 28 48 50 54 25", + "3" + ], + [ + 153, + "F382A07F-8C7F-4421-9787-1F1848CD9495", + 153, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-20T00:00:00Z", + "01 04 38 40 42 17", + "4" + ], + [ + 154, + "B816B09A-67CE-4F64-8F46-F40067CDEFB9", + 154, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-23T00:00:00Z", + "01 07 27 38 48 30", + "3" + ], + [ + 155, + "C4AE9DAC-E9EF-4D8E-A325-215DD8E9ED66", + 155, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-27T00:00:00Z", + "38 40 41 51 59 33", + "2" + ], + [ + 156, + "50A1075C-9262-4B20-8D86-C8D90A4E7752", + 156, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-07-30T00:00:00Z", + "20 40 41 47 55 19", + "2" + ], + [ + 157, + "44654407-6D79-4A7B-9289-448842BDFABD", + 157, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-03T00:00:00Z", + "13 19 21 28 49 11", + "2" + ], + [ + 158, + "8E9ECF5E-B2FD-4573-B80A-2A1ADCDC4202", + 158, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-06T00:00:00Z", + "25 30 54 57 59 06", + "3" + ], + [ + 159, + "8C84603D-A637-400F-885E-83939C95191E", + 159, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-10T00:00:00Z", + "11 18 36 41 46 38", + "4" + ], + [ + 160, + "C3DAF6FF-C8EE-4D4D-A6FE-D1B18DD65FF1", + 160, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-13T00:00:00Z", + "09 12 35 50 58 04", + "2" + ], + [ + 161, + "0EB476D2-7418-4354-B8A8-205A90DC1DDF", + 161, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-17T00:00:00Z", + "18 28 31 48 52 37", + "4" + ], + [ + 162, + "1480D8BB-7D88-4307-83EB-917D7D3D60A6", + 162, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-20T00:00:00Z", + "02 17 23 28 47 36", + "2" + ], + [ + 163, + "91FFF0D2-E5F6-46F2-AF8D-530E691E2758", + 163, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-24T00:00:00Z", + "09 13 47 49 53 39", + "5" + ], + [ + 164, + "DDE69E16-E29A-44F9-8DF0-B75FC8E5446E", + 164, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-27T00:00:00Z", + "02 12 25 54 58 14", + "3" + ], + [ + 165, + "03453461-CFD5-45F8-B8D6-4F4EFC4B3E1D", + 165, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-08-31T00:00:00Z", + "13 19 35 47 57 29", + "5" + ], + [ + 166, + "56803DBA-389D-414C-95F1-3F1F4EF87C93", + 166, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-03T00:00:00Z", + "15 25 52 53 54 02", + "5" + ], + [ + 167, + "7B8C595B-EAA8-4511-AB8A-22F05D0E1493", + 167, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-07T00:00:00Z", + "03 05 18 27 54 13", + "4" + ], + [ + 168, + "9A979EB9-5F95-4313-A115-1D0FDB7B2AA0", + 168, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-10T00:00:00Z", + "04 19 22 32 53 24", + "4" + ], + [ + 169, + "9FA4926B-6EEB-4FAB-A6A6-B8A71BF39BCD", + 169, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-14T00:00:00Z", + "16 41 42 50 59 05", + "3" + ], + [ + 170, + "7D4EDF40-6655-4D99-A635-66CC7FDAB422", + 170, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-17T00:00:00Z", + "06 20 22 32 43 11", + "2" + ], + [ + 171, + "17CEB9C3-945A-4874-BA6F-B9AE7C07FAFC", + 171, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-21T00:00:00Z", + "12 47 48 52 55 13", + "4" + ], + [ + 172, + "D074055A-E72B-4DBB-B1FB-E8783EAA0D41", + 172, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-24T00:00:00Z", + "03 04 12 27 44 26", + "5" + ], + [ + 173, + "34C73D37-392F-43BC-A494-E0FB5D6B354D", + 173, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-09-28T00:00:00Z", + "30 41 50 51 53 08", + "2" + ], + [ + 174, + "8EC47719-C980-4F2D-95A7-6DEA8EBBE49B", + 174, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-01T00:00:00Z", + "01 12 23 27 43 31", + "3" + ], + [ + 175, + "7E194E19-56CE-4A82-991B-E623641DDA4B", + 175, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-05T00:00:00Z", + "07 20 43 46 54 17", + "4" + ], + [ + 176, + "2E0A35CF-76FC-4AA4-9F59-B69878A66A81", + 176, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-08T00:00:00Z", + "03 27 35 37 45 31", + "5" + ], + [ + 177, + "4FE26456-F945-4CA1-9849-5405C5EB0D02", + 177, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-12T00:00:00Z", + "10 12 23 43 47 18", + "3" + ], + [ + 178, + "3989F7B0-F975-4456-986E-531A691311D9", + 178, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-15T00:00:00Z", + "05 10 24 38 43 01", + "4" + ], + [ + 179, + "36AEAE64-DA73-43F7-85B0-90FD865FFC9B", + 179, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-19T00:00:00Z", + "16 26 35 52 58 02", + "5" + ], + [ + 180, + "F14A714F-288C-4A49-80D9-8241C098F089", + 180, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-22T00:00:00Z", + "03 08 23 30 58 13", + "4" + ], + [ + 181, + "A3FFE3C7-995D-45D4-91E9-FAEB81FA105A", + 181, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-26T00:00:00Z", + "01 18 21 39 55 06", + "3" + ], + [ + 182, + "300213E7-DCFA-44CC-BD61-479DD2E54C11", + 182, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-10-29T00:00:00Z", + "11 16 40 51 56 38", + "5" + ], + [ + 183, + "9F7AB101-0EC5-4617-AAD4-FB5DD9810884", + 183, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-02T00:00:00Z", + "12 14 34 39 46 36", + "4" + ], + [ + 184, + "F32FB3B1-964E-4D3B-86A3-B39E8A1E44C8", + 184, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-05T00:00:00Z", + "02 33 39 40 43 26", + "3" + ], + [ + 185, + "05C290E8-16E5-4171-934E-A81EF8EA7CE4", + 185, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-09T00:00:00Z", + "05 35 57 58 59 12", + "3" + ], + [ + 186, + "29DD3DC2-E14B-4EDE-9C30-8216914D6FEA", + 186, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-12T00:00:00Z", + "04 35 36 51 56 08", + "5" + ], + [ + 187, + "8D0CE332-1F93-4397-80B5-7EEC36FA54C2", + 187, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-16T00:00:00Z", + "13 22 25 39 51 28", + "2" + ], + [ + 188, + "047DBA01-8F50-437D-A8CC-1A8EBB69B7B8", + 188, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-19T00:00:00Z", + "09 16 17 28 30 11", + "3" + ], + [ + 189, + "5354A5AD-8C46-4292-922D-061B18AB5D56", + 189, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-23T00:00:00Z", + "04 30 35 57 59 25", + "2" + ], + [ + 190, + "4064BDA6-CA03-4989-B90F-43317004BFF5", + 190, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-26T00:00:00Z", + "20 37 39 45 55 28", + "2" + ], + [ + 191, + "1AFEF399-4B0D-4F4B-8B78-731594986C57", + 191, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-11-30T00:00:00Z", + "02 06 34 35 47 22", + "2" + ], + [ + 192, + "7B2EB6A1-B2C2-410D-B252-880BC27937CD", + 192, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-03T00:00:00Z", + "05 18 33 43 45 08", + "3" + ], + [ + 193, + "3DE2C47F-5816-4A66-A1D1-A926FEDC1D96", + 193, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-07T00:00:00Z", + "03 14 20 39 40 37", + "2" + ], + [ + 194, + "18FDF2CE-359B-4AE4-ADDD-EE9BA474C3BC", + 194, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-10T00:00:00Z", + "04 19 33 41 59 09", + "5" + ], + [ + 195, + "997563CF-3217-4133-BC62-E7C36F38FF0B", + 195, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-14T00:00:00Z", + "02 24 46 52 56 19", + "5" + ], + [ + 196, + "583A0BA7-F5C2-4537-A074-F4589AD9ADCB", + 196, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-17T00:00:00Z", + "13 28 49 51 59 33", + "4" + ], + [ + 197, + "C1165E24-1C4B-4FB3-936D-3D6EE2FC6EB6", + 197, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-21T00:00:00Z", + "10 13 15 31 54 18", + "5" + ], + [ + 198, + "828E2F73-D48C-4C04-A3F1-2BB4E739E0D8", + 198, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-24T00:00:00Z", + "14 16 30 51 52 19", + "2" + ], + [ + 199, + "CA3DF9C8-70E1-4A1D-8520-452A0E9E058E", + 199, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-28T00:00:00Z", + "16 21 27 41 45 14", + "2" + ], + [ + 200, + "07D40B41-E652-4393-B749-19685DE4579C", + 200, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2011-12-31T00:00:00Z", + "05 23 25 28 40 34", + "4" + ], + [ + 201, + "6ED79AB6-04B8-48AF-802D-F8940CFC370A", + 201, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-04T00:00:00Z", + "21 35 46 47 50 02", + "4" + ], + [ + 202, + "4F718048-E61B-495B-805C-E35624F2182D", + 202, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-07T00:00:00Z", + "03 21 24 38 39 24", + "5" + ], + [ + 203, + "99D4B50F-83D9-478D-AA96-B7225A6A0F2B", + 203, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-11T00:00:00Z", + "05 19 29 45 47 25", + "2" + ], + [ + 204, + "369DB95A-DE5B-4070-A175-54CEA5043F88", + 204, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-14T00:00:00Z", + "10 30 36 38 41 01", + "5" + ], + [ + 205, + "68BFE997-EF24-4FF7-809E-4B98BAD12A33", + 205, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-18T00:00:00Z", + "06 29 34 44 50 28", + null + ], + [ + 206, + "73E19009-0F21-46C8-951D-D7BB50ECE5F1", + 206, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-21T00:00:00Z", + "12 24 43 44 45 07", + null + ], + [ + 207, + "02C6C142-463F-413B-9005-56E28EC96210", + 207, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-25T00:00:00Z", + "04 19 28 29 47 05", + null + ], + [ + 208, + "7B5054A4-2F50-484B-86F6-9F9CF78CC9A5", + 208, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-01-28T00:00:00Z", + "05 33 41 54 59 13", + null + ], + [ + 209, + "1EF7C6C9-8B72-48E6-AB36-6BFCFB77B3DE", + 209, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-01T00:00:00Z", + "08 13 17 34 59 35", + null + ], + [ + 210, + "A1F66607-2F2B-4C84-AD68-D3AF901A6182", + 210, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-04T00:00:00Z", + "15 23 43 45 56 07", + null + ], + [ + 211, + "9A2D1456-8BFB-40DF-A66A-FAF7EF6B4355", + 211, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-08T00:00:00Z", + "17 28 38 39 51 33", + null + ], + [ + 212, + "C9F84026-FA64-4891-8FDC-7D91CFAA9773", + 212, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-11T00:00:00Z", + "01 10 37 52 57 11", + null + ], + [ + 213, + "35B6335E-90F5-406F-9417-9ECA5F4ED28E", + 213, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-15T00:00:00Z", + "11 12 32 52 56 11", + null + ], + [ + 214, + "0D5BCFD5-88FC-46D0-ACD6-54C967456941", + 214, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-18T00:00:00Z", + "23 28 50 56 59 05", + null + ], + [ + 215, + "8F769561-C534-46EF-8DC9-0CD5F69FCD7C", + 215, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-22T00:00:00Z", + "07 16 17 39 51 32", + null + ], + [ + 216, + "F72A4C8C-E83F-4623-B0A8-AC4170F711BC", + 216, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-25T00:00:00Z", + "06 11 42 53 54 07", + null + ], + [ + 217, + "C6FD7554-ACF3-45A5-8B06-06DC1DF30BB2", + 217, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-02-29T00:00:00Z", + "01 04 11 23 26 14", + null + ], + [ + 218, + "222E59E8-FFD7-4CC5-BC7C-B757746CAF8D", + 218, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-03T00:00:00Z", + "29 30 45 47 49 35", + null + ], + [ + 219, + "D2A8DF68-9343-49F2-8705-FD28B2CC3A90", + 219, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-07T00:00:00Z", + "12 35 45 46 47 12", + null + ], + [ + 220, + "A36FEF9D-2D5B-4DEC-8A5E-58497A21241A", + 220, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-10T00:00:00Z", + "05 14 17 20 41 05", + null + ], + [ + 221, + "6BBE1009-6381-419A-88CC-F4DCCDF5AEEE", + 221, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-14T00:00:00Z", + "01 08 41 46 59 24", + null + ], + [ + 222, + "6340B968-9772-46AA-A489-0928359C5E72", + 222, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-17T00:00:00Z", + "11 14 49 55 58 30", + null + ], + [ + 223, + "28FCDA38-FE5D-4F76-8E81-91D7C46AEE36", + 223, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-21T00:00:00Z", + "32 43 53 55 56 06", + null + ], + [ + 224, + "C13FB396-7E85-4D9D-84E7-8F31BBE3953D", + 224, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-24T00:00:00Z", + "01 15 35 37 47 08", + null + ], + [ + 225, + "77D4E5AC-74EF-49E1-8D14-E1F3C85235C8", + 225, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-28T00:00:00Z", + "11 16 29 50 58 33", + null + ], + [ + 226, + "892B6304-F1C9-4968-BEFB-1D518B238C0A", + 226, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-03-31T00:00:00Z", + "05 14 36 54 58 27", + null + ], + [ + 227, + "0540775F-6648-4FEA-8444-5573749AE140", + 227, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-04T00:00:00Z", + "01 24 33 45 49 06", + null + ], + [ + 228, + "E63BE891-43F0-4910-8EE4-5EDA1FBB719F", + 228, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-07T00:00:00Z", + "05 13 17 20 30 18", + null + ], + [ + 229, + "82DD4C26-AA7D-4C11-BEA8-9899EF5FF86A", + 229, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-11T00:00:00Z", + "16 23 42 44 47 02", + null + ], + [ + 230, + "DAB9D612-C187-4B13-BCBC-36E33A22250B", + 230, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-14T00:00:00Z", + "14 15 16 19 24 02", + null + ], + [ + 231, + "82FC523B-BD1D-4A5B-925C-488764025F63", + 231, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-18T00:00:00Z", + "20 22 39 46 49 29", + null + ], + [ + 232, + "08E109BC-46CD-405D-B55B-D63C8EF1E88E", + 232, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-21T00:00:00Z", + "06 08 20 42 51 16", + null + ], + [ + 233, + "25732E04-4CEA-481A-BBBD-BB706A4822A2", + 233, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-25T00:00:00Z", + "04 25 29 34 43 29", + null + ], + [ + 234, + "84D6DF1E-2850-48D6-81C8-BA6813947093", + 234, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-04-28T00:00:00Z", + "31 39 40 57 58 33", + null + ], + [ + 235, + "CE62EC65-4B54-424B-AF1E-9DA89A23AC3B", + 235, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-02T00:00:00Z", + "07 08 33 38 50 29", + null + ], + [ + 236, + "247DF1DB-7140-4F4E-BAA8-82D44151B697", + 236, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-05T00:00:00Z", + "09 12 20 44 59 23", + null + ], + [ + 237, + "1D2FD83C-6F5D-4D0E-84F6-DBEBA73226FB", + 237, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-09T00:00:00Z", + "01 07 11 55 56 01", + null + ], + [ + 238, + "9F497756-5D8C-44F9-BCA9-32C85F24C7B4", + 238, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-12T00:00:00Z", + "10 24 35 53 58 22", + null + ], + [ + 239, + "CDC9826E-CAA4-4851-BA89-40F94C43640F", + 239, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-16T00:00:00Z", + "03 07 21 28 43 02", + null + ], + [ + 240, + "38ED6B08-4AE8-4D03-9CA3-F6CEEE7AD5EA", + 240, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-19T00:00:00Z", + "08 13 35 46 51 30", + null + ], + [ + 241, + "DC69454E-7153-42B1-80C0-B782FE2947C6", + 241, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-23T00:00:00Z", + "04 07 26 53 59 32", + null + ], + [ + 242, + "37DC3FAB-1784-4A7F-8175-12BF55F9F707", + 242, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-26T00:00:00Z", + "13 14 41 49 59 14", + null + ], + [ + 243, + "8841334C-6681-4C95-A2D1-E98368995E74", + 243, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-05-30T00:00:00Z", + "09 10 24 52 56 14", + null + ], + [ + 244, + "BC98C758-2146-4840-B56D-F558C6DFC597", + 244, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-02T00:00:00Z", + "09 10 17 29 45 33", + null + ], + [ + 245, + "8745C895-057D-425C-8AC4-3893B1217811", + 245, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-06T00:00:00Z", + "19 30 33 48 59 27", + null + ], + [ + 246, + "7ADA588B-6072-453B-83D3-3121A766E766", + 246, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-09T00:00:00Z", + "18 22 45 56 57 27", + null + ], + [ + 247, + "EE8DA13A-D8D2-4E45-AB14-F582E01B1890", + 247, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-13T00:00:00Z", + "07 10 14 33 57 18", + null + ], + [ + 248, + "131CCCCE-98B4-4508-BBE4-D1DAF52D24C1", + 248, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-16T00:00:00Z", + "08 14 15 16 27 26", + null + ], + [ + 249, + "E485B061-0AB2-480C-83DD-CDD20DAF53A9", + 249, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-20T00:00:00Z", + "11 17 29 56 57 14", + null + ], + [ + 250, + "64752403-F193-4E6C-8DAB-426B915D324C", + 250, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-23T00:00:00Z", + "01 03 41 44 53 30", + null + ], + [ + 251, + "5A9F43EF-49A3-4775-B5D4-01FB399BDBA0", + 251, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-27T00:00:00Z", + "06 34 40 46 58 06", + null + ], + [ + 252, + "187F3244-451C-44C4-9E2E-F6148EBD5486", + 252, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-06-30T00:00:00Z", + "07 15 20 41 44 22", + null + ], + [ + 253, + "0520D56E-49E1-4437-883A-BEA8549177E9", + 253, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-04T00:00:00Z", + "14 19 35 39 56 33", + null + ], + [ + 254, + "289BFBF7-9899-4318-8FA9-248D0D2DD6BE", + 254, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-07T00:00:00Z", + "03 05 29 39 59 29", + null + ], + [ + 255, + "5A74A68D-4FE4-47CF-A30E-FD00A448556C", + 255, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-11T00:00:00Z", + "05 22 36 49 55 23", + null + ], + [ + 256, + "68724EFF-9945-4B64-8703-C3885EEBF72A", + 256, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-14T00:00:00Z", + "04 16 32 37 46 13", + null + ], + [ + 257, + "E97770CF-2D5B-4E50-AD4E-DA908CB1A65D", + 257, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-18T00:00:00Z", + "02 05 20 23 57 03", + null + ], + [ + 258, + "94CE7B77-0577-441F-AEB8-21C06FB72FB1", + 258, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-21T00:00:00Z", + "09 31 38 54 56 20", + null + ], + [ + 259, + "EF93A1EE-E937-46EE-BE45-93144E3B018A", + 259, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-25T00:00:00Z", + "03 14 35 38 46 16", + null + ], + [ + 260, + "E6E27C61-9F67-4435-B056-6C9E11E05396", + 260, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-07-28T00:00:00Z", + "05 06 13 36 50 13", + null + ], + [ + 261, + "DFF18A33-7D8D-49DE-8811-13A0E2D2C846", + 261, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-01T00:00:00Z", + "03 16 48 56 58 04", + null + ], + [ + 262, + "98DBB22C-0155-4F72-A68B-179D47A1C9BA", + 262, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-04T00:00:00Z", + "19 30 48 53 55 18", + null + ], + [ + 263, + "3BCB7B3F-E4B8-4AB7-A071-82998C6274EF", + 263, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-08T00:00:00Z", + "03 07 11 15 28 12", + null + ], + [ + 264, + "BD63131D-D862-4186-A0EF-4A290455A282", + 264, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-11T00:00:00Z", + "04 13 39 46 51 01", + null + ], + [ + 265, + "06C0AA9D-39A8-4928-8C8F-61DA329BCC7F", + 265, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-15T00:00:00Z", + "06 27 46 51 56 21", + null + ], + [ + 266, + "4BE3F65C-4B6A-4081-B75D-9280C8367C17", + 266, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-18T00:00:00Z", + "14 26 41 55 59 01", + null + ], + [ + 267, + "9A0B6856-C420-4411-84EA-99AC6BBF0015", + 267, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-22T00:00:00Z", + "22 29 31 47 55 19", + null + ], + [ + 268, + "BF067455-0051-4B07-8A18-CAC7AA537C02", + 268, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-25T00:00:00Z", + "01 06 07 20 49 23", + null + ], + [ + 269, + "BE75088A-CED8-44AC-AFB8-19C09D6FE196", + 269, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-08-29T00:00:00Z", + "25 28 49 54 56 28", + null + ], + [ + 270, + "CEECAF38-CF6B-4715-8EE1-37C5206F1C2C", + 270, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-01T00:00:00Z", + "08 11 21 44 49 22", + null + ], + [ + 271, + "CE3C7F39-5D43-4AFF-9761-7CE56DB9D923", + 271, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-05T00:00:00Z", + "04 19 26 42 51 29", + null + ], + [ + 272, + "9D59886E-17B3-4947-90D9-2D3901D57C71", + 272, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-08T00:00:00Z", + "06 20 34 44 48 29", + null + ], + [ + 273, + "49C909B5-17D3-4790-9665-6C8030223DB0", + 273, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-12T00:00:00Z", + "24 33 36 48 56 06", + null + ], + [ + 274, + "AD1E516B-00D1-45E2-910C-1440D98CB95B", + 274, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-15T00:00:00Z", + "03 20 26 43 48 01", + null + ], + [ + 275, + "B5ACAEA4-1D1F-43F9-BC05-A0248EB5BE8B", + 275, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-19T00:00:00Z", + "01 05 08 39 50 23", + null + ], + [ + 276, + "5DDD7687-0420-45D4-9B0F-1A1BAC9E7B1D", + 276, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-22T00:00:00Z", + "02 16 18 40 42 33", + null + ], + [ + 277, + "30FAC46C-67D1-4517-B9C1-C45A66ECD4AD", + 277, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-26T00:00:00Z", + "13 26 39 41 42 10", + null + ], + [ + 278, + "085D6278-8169-45F2-8139-5AE139D49584", + 278, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-09-29T00:00:00Z", + "14 18 28 29 57 08", + null + ], + [ + 279, + "26ECC80A-B310-4A53-92CE-202F7B197214", + 279, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-03T00:00:00Z", + "17 23 36 55 59 10", + null + ], + [ + 280, + "914519F9-A8B7-434F-B0D4-907038C71E5A", + 280, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-06T00:00:00Z", + "15 26 34 36 59 35", + null + ], + [ + 281, + "6636BBF0-8EBC-418F-A550-FA95CACC0619", + 281, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-10T00:00:00Z", + "18 26 29 35 43 28", + null + ], + [ + 282, + "5365107E-2287-48CA-AD58-6C9A023C714C", + 282, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-13T00:00:00Z", + "02 05 25 26 49 18", + null + ], + [ + 283, + "E417DA4F-11BE-4903-ADAF-8FDD30355EF5", + 283, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-17T00:00:00Z", + "01 07 10 23 42 35", + null + ], + [ + 284, + "B4D90A89-0789-4D09-BDDC-03C9DF67DC6F", + 284, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-20T00:00:00Z", + "04 21 28 31 44 10", + null + ], + [ + 285, + "9BF840BF-31FE-4089-99F6-9A011979ABEE", + 285, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-24T00:00:00Z", + "03 18 21 23 50 04", + null + ], + [ + 286, + "B6575F0B-D385-47EA-9332-D106904A702A", + 286, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-27T00:00:00Z", + "22 32 34 36 56 33", + null + ], + [ + 287, + "57B7ED0C-5CC1-4081-9590-E199DF5FA176", + 287, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-10-31T00:00:00Z", + "01 27 31 45 48 05", + null + ], + [ + 288, + "C41607D3-580C-43BB-ADAD-9CC43C5819D0", + 288, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-03T00:00:00Z", + "04 07 09 30 54 25", + null + ], + [ + 289, + "00DF4287-E311-4041-803D-50CD8CF730F8", + 289, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-07T00:00:00Z", + "32 34 45 52 58 20", + null + ], + [ + 290, + "26EF36DB-6E16-4504-99D7-586EF63C5BFD", + 290, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-10T00:00:00Z", + "32 42 50 54 55 32", + null + ], + [ + 291, + "2DFD63FF-F496-4915-ADBE-CFC7B2F020E4", + 291, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-14T00:00:00Z", + "08 10 30 44 58 13", + null + ], + [ + 292, + "79A650AF-912E-4C50-A912-22D6CE48C74C", + 292, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-17T00:00:00Z", + "03 15 27 58 59 20", + null + ], + [ + 293, + "79919921-AEE6-48DF-9450-BB91C923FFB4", + 293, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-21T00:00:00Z", + "08 18 24 30 39 26", + null + ], + [ + 294, + "347CD937-33FD-40DF-B30A-2926AB462E46", + 294, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-24T00:00:00Z", + "22 32 37 44 50 34", + null + ], + [ + 295, + "42030C9D-944B-4CA6-ACF9-491121D867AC", + 295, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-11-28T00:00:00Z", + "05 16 22 23 29 06", + null + ], + [ + 296, + "1F2CCE2B-0EB4-4866-A863-4E0F6AF4C137", + 296, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-01T00:00:00Z", + "03 10 19 36 46 03", + null + ], + [ + 297, + "BAF2D745-7C18-4FFA-BDCE-9335B51B3044", + 297, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-05T00:00:00Z", + "13 17 19 27 38 12", + null + ], + [ + 298, + "2923720E-CC6D-4FA4-9D78-D0D1EA8EB401", + 298, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-08T00:00:00Z", + "07 23 26 40 53 21", + null + ], + [ + 299, + "08BF1FF1-5F06-47B9-BE7D-B256988D55E3", + 299, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-12T00:00:00Z", + "08 10 25 36 44 28", + null + ], + [ + 300, + "C471CB03-D137-4D02-A38B-17D3DD24AB61", + 300, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-15T00:00:00Z", + "15 23 40 44 55 14", + null + ], + [ + 301, + "8D72164F-DC14-4C2D-B905-2236F6D766A0", + 301, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-19T00:00:00Z", + "05 08 20 23 30 03", + null + ], + [ + 302, + "3751AF81-0687-4D2D-88E3-6394361D18E4", + 302, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-22T00:00:00Z", + "01 18 35 39 44 11", + null + ], + [ + 303, + "4E4D1611-40FC-4F76-8D11-814B0230E9E9", + 303, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-26T00:00:00Z", + "11 13 23 43 54 04", + null + ], + [ + 304, + "E8AD7A64-CBF3-41E0-8841-57A88A8A9CEA", + 304, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2012-12-29T00:00:00Z", + "36 46 50 52 55 14", + null + ], + [ + 305, + "EA310D55-EA1A-4AD5-AEC4-2D906D578237", + 305, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-02T00:00:00Z", + "18 20 28 35 53 20", + null + ], + [ + 306, + "5B6740CB-25FE-4096-952A-22B8FD71049F", + 306, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-05T00:00:00Z", + "26 30 49 51 54 25", + null + ], + [ + 307, + "2D2B2571-BCB7-43F9-903F-A95BC9352549", + 307, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-09T00:00:00Z", + "11 13 20 27 59 26", + null + ], + [ + 308, + "B6955E33-CFE9-470E-B016-CCA4037F7E8F", + 308, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-12T00:00:00Z", + "10 14 21 23 47 07", + null + ], + [ + 309, + "7D7ADFD8-0AD5-4D8D-BB5C-54B54BAB15F1", + 309, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-16T00:00:00Z", + "09 21 28 32 51 35", + null + ], + [ + 310, + "F135EEBF-2581-4D4B-B30D-405AC997C32F", + 310, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-19T00:00:00Z", + "08 28 29 34 38 35", + null + ], + [ + 311, + "9826E37F-19B7-499C-84FD-9FF396B106A4", + 311, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-23T00:00:00Z", + "11 12 24 43 45 09", + null + ], + [ + 312, + "397246CE-545F-4119-A29C-07BC53CFDA27", + 312, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-26T00:00:00Z", + "03 22 26 41 49 18", + null + ], + [ + 313, + "738F1EC3-A68F-437A-B9F8-A3E7DB8A259F", + 313, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-01-30T00:00:00Z", + "14 16 32 47 52 16", + null + ], + [ + 314, + "A1A3F5C7-97C7-4C9D-A694-2C0EE2A68760", + 314, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-02T00:00:00Z", + "11 16 33 40 41 34", + null + ], + [ + 315, + "333E4589-A54E-49D7-91D6-1FEC76CC953B", + 315, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-06T00:00:00Z", + "05 27 36 38 41 12", + null + ], + [ + 316, + "3FC6D439-3147-4484-8519-4440B8FE2A89", + 316, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-09T00:00:00Z", + "05 06 16 36 58 03", + null + ], + [ + 317, + "0C92A9B8-FEDC-40D7-A407-A791143CDDBE", + 317, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-13T00:00:00Z", + "12 23 25 27 43 29", + null + ], + [ + 318, + "BAEC5F53-D2F9-48B8-8FAF-84F32B265069", + 318, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-16T00:00:00Z", + "15 16 46 50 58 29", + null + ], + [ + 319, + "9DC15E1B-DDDC-4404-92CB-B5DE148175E0", + 319, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-20T00:00:00Z", + "03 17 19 25 32 17", + null + ], + [ + 320, + "508D9E18-9F15-4104-ABBD-86B5461522A7", + 320, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-23T00:00:00Z", + "02 05 31 39 41 29", + null + ], + [ + 321, + "46951F5E-AB70-43CF-A18F-8FAB450CBFC0", + 321, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-02-27T00:00:00Z", + "03 14 20 34 48 21", + null + ], + [ + 322, + "8AD80678-E48D-45AB-8DB9-E2389662D851", + 322, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-03-02T00:00:00Z", + "03 08 13 41 56 16", + null + ], + [ + 323, + "3422EF9A-9136-486B-8DBE-71ABA6D1996C", + 323, + 1362743858, + "706580", + 1362743858, + "706580", + "{\n}", + "2013-03-06T00:00:00Z", + "06 10 23 41 45 01", + null + ], + [ + 325, + "9860B5F7-D7E7-4DFF-B95D-34032B4BEDF8", + 325, + 1363349314, + "708543", + 1363349314, + "708543", + "{\n}", + "2013-03-09T00:00:00Z", + "10 37 40 46 52 12", + null + ], + [ + 326, + "0439154C-78D1-4996-8CAD-B1B954931675", + 326, + 1363349314, + "708543", + 1363349314, + "708543", + "{\n}", + "2013-03-13T00:00:00Z", + "05 09 28 32 38 29", + null + ], + [ + 328, + "FCF75212-D9E5-4AFF-87BC-66189B89CB98", + 328, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-03-16T00:00:00Z", + "03 07 21 44 53 16", + null + ], + [ + 329, + "48D32A7D-B346-4710-8BB8-42B2272FFC14", + 329, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-03-20T00:00:00Z", + "13 14 17 43 54 15", + null + ], + [ + 330, + "F5BE3238-68A7-4A8C-9965-AB377594A587", + 330, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-03-23T00:00:00Z", + "17 29 31 52 53 31", + null + ], + [ + 331, + "149CB1DF-EE7B-4E15-A8C8-5F1F0BFB48FC", + 331, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-03-27T00:00:00Z", + "07 37 43 48 52 16", + null + ], + [ + 332, + "4BD3AEAF-A4B7-41DB-80E3-29A84EBD1530", + 332, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-03-30T00:00:00Z", + "11 23 26 46 55 27", + null + ], + [ + 333, + "DC250164-F16B-448C-86BB-1552B8E73D78", + 333, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-04-03T00:00:00Z", + "01 06 08 12 35 03", + null + ], + [ + 334, + "BB9F041B-A32F-4CEB-AFEB-469174780DFA", + 334, + 1365512935, + "708543", + 1365512935, + "708543", + "{\n}", + "2013-04-06T00:00:00Z", + "04 07 08 29 39 24", + null + ], + [ + 336, + "D1BA6B1C-1971-4840-8744-146C6EA3CE93", + 336, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-04-10T00:00:00Z", + "01 36 40 52 53 20", + null + ], + [ + 337, + "D4C28FAA-6BF6-4DCD-9E92-A7CC09C7D397", + 337, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-04-13T00:00:00Z", + "10 12 31 56 57 33", + null + ], + [ + 338, + "0C60CBC5-7E4B-41EC-B5C2-0F22CB589A92", + 338, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-04-17T00:00:00Z", + "13 18 36 48 58 28", + null + ], + [ + 339, + "C8DC82C1-3976-4093-94F5-3951D031210C", + 339, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-04-20T00:00:00Z", + "06 08 30 39 48 20", + null + ], + [ + 340, + "072ED3B5-42D2-453F-866E-BA3719910A6C", + 340, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-04-24T00:00:00Z", + "09 19 31 56 59 02", + null + ], + [ + 341, + "41B7A123-CEDC-44E9-B022-C1BABEAAEC0F", + 341, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-04-27T00:00:00Z", + "03 23 48 54 55 05", + null + ], + [ + 342, + "EA1593AF-D20C-484F-B5FB-B12BE0C79F74", + 342, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-01T00:00:00Z", + "22 26 31 54 55 18", + null + ], + [ + 343, + "B7035D34-88EA-49E3-B987-9BAE3D16BE1A", + 343, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-04T00:00:00Z", + "07 12 26 36 40 17", + null + ], + [ + 344, + "31F614CE-1B8B-43F3-9365-925D7243374C", + 344, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-08T00:00:00Z", + "21 22 26 30 57 27", + null + ], + [ + 345, + "FAC6FECB-953A-4257-9AD0-6C4A35D5783E", + 345, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-11T00:00:00Z", + "06 13 19 23 43 16", + null + ], + [ + 346, + "AFE17066-CCB0-41AA-800C-4D02902505A5", + 346, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-15T00:00:00Z", + "02 11 26 34 41 32", + null + ], + [ + 347, + "E86DAD23-CDEE-4116-AD03-101D8C0296E5", + 347, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-18T00:00:00Z", + "10 13 14 22 52 11", + null + ], + [ + 348, + "F5D88A28-5B42-469C-BF81-FEA8E4C18C53", + 348, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-22T00:00:00Z", + "09 31 35 41 57 26", + null + ], + [ + 349, + "AF3B89F6-3B42-4947-B342-3723FCDE5308", + 349, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-25T00:00:00Z", + "02 06 19 21 27 25", + null + ], + [ + 350, + "AB777365-B121-43E3-A731-32EF418AE1C3", + 350, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-05-29T00:00:00Z", + "09 14 17 49 57 02", + null + ], + [ + 351, + "C903B823-813C-43E0-AF7E-74DE8E5561B6", + 351, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-01T00:00:00Z", + "22 28 33 53 59 14", + null + ], + [ + 352, + "80798224-1817-432D-89DB-DE18DFB1468E", + 352, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-05T00:00:00Z", + "04 26 33 36 55 32", + null + ], + [ + 353, + "859F250B-4CE8-40CD-85A4-2DC7CD13012A", + 353, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-08T00:00:00Z", + "02 11 22 26 32 19", + null + ], + [ + 354, + "837CB330-52CE-44F8-B889-32B6BAA00852", + 354, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-12T00:00:00Z", + "16 22 23 42 55 32", + null + ], + [ + 355, + "92C7D5C3-E3F8-4AFE-88D4-462D3BCE2272", + 355, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-15T00:00:00Z", + "28 36 40 48 55 01", + null + ], + [ + 356, + "FE49F2F1-95AC-4B43-8B2F-F07BDF89CEB3", + 356, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-19T00:00:00Z", + "07 46 47 52 57 17", + null + ], + [ + 357, + "5D40380C-DD65-4532-AC21-CF401894B317", + 357, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-22T00:00:00Z", + "13 19 23 33 57 28", + null + ], + [ + 358, + "0B2FCAF5-4E29-4F8F-9280-97BF0EC3D0BD", + 358, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-26T00:00:00Z", + "01 18 33 39 46 33", + null + ], + [ + 359, + "57D0A633-35B9-451E-9620-4E26808DE6A0", + 359, + 1373464425, + "708543", + 1373464425, + "708543", + "{\n}", + "2013-06-29T00:00:00Z", + "08 28 30 53 56 16", + null + ], + [ + 361, + "04AEA4EE-4D45-49C6-B20F-6A2B8F537C0F", + 361, + 1373960512, + "708543", + 1373960512, + "708543", + "{\n}", + "2013-07-03T00:00:00Z", + "03 06 29 40 51 04", + null + ], + [ + 362, + "978F0309-7452-430C-B61E-08844FEA7A48", + 362, + 1373960512, + "708543", + 1373960512, + "708543", + "{\n}", + "2013-07-06T00:00:00Z", + "02 13 35 36 52 11", + null + ], + [ + 363, + "063879CE-DB8E-461E-AE83-AF99A8E8DE11", + 363, + 1373960512, + "708543", + 1373960512, + "708543", + "{\n}", + "2013-07-10T00:00:00Z", + "30 31 45 55 59 27", + null + ], + [ + 365, + "F9F6AE36-65EB-4ED5-9C13-18CC98C7DA23", + 365, + 1375427681, + "708543", + 1375427681, + "708543", + "{\n}", + "2013-07-13T00:00:00Z", + "02 08 22 35 37 06", + null + ], + [ + 366, + "2DD53C13-565A-499E-99AB-73F43680F6A8", + 366, + 1375427681, + "708543", + 1375427681, + "708543", + "{\n}", + "2013-07-17T00:00:00Z", + "01 22 34 38 42 17", + null + ], + [ + 367, + "6752A041-C2DB-49F4-A8B4-FE9B4F32A190", + 367, + 1375427681, + "708543", + 1375427681, + "708543", + "{\n}", + "2013-07-20T00:00:00Z", + "14 25 27 38 58 06", + null + ], + [ + 368, + "9705E491-5DB5-4F82-8F41-E206CB414B29", + 368, + 1375427681, + "708543", + 1375427681, + "708543", + "{\n}", + "2013-07-24T00:00:00Z", + "09 29 40 44 54 07", + null + ], + [ + 369, + "51ED9563-D5E9-47A3-A39F-E32B58AB4BFE", + 369, + 1375427681, + "708543", + 1375427681, + "708543", + "{\n}", + "2013-07-27T00:00:00Z", + "09 23 40 53 58 06", + null + ], + [ + 370, + "48E88999-FBEB-4FDE-965C-BC6B7ABDC946", + 370, + 1375427681, + "708543", + 1375427681, + "708543", + "{\n}", + "2013-07-31T00:00:00Z", + "08 24 39 49 59 05", + null + ], + [ + 372, + "74E7FBC1-422D-4B2B-9B31-BE468A39AA04", + 372, + 1375712128, + "708543", + 1375712128, + "708543", + "{\n}", + "2013-08-03T00:00:00Z", + "21 24 36 42 45 15", + null + ], + [ + 374, + "CCB64CFF-4955-4BF4-88EB-CF475FDCBF6B", + 374, + 1376034828, + "708543", + 1376034828, + "708543", + "{\n}", + "2013-08-07T00:00:00Z", + "05 25 30 58 59 32", + null + ], + [ + 376, + "3A5B135F-7CF4-4F6C-AC7B-D9B87997C9F5", + 376, + 1376312350, + "708543", + 1376312350, + "708543", + "{\n}", + "2013-08-10T00:00:00Z", + "04 12 14 37 58 13", + null + ], + [ + 378, + "DB91BB61-FE4B-4AC7-B79B-CB62F5BFE967", + 378, + 1376636929, + "708543", + 1376636929, + "708543", + "{\n}", + "2013-08-14T00:00:00Z", + "04 11 17 43 51 20", + null + ], + [ + 380, + "35791B1C-33AB-472D-80D3-4CF9A6BE30EF", + 380, + 1376921117, + "708543", + 1376921117, + "708543", + "{\n}", + "2013-08-17T00:00:00Z", + "18 21 46 54 56 23", + null + ], + [ + 382, + "3DADF8FA-B273-422A-8DD2-E3DF108CCDCD", + 382, + 1377152900, + "708543", + 1377152900, + "708543", + "{\n}", + "2013-08-21T00:00:00Z", + "30 40 42 46 48 23", + null + ], + [ + 384, + "C61E59C5-F18C-45A7-A9F3-1D6B69C69312", + 384, + 1377508995, + "708543", + 1377508995, + "708543", + "{\n}", + "2013-08-24T00:00:00Z", + "12 17 25 45 59 19", + null + ], + [ + 386, + "E316A2A9-0932-4553-B9A2-3F4ED3AB256E", + 386, + 1377778238, + "708543", + 1377778238, + "708543", + "{\n}", + "2013-08-28T00:00:00Z", + "06 07 09 19 32 13", + null + ], + [ + 388, + "CBB2374D-6251-421E-AEAA-D57E0B1C98A1", + 388, + 1378004467, + "708543", + 1378004467, + "708543", + "{\n}", + "2013-08-31T00:00:00Z", + "02 07 25 40 56 20", + null + ], + [ + 390, + "B0677941-4C55-43C8-8994-5059357CF266", + 390, + 1378350069, + "708543", + 1378350069, + "708543", + "{\n}", + "2013-09-04T00:00:00Z", + "02 09 26 45 47 11", + null + ], + [ + 392, + "5270488F-C21B-4969-8E2A-C452EC7F052D", + 392, + 1378609358, + "708543", + 1378609358, + "708543", + "{\n}", + "2013-09-07T00:00:00Z", + "02 19 22 26 45 24", + null + ], + [ + 396, + "F3E5C8E3-49CC-4833-90B5-7A48A90BF043", + 396, + 1378954855, + "708543", + 1378954855, + "708543", + "{\n}", + "2013-09-11T00:00:00Z", + "11 19 33 42 52 33", + null + ], + [ + 398, + "3281F22C-24FC-47A0-B08B-C8F7C007EA64", + 398, + 1379214065, + "708543", + 1379214065, + "708543", + "{\n}", + "2013-09-14T00:00:00Z", + "01 17 25 37 44 20", + null + ], + [ + 400, + "03D572D2-4D3B-4576-A2C8-D09C7B640839", + 400, + 1379559676, + "708543", + 1379559676, + "708543", + "{\n}", + "2013-09-18T00:00:00Z", + "07 10 22 32 35 19", + null + ], + [ + 402, + "F0A0B8DD-B47E-4396-81C0-6ACED79548F2", + 402, + 1379818889, + "708543", + 1379818889, + "708543", + "{\n}", + "2013-09-21T00:00:00Z", + "12 17 45 54 58 13", + null + ], + [ + 404, + "AA19E8C5-B164-47E6-A4B2-11F301B635DF", + 404, + 1380164455, + "708543", + 1380164455, + "708543", + "{\n}", + "2013-09-25T00:00:00Z", + "02 07 17 49 53 23", + null + ], + [ + 406, + "5C8930B7-59A9-495E-9CD9-EDA4F114190C", + 406, + 1380423676, + "708543", + 1380423676, + "708543", + "{\n}", + "2013-09-28T00:00:00Z", + "14 47 52 53 54 05", + null + ], + [ + 408, + "AAB2E771-B827-45A1-8C4C-5FF4247E54A2", + 408, + 1380769256, + "708543", + 1380769256, + "708543", + "{\n}", + "2013-10-02T00:00:00Z", + "04 06 25 42 51 17", + null + ], + [ + 410, + "A11A6AD2-571D-4E68-9531-D7613C9AC5D4", + 410, + 1381028464, + "708543", + 1381028464, + "708543", + "{\n}", + "2013-10-05T00:00:00Z", + "11 12 17 39 40 05", + null + ], + [ + 412, + "BE0D91A1-302C-426D-A891-BCC716FF77F4", + 412, + 1381374055, + "708543", + 1381374055, + "708543", + "{\n}", + "2013-10-09T00:00:00Z", + "03 09 19 33 38 18", + null + ], + [ + 414, + "D088796F-DED4-4512-A6CD-965D62DFCD46", + 414, + 1381633254, + "708543", + 1381633254, + "708543", + "{\n}", + "2013-10-12T00:00:00Z", + "08 10 26 57 58 04", + null + ], + [ + 416, + "A1F81DDE-1222-482A-9797-99BDE4C680B7", + 416, + 1381978865, + "708543", + 1381978865, + "708543", + "{\n}", + "2013-10-16T00:00:00Z", + "03 26 28 34 42 28", + null + ], + [ + 418, + "B3EB04B8-0EB0-4863-A062-BDC74A5B55F8", + 418, + 1382238075, + "708543", + 1382238075, + "708543", + "{\n}", + "2013-10-19T00:00:00Z", + "09 33 54 56 57 05", + null + ], + [ + 420, + "81A24BED-C113-41DB-A8D7-BFA00A811E52", + 420, + 1382583677, + "708543", + 1382583677, + "708543", + "{\n}", + "2013-10-23T00:00:00Z", + "03 23 31 34 47 13", + null + ], + [ + 422, + "DA233102-CFC8-488A-9878-D4DA316E1FEE", + 422, + 1382842854, + "708543", + 1382842854, + "708543", + "{\n}", + "2013-10-26T00:00:00Z", + "04 06 34 49 56 29", + null + ], + [ + 424, + "BCD1777E-78BF-42AE-9F75-051E8AB6D526", + 424, + 1383188463, + "708543", + 1383188463, + "708543", + "{\n}", + "2013-10-30T00:00:00Z", + "02 36 40 49 54 10", + null + ], + [ + 426, + "3C980E92-DBA6-43EA-9C2F-6A357D8C198B", + 426, + 1383447654, + "708543", + 1383447654, + "708543", + "{\n}", + "2013-11-02T00:00:00Z", + "13 23 24 27 40 17", + null + ], + [ + 428, + "C6F8ACA9-A326-4CAF-9A5B-0D1848566D1A", + 428, + 1383793266, + "708543", + 1383793266, + "708543", + "{\n}", + "2013-11-06T00:00:00Z", + "01 05 10 15 49 22", + null + ], + [ + 430, + "A1AA1335-1304-41B6-9143-325B91A54538", + 430, + 1384052454, + "708543", + 1384052454, + "708543", + "{\n}", + "2013-11-09T00:00:00Z", + "03 09 37 49 56 32", + null + ], + [ + 432, + "875C9020-62D2-4C17-B5EE-E82B2ED215F0", + 432, + 1384398377, + "708543", + 1384398377, + "708543", + "{\n}", + "2013-11-13T00:00:00Z", + "05 31 50 55 56 09", + null + ], + [ + 434, + "A663C837-573A-4100-A04D-32D154358CEF", + 434, + 1384657257, + "708543", + 1384657257, + "708543", + "{\n}", + "2013-11-16T00:00:00Z", + "10 29 37 44 59 10", + null + ], + [ + 436, + "EF0B5D0B-6670-4ED1-BD05-7F753D7BD99E", + 436, + 1385002844, + "708543", + 1385002844, + "708543", + "{\n}", + "2013-11-20T00:00:00Z", + "04 18 23 32 45 07", + null + ], + [ + 438, + "6E46D30A-E623-4F9E-AE38-A28FF69C700D", + 438, + 1385262044, + "708543", + 1385262044, + "708543", + "{\n}", + "2013-11-23T00:00:00Z", + "05 12 43 52 55 10", + null + ], + [ + 440, + "84BFA534-38CC-4912-A4BE-6C5718E04989", + 440, + 1385607655, + "708543", + 1385607655, + "708543", + "{\n}", + "2013-11-27T00:00:00Z", + "18 25 50 55 57 17", + null + ], + [ + 442, + "4FDC7B73-BC13-4F98-9DD5-00B40EEF893A", + 442, + 1385866854, + "708543", + 1385866854, + "708543", + "{\n}", + "2013-11-30T00:00:00Z", + "05 26 44 45 57 29", + null + ], + [ + 444, + "325D02BB-4FC5-4A32-A398-3A68C9C2DB69", + 444, + 1386212457, + "708543", + 1386212457, + "708543", + "{\n}", + "2013-12-04T00:00:00Z", + "06 09 11 31 44 25", + null + ], + [ + 446, + "50AD8F90-A9BE-4390-8C78-FC00C4A81C76", + 446, + 1386471654, + "708543", + 1386471654, + "708543", + "{\n}", + "2013-12-07T00:00:00Z", + "13 20 32 45 48 17", + null + ], + [ + 448, + "CC93F4A9-00A4-4525-BC38-9DE756831B28", + 448, + 1386817266, + "708543", + 1386817266, + "708543", + "{\n}", + "2013-12-11T00:00:00Z", + "01 10 13 18 19 27", + null + ], + [ + 450, + "C003B8B1-CDB9-498C-9C7D-C4ECC78ED256", + 450, + 1387076495, + "708543", + 1387076495, + "708543", + "{\n}", + "2013-12-14T00:00:00Z", + "14 25 32 33 41 34", + null + ], + [ + 452, + "C538153A-1685-4B6C-9A6E-A08F40474590", + 452, + 1387422065, + "708543", + 1387422065, + "708543", + "{\n}", + "2013-12-18T00:00:00Z", + "07 24 37 39 40 01", + null + ], + [ + 454, + "393859FA-4F84-4694-9404-8373A0A70B92", + 454, + 1387724454, + "708543", + 1387724454, + "708543", + "{\n}", + "2013-12-21T00:00:00Z", + "25 36 40 45 51 08", + null + ], + [ + 456, + "DEA4DB56-E3E5-492D-8F26-8F121A050F39", + 456, + 1388026855, + "708543", + 1388026855, + "708543", + "{\n}", + "2013-12-25T00:00:00Z", + "23 28 38 39 56 32", + null + ], + [ + 458, + "2E898FF5-500D-46BB-B25E-715243B6D85F", + 458, + 1388286097, + "708543", + 1388286097, + "708543", + "{\n}", + "2013-12-28T00:00:00Z", + "08 35 44 51 56 18", + null + ], + [ + 460, + "869B299A-CB43-42BA-96B5-0C52C7B2948B", + 460, + 1388631654, + "708543", + 1388631654, + "708543", + "{\n}", + "2014-01-01T00:00:00Z", + "15 24 40 48 52 23", + null + ], + [ + 462, + "6992200D-6A41-45F0-B6CE-D0DBB8C067F3", + 462, + 1388890864, + "708543", + 1388890864, + "708543", + "{\n}", + "2014-01-04T00:00:00Z", + "19 20 37 41 58 14", + null + ], + [ + 464, + "CB8287E5-7897-4CFA-8EA7-364CDE173A5C", + 464, + 1389236455, + "708543", + 1389236455, + "708543", + "{\n}", + "2014-01-08T00:00:00Z", + "10 28 39 47 58 22", + null + ], + [ + 466, + "06973D85-FD1A-4DB3-95B0-56A307538275", + 466, + 1389495704, + "708543", + 1389495704, + "708543", + "{\n}", + "2014-01-11T00:00:00Z", + "10 15 33 48 54 34", + null + ], + [ + 468, + "8FD5794D-0FD0-4164-AB47-EA69A2726DA2", + 468, + 1389841276, + "708543", + 1389841276, + "708543", + "{\n}", + "2014-01-15T00:00:00Z", + "07 08 09 24 29 25", + null + ], + [ + 470, + "632FA9B1-6504-4745-A858-A4AD77142A73", + 470, + 1390100458, + "708543", + 1390100458, + "708543", + "{\n}", + "2014-01-18T00:00:00Z", + "13 14 19 31 38 25", + null + ], + [ + 472, + "6B5C814C-3778-4C08-A8E8-14A2690DB4E1", + 472, + 1390446076, + "708543", + 1390446076, + "708543", + "{\n}", + "2014-01-22T00:00:00Z", + "01 02 07 09 55 29", + "3" + ], + [ + 474, + "959EED5C-40DB-46A6-BA50-8C7F18F12B9B", + 474, + 1390705283, + "708543", + 1390705283, + "708543", + "{\n}", + "2014-01-25T00:00:00Z", + "08 12 18 55 57 02", + "2" + ], + [ + 476, + "CF00D567-AD20-4773-98F0-D6F59CEBEB0A", + 476, + 1391050868, + "708543", + 1391050868, + "708543", + "{\n}", + "2014-01-29T00:00:00Z", + "11 23 28 32 47 20", + "2" + ], + [ + 478, + "16039CD5-5D97-462D-80B9-C7E57C4219E1", + 478, + 1391310055, + "708543", + 1391310055, + "708543", + "{\n}", + "2014-02-01T00:00:00Z", + "05 12 15 27 38 07", + "2" + ], + [ + 480, + "7662D28E-81B6-4F64-9D1D-928B22ADAAD8", + 480, + 1391655655, + "708543", + 1391655655, + "708543", + "{\n}", + "2014-02-05T00:00:00Z", + "08 17 32 57 59 24", + "3" + ], + [ + 482, + "E2CD3E79-8E4D-49A1-AC4E-75678402B48D", + 482, + 1391914866, + "708543", + 1391914866, + "708543", + "{\n}", + "2014-02-08T00:00:00Z", + "24 25 34 37 54 29", + "2" + ], + [ + 484, + "3F39F11A-2E74-44CF-BDD9-7E456C37AC50", + 484, + 1392260446, + "708543", + 1392260446, + "708543", + "{\n}", + "2014-02-12T00:00:00Z", + "36 44 49 52 57 01", + "2" + ], + [ + 486, + "38A5578D-6E92-430E-9674-0255200D4928", + 486, + 1392519644, + "708543", + 1392519644, + "708543", + "{\n}", + "2014-02-15T00:00:00Z", + "02 09 14 21 23 03", + "3" + ], + [ + 488, + "5A0B4133-BE25-4EDE-9686-3F3939CE78B1", + 488, + 1392865281, + "708543", + 1392865281, + "708543", + "{\n}", + "2014-02-19T00:00:00Z", + "01 17 35 49 54 34", + "3" + ], + [ + 490, + "72286024-9A34-4F95-85BD-71C9ABFD2765", + 490, + 1393124475, + "708543", + 1393124475, + "708543", + "{\n}", + "2014-02-22T00:00:00Z", + "02 03 13 14 54 04", + "5" + ], + [ + 492, + "06333392-9CB1-4436-B6DB-E0A8A264B065", + 492, + 1393470054, + "708543", + 1393470054, + "708543", + "{\n}", + "2014-02-26T00:00:00Z", + "11 12 17 38 42 02", + "2" + ], + [ + 494, + "A96E282B-1D16-443C-9506-FE865E27E0BF", + 494, + 1393729254, + "708543", + 1393729254, + "708543", + "{\n}", + "2014-03-01T00:00:00Z", + "03 08 25 30 47 13", + "4" + ], + [ + 496, + "DF678B5A-F304-494C-AEC5-39922FA6FB03", + 496, + 1394074812, + "708543", + 1394074812, + "708543", + "{\n}", + "2014-03-05T00:00:00Z", + "03 07 09 26 54 19", + "2" + ], + [ + 498, + "B5F25102-9FFD-4696-B916-73870F17DFBA", + 498, + 1394334054, + "708543", + 1394334054, + "708543", + "{\n}", + "2014-03-08T00:00:00Z", + "10 14 24 32 41 30", + "2" + ], + [ + 500, + "C38A2D61-6CC5-430E-BB3A-37446F6C7263", + 500, + 1394679655, + "708543", + 1394679655, + "708543", + "{\n}", + "2014-03-12T00:00:00Z", + "14 15 28 37 54 10", + "2" + ], + [ + 502, + "079EA7C4-965C-4E3D-9836-9B92C6BE73E5", + 502, + 1394938854, + "708543", + 1394938854, + "708543", + "{\n}", + "2014-03-15T00:00:00Z", + "02 05 34 51 58 09", + "4" + ], + [ + 504, + "FD32D0FB-4D24-4317-B944-784A4EC18BF5", + 504, + 1395284455, + "708543", + 1395284455, + "708543", + "{\n}", + "2014-03-19T00:00:00Z", + "02 19 23 34 43 14", + "2" + ], + [ + 506, + "2B7067E1-A09E-48C4-9798-5A8FCF035ACE", + 506, + 1395543655, + "708543", + 1395543655, + "708543", + "{\n}", + "2014-03-22T00:00:00Z", + "13 28 31 55 58 15", + "2" + ], + [ + 508, + "30FF8647-C283-41A2-9DCC-A8D7384F1EB7", + 508, + 1395889255, + "708543", + 1395889255, + "708543", + "{\n}", + "2014-03-26T00:00:00Z", + "28 33 41 44 59 21", + "2" + ], + [ + 510, + "739C3709-5735-4AF0-A580-719A06580CCB", + 510, + 1396148444, + "708543", + 1396148444, + "708543", + "{\n}", + "2014-03-29T00:00:00Z", + "02 03 12 27 38 17", + "2" + ], + [ + 512, + "3CF1F0CA-F90D-48A7-96BB-FAD65E3CC086", + 512, + 1396494070, + "708543", + 1396494070, + "708543", + "{\n}", + "2014-04-02T00:00:00Z", + "08 13 19 22 53 24", + "2" + ], + [ + 514, + "9F59ED34-C239-4AE8-8678-09B3D2D039B1", + 514, + 1396753245, + "708543", + 1396753245, + "708543", + "{\n}", + "2014-04-05T00:00:00Z", + "11 21 26 33 34 29", + "5" + ], + [ + 516, + "6D64F1A9-4039-4193-A9D2-951048F7C1AC", + 516, + 1397098855, + "708543", + 1397098855, + "708543", + "{\n}", + "2014-04-09T00:00:00Z", + "09 14 44 48 49 29", + "2" + ], + [ + 518, + "C20FBD64-77FB-497C-86D6-9C66C29AA034", + 518, + 1397358054, + "708543", + 1397358054, + "708543", + "{\n}", + "2014-04-12T00:00:00Z", + "14 26 45 54 55 20", + "2" + ], + [ + 520, + "82F04093-BAEB-4764-9D9C-575EA9E17E3E", + 520, + 1397703676, + "708543", + 1397703676, + "708543", + "{\n}", + "2014-04-16T00:00:00Z", + "34 39 42 44 59 08", + "3" + ], + [ + 522, + "C0C4BB31-08F9-4FC8-8A5C-D3CD57B7A5C9", + 522, + 1397962855, + "708543", + 1397962855, + "708543", + "{\n}", + "2014-04-19T00:00:00Z", + "05 06 29 35 51 21", + "5" + ], + [ + 524, + "4AB21E57-4F08-48A7-BAAE-E39DE7770947", + 524, + 1398308454, + "708543", + 1398308454, + "708543", + "{\n}", + "2014-04-23T00:00:00Z", + "19 25 29 36 48 12", + "4" + ], + [ + 526, + "1B2FF91E-4DF8-45F7-9983-CCBF68599DD0", + 526, + 1398567654, + "708543", + 1398567654, + "708543", + "{\n}", + "2014-04-26T00:00:00Z", + "03 07 22 30 33 20", + "3" + ], + [ + 528, + "41BBC522-A603-4A2D-BFBD-F45B00F2D96A", + 528, + 1398913245, + "708543", + 1398913245, + "708543", + "{\n}", + "2014-04-30T00:00:00Z", + "02 09 11 19 50 32", + "3" + ], + [ + 530, + "487D1FF3-303E-4D43-BD9F-7FBCEEA53A78", + 530, + 1399172525, + "708543", + 1399172525, + "708543", + "{\n}", + "2014-05-03T00:00:00Z", + "05 15 16 46 49 26", + "4" + ], + [ + 532, + "C096BBA0-25ED-4CAF-9872-27CDF41C3AB2", + 532, + 1399518165, + "708543", + 1399518165, + "708543", + "{\n}", + "2014-05-07T00:00:00Z", + "17 29 31 48 49 34", + "2" + ], + [ + 534, + "5A46495E-2CB7-4C99-A3FF-6B829658680B", + 534, + 1399777318, + "708543", + 1399777318, + "708543", + "{\n}", + "2014-05-10T00:00:00Z", + "04 31 41 47 55 01", + "2" + ], + [ + 536, + "44B9F291-72B1-4456-B88A-AF46130AB86A", + 536, + 1400122951, + "708543", + 1400122951, + "708543", + "{\n}", + "2014-05-14T00:00:00Z", + "07 33 39 52 55 33", + "3" + ], + [ + 538, + "3BA9206D-AA33-4EED-8E23-3B022B7E06EC", + 538, + 1400382119, + "708543", + 1400382119, + "708543", + "{\n}", + "2014-05-17T00:00:00Z", + "23 32 39 47 49 22", + "3" + ], + [ + 540, + "10E769B9-E7B7-4048-9302-B596CD6278DD", + 540, + 1400727781, + "708543", + 1400727781, + "708543", + "{\n}", + "2014-05-21T00:00:00Z", + "04 20 34 39 58 31", + "5" + ], + [ + 542, + "1F143612-927F-4772-8B81-B62E2F26990C", + 542, + 1400986845, + "708543", + 1400986845, + "708543", + "{\n}", + "2014-05-24T00:00:00Z", + "15 16 28 49 55 18", + "2" + ], + [ + 544, + "75647DDC-DE92-4874-A22C-453F73FBC94F", + 544, + 1401332519, + "708543", + 1401332519, + "708543", + "{\n}", + "2014-05-28T00:00:00Z", + "02 24 28 32 59 25", + "3" + ], + [ + 546, + "07092E27-EB7F-4781-A41C-56FC4509332C", + 546, + 1401591729, + "708543", + 1401591729, + "708543", + "{\n}", + "2014-05-31T00:00:00Z", + "15 27 31 34 48 01", + "2" + ], + [ + 548, + "DBB2A4CA-C19A-4E21-9934-3774E0CCED88", + 548, + 1402024048, + "708543", + 1402024048, + "708543", + "{\n}", + "2014-06-04T00:00:00Z", + "01 07 10 22 49 24", + "3" + ], + [ + 550, + "D18F3C84-81FD-46FB-A1FC-16090A6305AC", + 550, + 1402196528, + "708543", + 1402196528, + "708543", + "{\n}", + "2014-06-07T00:00:00Z", + "28 30 35 58 59 15", + "2" + ], + [ + 552, + "3B509634-0F92-481A-8A92-B3DCD47BDB27", + 552, + 1402542055, + "708543", + 1402542055, + "708543", + "{\n}", + "2014-06-11T00:00:00Z", + "14 18 25 33 49 23", + "5" + ], + [ + 554, + "913D60FF-B8B0-400A-91CB-8C588A4D0BB3", + 554, + 1402844528, + "708543", + 1402844528, + "708543", + "{\n}", + "2014-06-14T00:00:00Z", + "09 33 42 45 54 30", + "3" + ], + [ + 556, + "54661135-06E8-401F-92FD-07186ACC9C1B", + 556, + 1403233446, + "708543", + 1403233446, + "708543", + "{\n}", + "2014-06-18T00:00:00Z", + "06 09 29 52 59 07", + "3" + ], + [ + 558, + "FD92596C-A65C-4C4D-B1BF-79E9E47619A9", + 558, + 1403406138, + "708543", + 1403406138, + "708543", + "{\n}", + "2014-06-21T00:00:00Z", + "05 06 37 41 54 26", + "3" + ], + [ + 560, + "4003D691-5309-4F30-B2B0-E19E03AAC642", + 560, + 1403751739, + "708543", + 1403751739, + "708543", + "{\n}", + "2014-06-25T00:00:00Z", + "10 20 25 50 53 35", + "4" + ], + [ + 562, + "52E50253-BF74-40B5-9581-682B443841D2", + 562, + 1404356454, + "708543", + 1404356454, + "708543", + "{\n}", + "2014-07-02T00:00:00Z", + "08 18 45 53 58 35", + "2" + ], + [ + 564, + "8CB66308-6F25-476F-95DE-A7C8E1D621CD", + 564, + 1404615645, + "708543", + 1404615645, + "708543", + "{\n}", + "2014-07-05T00:00:00Z", + "24 34 36 57 58 11", + "4" + ], + [ + 566, + "0D0AAA69-2F7A-4D5F-9DF3-C9701C7BAC22", + 566, + 1404961255, + "708543", + 1404961255, + "708543", + "{\n}", + "2014-07-09T00:00:00Z", + "09 25 42 55 57 14", + "2" + ], + [ + 568, + "55FE34B2-623D-4241-A89E-308A84B4C74B", + 568, + 1405220454, + "708543", + 1405220454, + "708543", + "{\n}", + "2014-07-12T00:00:00Z", + "02 03 07 23 51 26", + "2" + ], + [ + 570, + "FCFDF56B-4E14-49E5-867F-C2E4AB445A9F", + 570, + 1405582531, + "708543", + 1405582531, + "708543", + "{\n}", + "2014-07-16T00:00:00Z", + "05 15 18 26 32 35", + "3" + ], + [ + 572, + "1716855F-F638-4C7E-8B8D-8EF7F73B5B06", + 572, + 1405825244, + "708543", + 1405825244, + "708543", + "{\n}", + "2014-07-19T00:00:00Z", + "10 17 25 45 53 09", + "2" + ], + [ + 574, + "7D6898C6-01D5-4782-95BA-C2749ADFE9BC", + 574, + 1406170855, + "708543", + 1406170855, + "708543", + "{\n}", + "2014-07-23T00:00:00Z", + "04 10 12 22 31 03", + "5" + ], + [ + 576, + "D62285D6-7C01-4C90-B7A9-C4D14752E119", + 576, + 1406430095, + "708543", + 1406430095, + "708543", + "{\n}", + "2014-07-26T00:00:00Z", + "24 28 30 38 39 16", + "2" + ], + [ + 578, + "394E9921-468B-4E29-B772-59A0C54F5492", + 578, + 1406775657, + "708543", + 1406775657, + "708543", + "{\n}", + "2014-07-30T00:00:00Z", + "13 30 42 49 53 29", + "3" + ], + [ + 580, + "284B0E05-5283-488D-AFE0-5B256E9D81C0", + 580, + 1407034866, + "708543", + 1407034866, + "708543", + "{\n}", + "2014-08-02T00:00:00Z", + "12 26 44 46 47 29", + "2" + ], + [ + 582, + "62B6DC77-A166-4553-8D32-8A8F7840EC9F", + 582, + 1407380456, + "708543", + 1407380456, + "708543", + "{\n}", + "2014-08-06T00:00:00Z", + "01 08 24 28 49 24", + "5" + ], + [ + 584, + "B5ACA65E-F5FE-4764-8138-2C700D050E05", + 584, + 1407639655, + "708543", + 1407639655, + "708543", + "{\n}", + "2014-08-09T00:00:00Z", + "03 12 31 34 51 24", + "2" + ], + [ + 586, + "FB356DBD-E3D3-465F-8A17-C7465009E078", + 586, + 1407985265, + "708543", + 1407985265, + "708543", + "{\n}", + "2014-08-13T00:00:00Z", + "08 37 39 40 52 24", + "2" + ], + [ + 588, + "1AADCEC8-EF2A-47A0-9508-69E2D0A25C21", + 588, + 1408244445, + "708543", + 1408244445, + "708543", + "{\n}", + "2014-08-16T00:00:00Z", + "07 08 17 48 59 09", + "2" + ], + [ + 590, + "ADB2B268-7B1F-4A3C-B252-DF4298ED22F6", + 590, + 1408590066, + "708543", + 1408590066, + "708543", + "{\n}", + "2014-08-20T00:00:00Z", + "04 08 21 38 40 03", + "2" + ], + [ + 592, + "F1DB5012-8A45-4E79-B123-79C3F17AE2DA", + 592, + 1408849266, + "708543", + 1408849266, + "708543", + "{\n}", + "2014-08-23T00:00:00Z", + "28 32 35 36 52 31", + "3" + ], + [ + 594, + "B33326D6-1FA2-4719-9888-9C6E88EBFFEA", + 594, + 1409194865, + "708543", + 1409194865, + "708543", + "{\n}", + "2014-08-27T00:00:00Z", + "17 24 26 45 46 19", + "3" + ], + [ + 596, + "4A22925B-EB06-46B1-BB68-407C5E31D5E7", + 596, + 1409454066, + "708543", + 1409454066, + "708543", + "{\n}", + "2014-08-30T00:00:00Z", + "05 28 31 52 59 27", + "2" + ], + [ + 598, + "7858F42B-EB4E-408A-A84B-5AEBA66AA3DF", + 598, + 1409886079, + "708543", + 1409886079, + "708543", + "{\n}", + "2014-09-03T00:00:00Z", + "02 16 43 45 51 35", + "3" + ], + [ + 600, + "97430822-1C96-46B9-92BF-86AB1BA10905", + 600, + 1410058856, + "708543", + 1410058856, + "708543", + "{\n}", + "2014-09-06T00:00:00Z", + "09 29 31 43 50 18", + "2" + ], + [ + 602, + "CABB0AFD-C37C-4E49-B8C6-7D5F86DCE1A7", + 602, + 1410404493, + "708543", + 1410404493, + "708543", + "{\n}", + "2014-09-10T00:00:00Z", + "02 14 39 40 43 13", + "5" + ], + [ + 604, + "D1EB641C-B9E7-4958-BFA3-6A6E353EA51A", + 604, + 1410857379, + "708543", + 1410857379, + "708543", + "{\n}", + "2014-09-13T00:00:00Z", + "01 06 16 37 53 27", + "3" + ], + [ + 606, + "68358BCC-7ACC-4505-91BA-33741DE045AA", + 606, + 1411009291, + "708543", + 1411009291, + "708543", + "{\n}", + "2014-09-17T00:00:00Z", + "18 25 36 48 50 23", + "2" + ], + [ + 608, + "58DCE448-E60B-4D6A-A67C-0B31304E01D4", + 608, + 1411484653, + "708543", + 1411484653, + "708543", + "{\n}", + "2014-09-20T00:00:00Z", + "22 23 30 37 39 16", + "4" + ], + [ + 610, + "A125446B-3200-4E26-8E30-D3E0D11AEEA8", + 610, + 1411741517, + "708543", + 1411741517, + "708543", + "{\n}", + "2014-09-24T00:00:00Z", + "07 14 21 24 41 26", + "4" + ], + [ + 612, + "44FDD0E0-D854-4CBB-A674-4E748BB851E6", + 612, + 1411873297, + "708543", + 1411873297, + "708543", + "{\n}", + "2014-09-27T00:00:00Z", + "02 11 35 52 54 13", + "3" + ], + [ + 614, + "833921F3-DA63-4F64-8435-FE0FF6907174", + 614, + 1412218893, + "708543", + 1412218893, + "708543", + "{\n}", + "2014-10-01T00:00:00Z", + "01 04 18 20 45 07", + "2" + ], + [ + 616, + "EE6B6F59-37D7-45CC-BE81-AA2F1F308F2C", + 616, + 1412521327, + "708543", + 1412521327, + "708543", + "{\n}", + "2014-10-04T00:00:00Z", + "13 18 24 25 33 31", + "2" + ], + [ + 618, + "F8E7AC21-2BDD-4DEE-97A9-7228CF621E0A", + 618, + 1412823672, + "708543", + 1412823672, + "708543", + "{\n}", + "2014-10-08T00:00:00Z", + "05 16 31 46 50 18", + "3" + ], + [ + 620, + "E8BE2206-8EF5-4CBA-BC14-97458F655875", + 620, + 1413082889, + "708543", + 1413082889, + "708543", + "{\n}", + "2014-10-11T00:00:00Z", + "10 19 37 38 39 28", + "2" + ], + [ + 622, + "36FCC416-19AC-49D7-A6A5-6F2B02B14037", + 622, + 1413428491, + "708543", + 1413428491, + "708543", + "{\n}", + "2014-10-15T00:00:00Z", + "05 07 19 27 28 20", + "2" + ], + [ + 624, + "4DB598EB-4512-4085-AB52-B31451700CE4", + 624, + 1413687689, + "708543", + 1413687689, + "708543", + "{\n}", + "2014-10-18T00:00:00Z", + "20 26 27 36 54 19", + "2" + ], + [ + 626, + "D8A3E583-5FAB-4687-9C12-DF66BC25D1A1", + 626, + 1414033290, + "708543", + 1414033290, + "708543", + "{\n}", + "2014-10-22T00:00:00Z", + "29 30 40 42 50 16", + "2" + ], + [ + 628, + "94A238A4-0D81-4904-93F0-94206E2A507D", + 628, + 1414292491, + "708543", + 1414292491, + "708543", + "{\n}", + "2014-10-25T00:00:00Z", + "06 10 51 54 57 12", + "2" + ], + [ + 630, + "6A101A82-36BA-47CD-965F-CD0E9DC46DA1", + 630, + 1414638069, + "708543", + 1414638069, + "708543", + "{\n}", + "2014-10-29T00:00:00Z", + "25 28 48 57 59 16", + "3" + ], + [ + 632, + "C216F750-2E31-4F60-9188-F2412BF65C5C", + 632, + 1414897288, + "708543", + 1414897288, + "708543", + "{\n}", + "2014-11-01T00:00:00Z", + "01 03 13 25 38 17", + "2" + ], + [ + 634, + "C2DD204C-8C36-4F3A-826C-93A4B5FDA4B9", + 634, + 1415329396, + "708543", + 1415329396, + "708543", + "{\n}", + "2014-11-05T00:00:00Z", + "02 11 19 21 42 34", + "3" + ], + [ + 636, + "10664F33-06F4-44A8-ACFC-B4577D5EC5EA", + 636, + 1415502092, + "708543", + 1415502092, + "708543", + "{\n}", + "2014-11-08T00:00:00Z", + "09 19 33 38 54 15", + "3" + ], + [ + 638, + "412214CC-C4CC-4993-AA11-7F6FAE4060AF", + 638, + 1415847687, + "708543", + 1415847687, + "708543", + "{\n}", + "2014-11-12T00:00:00Z", + "37 39 51 52 55 11", + "3" + ], + [ + 640, + "8590E6C5-15BF-42B1-A4F6-6C15C6C21B8B", + 640, + 1416193376, + "708543", + 1416193376, + "708543", + "{\n}", + "2014-11-15T00:00:00Z", + "13 16 33 35 51 28", + "2" + ], + [ + 642, + "A8BAE147-EA3C-4252-ABE0-06641E9414C2", + 642, + 1416452533, + "708543", + 1416452533, + "708543", + "{\n}", + "2014-11-19T00:00:00Z", + "06 36 38 48 51 17", + "2" + ], + [ + 644, + "8856B080-2BF0-4C94-919F-CAD7D14D394B", + 644, + 1416711688, + "708543", + 1416711688, + "708543", + "{\n}", + "2014-11-22T00:00:00Z", + "23 49 53 54 57 35", + "2" + ], + [ + 646, + "EDE28D34-E74E-4EB6-AA31-B7E291380862", + 646, + 1417057290, + "708543", + 1417057290, + "708543", + "{\n}", + "2014-11-26T00:00:00Z", + "16 17 22 46 54 35", + "5" + ], + [ + 648, + "492FE8DB-DF45-46CC-98A2-75020B7AE310", + 648, + 1417316490, + "708543", + 1417316490, + "708543", + "{\n}", + "2014-11-29T00:00:00Z", + "13 24 30 42 48 27", + "2" + ], + [ + 650, + "8A284F29-40F3-4934-80C2-DEC138E688C4", + 650, + 1417662093, + "708543", + 1417662093, + "708543", + "{\n}", + "2014-12-03T00:00:00Z", + "25 30 32 46 54 26", + "3" + ], + [ + 652, + "6B8C9416-B679-4062-AE0E-2F5D4DE63AAB", + 652, + 1417921272, + "708543", + 1417921272, + "708543", + "{\n}", + "2014-12-06T00:00:00Z", + "12 15 22 43 49 14", + "2" + ], + [ + 654, + "B5E65633-5DC5-41A9-A777-47BF48B5694F", + 654, + 1418266870, + "708543", + 1418266870, + "708543", + "{\n}", + "2014-12-10T00:00:00Z", + "34 44 48 54 55 10", + "2" + ], + [ + 656, + "2078DFB3-E426-458F-B76C-8CF659E96CDD", + 656, + 1418526094, + "708543", + 1418526094, + "708543", + "{\n}", + "2014-12-13T00:00:00Z", + "05 13 28 43 55 33", + "3" + ], + [ + 658, + "576E343A-594A-49F4-BAF2-320389AED2C8", + 658, + 1418871699, + "708543", + 1418871699, + "708543", + "{\n}", + "2014-12-17T00:00:00Z", + "22 31 38 47 48 15", + "3" + ], + [ + 660, + "C5AF5FF2-DA14-4056-865F-7C7F55E705CB", + 660, + 1419130892, + "708543", + 1419130892, + "708543", + "{\n}", + "2014-12-20T00:00:00Z", + "14 15 19 31 56 05", + "5" + ], + [ + 662, + "5E6A6652-C161-4DA4-9D8E-1791C9D0DDA5", + 662, + 1419476499, + "708543", + 1419476499, + "708543", + "{\n}", + "2014-12-24T00:00:00Z", + "11 12 46 47 50 22", + "4" + ], + [ + 664, + "A973E6CD-C592-490A-A8B9-99597CFB0166", + 664, + 1419735679, + "708543", + 1419735679, + "708543", + "{\n}", + "2014-12-27T00:00:00Z", + "07 10 11 14 36 15", + "2" + ], + [ + 666, + "852D9F3D-2D01-456C-97B3-323697723F5F", + 666, + 1420081293, + "708543", + 1420081293, + "708543", + "{\n}", + "2014-12-31T00:00:00Z", + "17 27 37 40 53 35", + "2" + ], + [ + 668, + "3F7A2659-CCCC-4C35-BD86-0E3C025C9311", + 668, + 1420340499, + "708543", + 1420340499, + "708543", + "{\n}", + "2015-01-03T00:00:00Z", + "04 18 43 46 55 25", + "3" + ], + [ + 670, + "434CE58A-723C-4C47-9D33-67064A0081B4", + 670, + 1420686097, + "708543", + 1420686097, + "708543", + "{\n}", + "2015-01-07T00:00:00Z", + "14 15 47 49 59 10", + "2" + ], + [ + 672, + "C9C20E1B-B660-43F9-80EE-BFA56EB5ADFF", + 672, + 1420945292, + "708543", + 1420945292, + "708543", + "{\n}", + "2015-01-10T00:00:00Z", + "02 09 19 28 29 19", + "5" + ], + [ + 674, + "60D4CBA8-C33C-4F8D-9A5F-A091A06EEE39", + 674, + 1421290892, + "708543", + 1421290892, + "708543", + "{\n}", + "2015-01-14T00:00:00Z", + "02 04 10 41 53 22", + "5" + ], + [ + 676, + "96C3084D-A699-477E-940E-7540D2E079DD", + 676, + 1421550089, + "708543", + 1421550089, + "708543", + "{\n}", + "2015-01-17T00:00:00Z", + "15 16 23 27 36 09", + "2" + ], + [ + 678, + "64D16892-1A8F-4BD3-AD08-0F12AF37DC5B", + 678, + 1421895752, + "708543", + 1421895752, + "708543", + "{\n}", + "2015-01-21T00:00:00Z", + "11 12 15 28 57 23", + "4" + ], + [ + 680, + "9B98D299-2E89-45CC-9C20-CA9A9858401C", + 680, + 1422154888, + "708543", + 1422154888, + "708543", + "{\n}", + "2015-01-24T00:00:00Z", + "16 19 20 29 33 10", + "2" + ], + [ + 682, + "C8B9F03E-D092-4B68-A882-060CC9A3D5A4", + 682, + 1422500493, + "708543", + 1422500493, + "708543", + "{\n}", + "2015-01-28T00:00:00Z", + "12 24 35 36 49 01", + "5" + ], + [ + 684, + "2031E7C9-B0FA-43E5-A952-25686F49FE00", + 684, + 1422759691, + "708543", + 1422759691, + "708543", + "{\n}", + "2015-01-31T00:00:00Z", + "05 11 16 26 50 34", + "2" + ], + [ + 686, + "B7216262-139E-4F1A-BA84-5DB845271DAE", + 686, + 1423105293, + "708543", + 1423105293, + "708543", + "{\n}", + "2015-02-04T00:00:00Z", + "24 36 51 52 56 22", + "2" + ], + [ + 688, + "08D2F580-1207-45F6-A29F-7FE66620CD90", + 688, + 1423364488, + "708543", + 1423364488, + "708543", + "{\n}", + "2015-02-07T00:00:00Z", + "05 10 21 34 58 33", + "5" + ], + [ + 690, + "DDF1543E-9A9B-4ACE-BAFE-8AB37973E90C", + 690, + 1423710069, + "708543", + 1423710069, + "708543", + "{\n}", + "2015-02-11T00:00:00Z", + "11 13 25 39 54 19", + "3" + ], + [ + 692, + "435F62B2-DF03-4FB8-A8B8-52E5A75666D3", + 692, + 1423969290, + "708543", + 1423969290, + "708543", + "{\n}", + "2015-02-14T00:00:00Z", + "01 24 44 45 51 28", + "2" + ], + [ + 694, + "3156E6C0-2C89-45D1-9CD4-26C73005A7B3", + 694, + 1424314889, + "708543", + 1424314889, + "708543", + "{\n}", + "2015-02-18T00:00:00Z", + "01 09 29 32 49 22", + "2" + ], + [ + 696, + "78AFD76F-A532-4015-821A-A6052893850A", + 696, + 1424574090, + "708543", + 1424574090, + "708543", + "{\n}", + "2015-02-21T00:00:00Z", + "10 14 18 34 51 26", + "2" + ], + [ + 698, + "1958CB7F-4F9B-461B-9304-89D6C516BF36", + 698, + 1424919689, + "708543", + 1424919689, + "708543", + "{\n}", + "2015-02-25T00:00:00Z", + "17 19 21 32 39 08", + "3" + ], + [ + 700, + "EDCD1F4D-DF40-4372-A354-00A3F20BA52E", + 700, + 1425178891, + "708543", + 1425178891, + "708543", + "{\n}", + "2015-02-28T00:00:00Z", + "11 17 25 28 46 12", + "2" + ], + [ + 702, + "F1546B7C-472E-4965-8CF5-A60A2F488AEE", + 702, + 1425524491, + "708543", + 1425524491, + "708543", + "{\n}", + "2015-03-04T00:00:00Z", + "08 12 15 35 50 32", + "2" + ], + [ + 704, + "B79C61A2-F6BE-45C7-A8E2-AF96CAF6BCA8", + 704, + 1425783779, + "708543", + 1425783779, + "708543", + "{\n}", + "2015-03-07T00:00:00Z", + "34 36 38 42 50 33", + "4" + ], + [ + 706, + "65C41C93-2669-45C8-BF86-9583480708E0", + 706, + 1426129290, + "708543", + 1426129290, + "708543", + "{\n}", + "2015-03-11T00:00:00Z", + "11 24 31 40 44 27", + "2" + ], + [ + 708, + "21E7CFAA-5C8C-4714-B690-23C86D9DD12F", + 708, + 1426388488, + "708543", + 1426388488, + "708543", + "{\n}", + "2015-03-14T00:00:00Z", + "08 14 39 46 47 18", + "2" + ], + [ + 710, + "82F2F807-EC9F-42E1-B804-AEEABBC72D9E", + 710, + 1426734087, + "708543", + 1426734087, + "708543", + "{\n}", + "2015-03-18T00:00:00Z", + "14 25 30 33 47 08", + "2" + ], + [ + 712, + "47FE9CA5-F869-4345-A69D-5E941CF5FFBB", + 712, + 1426993286, + "708543", + 1426993286, + "708543", + "{\n}", + "2015-03-21T00:00:00Z", + "11 16 30 38 42 07", + "4" + ], + [ + 714, + "54EE26F7-D934-48B1-8BA1-B3285B3FBC19", + 714, + 1427338886, + "708543", + 1427338886, + "708543", + "{\n}", + "2015-03-25T00:00:00Z", + "07 19 23 50 54 14", + "2" + ], + [ + 716, + "9934E265-895E-421B-8ACC-BDE393F70FF3", + 716, + 1427598086, + "708543", + 1427598086, + "708543", + "{\n}", + "2015-03-28T00:00:00Z", + "02 04 06 12 38 17", + "3" + ], + [ + 718, + "36663E0C-0277-4255-B11C-2F697A9B8525", + 718, + 1427943687, + "708543", + 1427943687, + "708543", + "{\n}", + "2015-04-01T00:00:00Z", + "02 30 33 39 44 01", + "3" + ], + [ + 720, + "C0E1AACD-A900-4A28-AA88-B712DB48FCC0", + 720, + 1428202890, + "708543", + 1428202890, + "708543", + "{\n}", + "2015-04-04T00:00:00Z", + "33 39 40 41 54 28", + "3" + ], + [ + 722, + "92E8465A-5CDF-4BED-83FA-7BD027280751", + 722, + 1428548489, + "708543", + 1428548489, + "708543", + "{\n}", + "2015-04-08T00:00:00Z", + "01 19 45 46 58 29", + "2" + ], + [ + 724, + "E6490D86-EF2D-4C79-A2E1-DCD02F7215BF", + 724, + 1428807687, + "708543", + 1428807687, + "708543", + "{\n}", + "2015-04-11T00:00:00Z", + "01 12 32 42 58 12", + "2" + ], + [ + 726, + "02CAC888-050D-48A5-868C-B37CC88EEC42", + 726, + 1429153308, + "708543", + 1429153308, + "708543", + "{\n}", + "2015-04-15T00:00:00Z", + "01 16 21 29 40 30", + "3" + ], + [ + 728, + "81E5718B-6F5D-49A2-B3A6-E8C5A8C49458", + 728, + 1429412486, + "708543", + 1429412486, + "708543", + "{\n}", + "2015-04-18T00:00:00Z", + "13 22 23 29 31 17", + "3" + ], + [ + 730, + "4ED36D51-0CD1-403B-BF6F-474E76D12866", + 730, + 1429758092, + "708543", + 1429758092, + "708543", + "{\n}", + "2015-04-22T00:00:00Z", + "10 14 25 39 53 18", + "2" + ], + [ + 732, + "1E602E88-5A04-4E97-81F4-1AC8E0F65593", + 732, + 1430017289, + "708543", + 1430017289, + "708543", + "{\n}", + "2015-04-25T00:00:00Z", + "21 33 35 38 45 12", + "2" + ], + [ + 734, + "7E163D25-1D6C-41EC-98F3-FCB6323BBE21", + 734, + 1430362890, + "708543", + 1430362890, + "708543", + "{\n}", + "2015-04-29T00:00:00Z", + "01 26 34 38 51 06", + "3" + ], + [ + 736, + "6AE4172D-2045-4718-875A-B5FF15FF15D7", + 736, + 1430622097, + "708543", + 1430622097, + "708543", + "{\n}", + "2015-05-02T00:00:00Z", + "02 06 11 30 31 33", + "3" + ], + [ + 738, + "C36A8A54-82C5-48FE-AA7E-570DB8ED39AD", + 738, + 1430967717, + "708543", + 1430967717, + "708543", + "{\n}", + "2015-05-06T00:00:00Z", + "23 24 27 39 41 30", + "5" + ], + [ + 740, + "3CF64B67-5986-4A6E-86D2-3D3A75006C2D", + 740, + 1431226891, + "708543", + 1431226891, + "708543", + "{\n}", + "2015-05-09T00:00:00Z", + "04 15 17 35 58 17", + "3" + ], + [ + 742, + "21A93C94-A9CF-4C66-8752-DB70A3C877E9", + 742, + 1431572489, + "708543", + 1431572489, + "708543", + "{\n}", + "2015-05-13T00:00:00Z", + "01 25 29 31 47 07", + "3" + ], + [ + 744, + "852204B9-3070-4BB2-93D6-89525B2A6A88", + 744, + 1431831689, + "708543", + 1431831689, + "708543", + "{\n}", + "2015-05-16T00:00:00Z", + "24 29 38 48 52 32", + "2" + ], + [ + 746, + "C58E93C9-ED63-4A6B-8E70-DB0E572779DF", + 746, + 1432177299, + "708543", + 1432177299, + "708543", + "{\n}", + "2015-05-20T00:00:00Z", + "01 12 28 35 44 25", + "3" + ], + [ + 748, + "4BA1309D-2E3A-47C7-BCB0-D5E8AACF8A23", + 748, + 1432436488, + "708543", + 1432436488, + "708543", + "{\n}", + "2015-05-23T00:00:00Z", + "09 15 17 31 43 16", + "4" + ], + [ + 750, + "1BFBA543-A31E-4A61-9EE2-842B252E1A49", + 750, + 1432782091, + "708543", + 1432782091, + "708543", + "{\n}", + "2015-05-27T00:00:00Z", + "08 15 34 53 59 23", + "2" + ], + [ + 752, + "A176D8B7-2B06-4638-B917-DFF229554FC5", + 752, + 1433041293, + "708543", + 1433041293, + "708543", + "{\n}", + "2015-05-30T00:00:00Z", + "08 09 25 56 57 22", + "2" + ], + [ + 754, + "9B16EFF0-1C1A-43E1-89D0-0A138591BF89", + 754, + 1433386892, + "708543", + 1433386892, + "708543", + "{\n}", + "2015-06-03T00:00:00Z", + "06 08 13 37 40 11", + "2" + ], + [ + 756, + "D2B7FDF6-0C3C-4BA6-8AE3-3EDD2D3554B9", + 756, + 1433646129, + "708543", + 1433646129, + "708543", + "{\n}", + "2015-06-06T00:00:00Z", + "08 13 18 27 43 15", + "4" + ], + [ + 758, + "7535E4D2-583F-4096-8C62-BF639B1F0C4F", + 758, + 1433991688, + "708543", + 1433991688, + "708543", + "{\n}", + "2015-06-10T00:00:00Z", + "31 32 48 49 53 25", + "2" + ], + [ + 760, + "87226083-EDDC-40D5-AC6E-2E17E8F7DAF1", + 760, + 1434250895, + "708543", + 1434250895, + "708543", + "{\n}", + "2015-06-13T00:00:00Z", + "29 41 48 52 54 29", + "2" + ], + [ + 762, + "D9A556D7-FAF0-4451-A6D9-8E7ABAAF75F1", + 762, + 1434596511, + "708543", + 1434596511, + "708543", + "{\n}", + "2015-06-17T00:00:00Z", + "20 21 22 41 54 07", + "3" + ], + [ + 764, + "0B4B4E43-2914-4252-9B4D-445656DD001E", + 764, + 1434855712, + "708543", + 1434855712, + "708543", + "{\n}", + "2015-06-20T00:00:00Z", + "09 10 16 20 57 15", + "2" + ], + [ + 766, + "402F6B05-3B40-4839-B20E-4C86605592EA", + 766, + 1435201309, + "708543", + 1435201309, + "708543", + "{\n}", + "2015-06-24T00:00:00Z", + "03 05 10 22 32 07", + "4" + ], + [ + 768, + "85C14851-24B0-4482-8610-DB5318822E47", + 768, + 1435460508, + "708543", + 1435460508, + "708543", + "{\n}", + "2015-06-27T00:00:00Z", + "18 28 35 46 49 27", + "5" + ], + [ + 770, + "F917646C-C9E4-4DD0-9705-1AE52C0DBEE2", + 770, + 1435806142, + "708543", + 1435806142, + "708543", + "{\n}", + "2015-07-01T00:00:00Z", + "07 24 26 31 41 25", + "2" + ], + [ + 772, + "F39FD4CD-D959-462E-B398-9A813FA9128A", + 772, + 1436065288, + "708543", + 1436065288, + "708543", + "{\n}", + "2015-07-04T00:00:00Z", + "03 06 14 18 24 21", + "3" + ], + [ + 774, + "53124F7D-90C3-4B9D-B7BB-A5DD90478C00", + 774, + 1436410928, + "708543", + 1436410928, + "708543", + "{\n}", + "2015-07-08T00:00:00Z", + "04 15 25 27 30 18", + "3" + ], + [ + 776, + "3B86E5CC-7CFA-4329-A914-E0BCBA3B017F", + 776, + 1436670069, + "708543", + 1436670069, + "708543", + null, + "2015-07-11T00:00:00Z", + "11 39 46 52 54 03", + "2" + ], + [ + 777, + "4D234C5C-F376-4344-BD6D-A5770CD56A1F", + 777, + 1437015729, + "708543", + 1437015729, + "708543", + null, + "2015-07-15T00:00:00Z", + "13 16 34 45 50 11", + "2" + ], + [ + 778, + "24EE016C-7F9D-4E0D-AA08-C4AF54E66F11", + 778, + 1437274885, + "708543", + 1437274885, + "708543", + null, + "2015-07-18T00:00:00Z", + "06 37 39 45 55 33", + "3" + ], + [ + 779, + "C9C2B6CC-06CB-4F01-9281-7E4A8C43FB8E", + 779, + 1437620486, + "708543", + 1437620486, + "708543", + null, + "2015-07-22T00:00:00Z", + "12 31 43 44 57 11", + "2" + ], + [ + 780, + "CC90B341-400A-4806-BBAF-E8E327598BD2", + 780, + 1437879687, + "708543", + 1437879687, + "708543", + null, + "2015-07-25T00:00:00Z", + "27 29 34 41 44 02", + "3" + ], + [ + 781, + "E512BA46-7C58-41C7-9DBD-2457E9029D67", + 781, + 1438225285, + "708543", + 1438225285, + "708543", + null, + "2015-07-29T00:00:00Z", + "04 22 27 28 52 35", + "3" + ], + [ + 782, + "10064E9F-AD64-429D-84F8-E8D410526A6F", + 782, + 1438484508, + "708543", + 1438484508, + "708543", + null, + "2015-08-01T00:00:00Z", + "07 13 24 49 57 15", + "3" + ], + [ + 783, + "C787A37A-573D-4859-87E7-119575F1D112", + 783, + 1438830107, + "708543", + 1438830107, + "708543", + null, + "2015-08-05T00:00:00Z", + "09 11 14 16 42 19", + "2" + ], + [ + 784, + "DD6C5E0E-BD8D-4290-AA73-94E40E188200", + 784, + 1439089330, + "708543", + 1439089330, + "708543", + null, + "2015-08-08T00:00:00Z", + "09 34 48 52 54 15", + "4" + ], + [ + 785, + "A3D0D844-6B97-4671-87DA-693740D7D8AF", + 785, + 1439434947, + "708543", + 1439434947, + "708543", + null, + "2015-08-12T00:00:00Z", + "08 13 29 38 52 28", + "2" + ], + [ + 786, + "3728F12A-F565-4B44-8176-2EEF0D165955", + 786, + 1439694118, + "708543", + 1439694118, + "708543", + null, + "2015-08-15T00:00:00Z", + "03 13 17 42 52 24", + "4" + ], + [ + 787, + "298DD735-4622-4189-8EE7-F86F90B5AFCE", + 787, + 1440039778, + "708543", + 1440039778, + "708543", + null, + "2015-08-19T00:00:00Z", + "06 08 43 48 50 07", + "2" + ], + [ + 788, + "DA91602B-3A63-4F41-A4E9-2CBF1168AE59", + 788, + 1440298930, + "708543", + 1440298930, + "708543", + null, + "2015-08-22T00:00:00Z", + "04 12 14 21 55 07", + "4" + ], + [ + 789, + "2529F7C9-6E07-4C91-B535-DF2BEFDE2D56", + 789, + 1440644516, + "708543", + 1440644516, + "708543", + null, + "2015-08-26T00:00:00Z", + "02 22 32 45 56 12", + "5" + ], + [ + 790, + "97C9829B-CEEE-4118-A38B-F7B7F79C31EF", + 790, + 1440959254, + "708543", + 1440959254, + "708543", + null, + "2015-08-29T00:00:00Z", + "18 21 25 28 29 16", + "2" + ], + [ + 791, + "3EF82611-85F8-4A8A-8E3A-AA1FD0317354", + 791, + 1441249319, + "708543", + 1441249319, + "708543", + null, + "2015-09-02T00:00:00Z", + "17 22 30 46 56 16", + "3" + ], + [ + 792, + "63CC0BFD-0878-4D37-9699-69D02473AA08", + 792, + 1441508507, + "708543", + 1441508507, + "708543", + null, + "2015-09-05T00:00:00Z", + "10 16 18 29 45 19", + "2" + ], + [ + 793, + "73962F5A-8EC6-41F9-B0D0-13D7E9F944C4", + 793, + 1441854115, + "708543", + 1441854115, + "708543", + null, + "2015-09-09T00:00:00Z", + "44 45 47 50 51 08", + "2" + ], + [ + 794, + "42753DF4-07BE-4C30-A721-B2CF0CCDB7CD", + 794, + 1442113307, + "708543", + 1442113307, + "708543", + null, + "2015-09-12T00:00:00Z", + "02 03 13 16 35 27", + "3" + ], + [ + 795, + "56B46B8A-B108-42E4-9A38-24C56DE66CE6", + 795, + 1442458906, + "708543", + 1442458906, + "708543", + null, + "2015-09-16T00:00:00Z", + "05 07 24 31 39 07", + "3" + ], + [ + 796, + "CDF7063C-D520-4F5D-861A-96755805F6F4", + 796, + 1442847785, + "708543", + 1442847785, + "708543", + null, + "2015-09-19T00:00:00Z", + "12 17 26 43 48 24", + "2" + ], + [ + 797, + "1A936092-357A-40DD-B18B-4747851BBE87", + 797, + 1443063706, + "708543", + 1443063706, + "708543", + null, + "2015-09-23T00:00:00Z", + "08 29 41 51 58 05", + "2" + ], + [ + 798, + "A06BDED2-3FEB-40F0-89A4-2CAF9B0A2858", + 798, + 1443322914, + "708543", + 1443322914, + "708543", + null, + "2015-09-26T00:00:00Z", + "23 31 42 50 57 05", + "3" + ], + [ + 799, + "DB03982B-C76B-4404-977C-C9EEA3200274", + 799, + 1443668505, + "708543", + 1443668505, + "708543", + null, + "2015-09-30T00:00:00Z", + "21 39 40 55 59 17", + "3" + ], + [ + 800, + "FABF6C69-E0F5-4F46-8BE0-3CA7766831D0", + 800, + 1443927709, + "708543", + 1443927709, + "708543", + null, + "2015-10-03T00:00:00Z", + "06 26 33 44 46 04", + "2" + ], + [ + 801, + "43CA547E-F47A-453C-B0A9-26381E38A410", + 801, + 1444273306, + "708543", + 1444273306, + "708543", + null, + "2015-10-07T00:00:00Z", + "18 30 40 48 52 09", + "3" + ], + [ + 802, + "400812A5-A956-48A9-91B1-F3D056E2F5C9", + 802, + 1444532485, + "708543", + 1444532485, + "708543", + null, + "2015-10-10T00:00:00Z", + "12 27 29 43 68 01", + "2" + ], + [ + 803, + "7ABCEB8C-820F-4379-ADFA-0D590640A30C", + 803, + 1444878105, + "708543", + 1444878105, + "708543", + null, + "2015-10-14T00:00:00Z", + "15 20 29 31 40 01", + "2" + ], + [ + 804, + "8B64AF93-027A-4027-A217-5D9DB0ED22AB", + 804, + 1445137286, + "708543", + 1445137286, + "708543", + null, + "2015-10-17T00:00:00Z", + "48 49 57 62 69 19", + "3" + ], + [ + 805, + "465C206D-BEB3-4F5C-AF45-B7C60F736D1E", + 805, + 1445482905, + "708543", + 1445482905, + "708543", + null, + "2015-10-21T00:00:00Z", + "30 32 42 56 57 11", + "4" + ], + [ + 806, + "0ECE9623-21D9-4E2B-B9F9-D67A3C284E73", + 806, + 1445742085, + "708543", + 1445742085, + "708543", + null, + "2015-10-24T00:00:00Z", + "20 31 56 60 64 02", + "3" + ], + [ + 807, + "C22995CB-CBF3-4958-B80C-F9B1F8F9B9C5", + 807, + 1446087727, + "708543", + 1446087727, + "708543", + null, + "2015-10-28T00:00:00Z", + "04 54 56 62 63 10", + "2" + ], + [ + 808, + "9DB950E1-1439-4B85-91F3-2D73EBECD6D4", + 808, + 1446346927, + "708543", + 1446346927, + "708543", + null, + "2015-10-31T00:00:00Z", + "09 20 25 47 68 07", + "2" + ], + [ + 809, + "2C693FFD-694C-4DF3-AA8E-73C92ACD38AF", + 809, + 1446692509, + "708543", + 1446692509, + "708543", + null, + "2015-11-04T00:00:00Z", + "02 12 17 20 65 17", + "4" + ], + [ + 810, + "D655D04B-E21B-4342-BD5D-C027CA362005", + 810, + 1446951708, + "708543", + 1446951708, + "708543", + null, + "2015-11-07T00:00:00Z", + "07 16 25 50 53 15", + "2" + ], + [ + 811, + "7ECA2F66-0B64-493A-9FED-BC107E02287C", + 811, + 1447297309, + "708543", + 1447297309, + "708543", + null, + "2015-11-11T00:00:00Z", + "04 26 32 55 64 18", + "3" + ], + [ + 812, + "1D579B1E-10CC-407E-B78A-9C5569D7A2F8", + 812, + 1447556507, + "708543", + 1447556507, + "708543", + null, + "2015-11-14T00:00:00Z", + "14 22 37 45 66 05", + "3" + ], + [ + 813, + "5D32E728-9113-4C09-A8CD-BDAC99661DFD", + 813, + 1447902130, + "708543", + 1447902130, + "708543", + null, + "2015-11-18T00:00:00Z", + "17 40 41 46 69 06", + "2" + ], + [ + 814, + "FCB4536B-1006-4F05-BC8D-AAFB9DF95A93", + 814, + 1448161306, + "708543", + 1448161306, + "708543", + null, + "2015-11-21T00:00:00Z", + "37 47 50 52 57 21", + "3" + ], + [ + 815, + "21E5D4E6-B471-4928-9385-4CE1ECF18792", + 815, + 1448506906, + "708543", + 1448506906, + "708543", + null, + "2015-11-25T00:00:00Z", + "16 29 53 58 69 21", + "2" + ], + [ + 816, + "B18D454A-B143-47CE-A4E8-EA78D6778190", + 816, + 1448766107, + "708543", + 1448766107, + "708543", + null, + "2015-11-28T00:00:00Z", + "02 06 47 66 67 02", + "3" + ], + [ + 817, + "5F02EEC4-4E7F-49AD-A4AA-9BB594D1A47F", + 817, + 1449111727, + "708543", + 1449111727, + "708543", + null, + "2015-12-02T00:00:00Z", + "14 18 19 32 64 09", + "2" + ], + [ + 818, + "FA5ECE8D-2868-4AA2-AE84-8272D4C1C3D9", + 818, + 1449370908, + "708543", + 1449370908, + "708543", + null, + "2015-12-05T00:00:00Z", + "13 27 33 47 68 13", + "2" + ], + [ + 819, + "6655127F-8D2F-493B-8BE8-8A3D3073C305", + 819, + 1449716510, + "708543", + 1449716510, + "708543", + null, + "2015-12-09T00:00:00Z", + "07 10 16 46 56 01", + "2" + ], + [ + 820, + "0B0D036D-AAA7-4012-98DA-45227548BADF", + 820, + 1449975728, + "708543", + 1449975728, + "708543", + null, + "2015-12-12T00:00:00Z", + "02 14 19 30 62 22", + "2" + ], + [ + 821, + "DFA266CA-6A2B-4D42-8D07-283712CE541B", + 821, + 1450321306, + "708543", + 1450321306, + "708543", + null, + "2015-12-16T00:00:00Z", + "09 10 32 42 55 06", + "2" + ], + [ + 822, + "D0D8AE46-E6E2-40BF-8C54-8E58523CC68A", + 822, + 1450580489, + "708543", + 1450580489, + "708543", + null, + "2015-12-19T00:00:00Z", + "28 30 41 59 68 10", + "2" + ], + [ + 823, + "B473C73C-19F4-4C65-82A6-0E614998234A", + 823, + 1450926106, + "708543", + 1450926106, + "708543", + null, + "2015-12-23T00:00:00Z", + "16 38 55 63 67 25", + "4" + ], + [ + 824, + "0525C88E-D2C8-46A4-8408-BA8E786DA09D", + 824, + 1451185308, + "708543", + 1451185308, + "708543", + null, + "2015-12-26T00:00:00Z", + "27 40 44 59 65 20", + "2" + ], + [ + 825, + "C6064586-54E3-4309-8B9B-446C6041CB02", + 825, + 1451530913, + "708543", + 1451530913, + "708543", + null, + "2015-12-30T00:00:00Z", + "12 36 38 54 61 22", + "3" + ], + [ + 826, + "F961863C-78F0-401C-9743-1D3791C3490A", + 826, + 1451790150, + "708543", + 1451790150, + "708543", + null, + "2016-01-02T00:00:00Z", + "05 06 15 29 42 10", + "2" + ], + [ + 827, + "9D501501-D06D-46B2-9CAD-211B2F995F7A", + 827, + 1452135747, + "708543", + 1452135747, + "708543", + null, + "2016-01-06T00:00:00Z", + "02 11 47 62 63 17", + "3" + ], + [ + 828, + "F5DBEFA5-54A6-4B9A-B2FB-267CD56F9835", + 828, + 1452394927, + "708543", + 1452394927, + "708543", + null, + "2016-01-09T00:00:00Z", + "16 19 32 34 57 13", + "3" + ], + [ + 829, + "FDF34E6A-BA25-4D92-9DB7-7985BA3DCC2D", + 829, + 1452740568, + "708543", + 1452740568, + "708543", + null, + "2016-01-13T00:00:00Z", + "04 08 19 27 34 10", + "2" + ], + [ + 830, + "7EE2F9FB-7673-4DDE-AB72-3651B3AF0444", + 830, + 1453042908, + "708543", + 1453042908, + "708543", + null, + "2016-01-16T00:00:00Z", + "03 51 52 61 64 06", + "2" + ], + [ + 831, + "FACC0343-646E-4CA2-8974-C6A298077671", + 831, + 1453345367, + "708543", + 1453345367, + "708543", + null, + "2016-01-20T00:00:00Z", + "05 39 44 47 69 24", + "5" + ], + [ + 832, + "F93CCC4F-D69B-4AAB-91EB-9D7446F7A2A0", + 832, + 1453604572, + "708543", + 1453604572, + "708543", + null, + "2016-01-23T00:00:00Z", + "22 32 34 40 69 19", + "4" + ], + [ + 833, + "21149184-5031-4CDD-A832-1D34A2C7B623", + 833, + 1453950088, + "708543", + 1453950088, + "708543", + null, + "2016-01-27T00:00:00Z", + "03 12 40 52 67 21", + "2" + ], + [ + 834, + "CEA18644-71EA-460A-B8E4-A93CF3581107", + 834, + 1454209328, + "708543", + 1454209328, + "708543", + null, + "2016-01-30T00:00:00Z", + "05 12 16 31 43 18", + "4" + ], + [ + 835, + "8D0A23AA-4646-44B2-9A9E-4C25B15DB9E2", + 835, + 1454554910, + "708543", + 1454554910, + "708543", + null, + "2016-02-03T00:00:00Z", + "26 28 31 60 67 23", + "3" + ], + [ + 836, + "A1E03B5F-A887-48BA-94AF-8BA6F270AA8A", + 836, + 1454814130, + "708543", + 1454814130, + "708543", + null, + "2016-02-06T00:00:00Z", + "04 13 31 36 52 08", + "3" + ], + [ + 837, + "41D48664-EBDB-4E7E-8FAC-CD8F09739F73", + 837, + 1455159687, + "708543", + 1455159687, + "708543", + null, + "2016-02-10T00:00:00Z", + "02 03 40 50 62 05", + "2" + ], + [ + 838, + "7AEB4B66-7747-46CC-9BEA-F25ACAE6C3C9", + 838, + 1455418987, + "708543", + 1455418987, + "708543", + null, + "2016-02-13T00:00:00Z", + "07 15 18 19 36 20", + "2" + ], + [ + 839, + "6B8BE743-F22C-4A50-B2B5-380FD1D2F8EE", + 839, + 1455764517, + "708543", + 1455764517, + "708543", + null, + "2016-02-17T00:00:00Z", + "07 17 27 29 40 25", + "2" + ], + [ + 840, + "C2CCCF1C-3F1A-405F-B70F-4C6C86655FEA", + 840, + 1456023770, + "708543", + 1456023770, + "708543", + null, + "2016-02-20T00:00:00Z", + "11 12 15 16 54 25", + "5" + ], + [ + 841, + "94B1F83F-79A0-41B3-8482-9FC6C233E98B", + 841, + 1456369306, + "708543", + 1456369306, + "708543", + null, + "2016-02-24T00:00:00Z", + "21 31 64 65 67 05", + "3" + ], + [ + 842, + "026D1654-83BA-4BF3-9C2E-66FD17B5357F", + 842, + 1456628570, + "708543", + 1456628570, + "708543", + null, + "2016-02-27T00:00:00Z", + "10 11 21 22 53 18", + "3" + ], + [ + 843, + "32A2DD81-B860-4FCB-84AA-2CC4C5A2E4C6", + 843, + 1456974110, + "708543", + 1456974110, + "708543", + null, + "2016-03-02T00:00:00Z", + "12 13 44 52 62 06", + "2" + ], + [ + 844, + "59C142D9-3DAB-4426-9AE6-CE628E5A454E", + 844, + 1457233373, + "708543", + 1457233373, + "708543", + null, + "2016-03-05T00:00:00Z", + "03 27 34 59 69 19", + "2" + ], + [ + 845, + "3F050CD8-2598-4E91-8EB0-6672BE274C30", + 845, + 1457578898, + "708543", + 1457578898, + "708543", + null, + "2016-03-09T00:00:00Z", + "14 23 32 34 68 03", + "3" + ], + [ + 846, + "D6246154-1A79-49D1-8AE3-D588EEF93CAD", + 846, + 1457838158, + "708543", + 1457838158, + "708543", + null, + "2016-03-12T00:00:00Z", + "11 28 50 57 62 23", + "2" + ], + [ + 847, + "B4ADA05D-A321-4010-A151-3E00A3EC9E27", + 847, + 1458183687, + "708543", + 1458183687, + "708543", + null, + "2016-03-16T00:00:00Z", + "10 12 13 46 50 21", + "3" + ], + [ + 848, + "C44AC758-6188-4C66-889E-0C11B69B3F5A", + 848, + 1458442886, + "708543", + 1458442886, + "708543", + null, + "2016-03-19T00:00:00Z", + "11 23 43 54 60 03", + "3" + ], + [ + 849, + "F76B28BE-B8CC-4333-B8C2-8038FA04A5D7", + 849, + 1458788506, + "708543", + 1458788506, + "708543", + null, + "2016-03-23T00:00:00Z", + "05 08 15 22 49 25", + "3" + ], + [ + 850, + "DAC76276-F82B-4521-8B22-2D77AE8B65DD", + 850, + 1459047769, + "708543", + 1459047769, + "708543", + null, + "2016-03-26T00:00:00Z", + "11 23 42 52 68 06", + "3" + ], + [ + 851, + "AFA36766-0E68-4370-AF47-008B6ED8071E", + 851, + 1459393289, + "708543", + 1459393289, + "708543", + null, + "2016-03-30T00:00:00Z", + "24 44 53 55 63 19", + "2" + ], + [ + 852, + "0638F190-3A0F-43C2-8688-ED2D07E85386", + 852, + 1459652500, + "708543", + 1459652500, + "708543", + null, + "2016-04-02T00:00:00Z", + "09 28 30 40 61 03", + "2" + ], + [ + 853, + "538BA672-7387-4BB6-B077-DECC618EE0DA", + 853, + 1459998107, + "708543", + 1459998107, + "708543", + null, + "2016-04-06T00:00:00Z", + "04 28 49 60 65 25", + "2" + ], + [ + 854, + "D292DAB1-F656-478B-9776-4307D1D2E9F6", + 854, + 1460257309, + "708543", + 1460257309, + "708543", + null, + "2016-04-09T00:00:00Z", + "14 22 23 41 61 09", + "3" + ], + [ + 855, + "806C3A3C-F727-443D-AA51-A0B6FD55392C", + 855, + 1460602907, + "708543", + 1460602907, + "708543", + null, + "2016-04-13T00:00:00Z", + "30 33 35 38 64 22", + "3" + ], + [ + 856, + "6C513E67-72D5-49DC-9339-8855AE411D23", + 856, + 1460862109, + "708543", + 1460862109, + "708543", + null, + "2016-04-16T00:00:00Z", + "03 18 25 32 51 03", + "2" + ], + [ + 857, + "3CC889C1-BC6D-4AB3-9703-EDB0B0993D25", + 857, + 1461207686, + "708543", + 1461207686, + "708543", + null, + "2016-04-20T00:00:00Z", + "12 25 30 52 62 08", + "3" + ], + [ + 858, + "66E2C834-3EE5-417A-9333-8CD4C4BDDC0D", + 858, + 1461466948, + "708543", + 1461466948, + "708543", + null, + "2016-04-23T00:00:00Z", + "19 35 46 59 62 13", + "5" + ], + [ + 859, + "FB0E502B-4C20-40F1-9191-02932FFEFC20", + 859, + 1461812486, + "708543", + 1461812486, + "708543", + null, + "2016-04-27T00:00:00Z", + "02 25 33 39 64 17", + "2" + ], + [ + 860, + "EFC02B54-5324-4CEA-A33B-F13F2792B866", + 860, + 1462071708, + "708543", + 1462071708, + "708543", + null, + "2016-04-30T00:00:00Z", + "03 12 16 32 34 14", + "3" + ], + [ + 861, + "B343B51F-4E61-4B9A-8D32-4A6872B2B45D", + 861, + 1462417308, + "708543", + 1462417308, + "708543", + null, + "2016-05-04T00:00:00Z", + "30 47 57 66 69 03", + "3" + ], + [ + 862, + "27B6967E-B5D2-46D0-B7BC-DA91059FFCDB", + 862, + 1462676507, + "708543", + 1462676507, + "708543", + null, + "2016-05-07T00:00:00Z", + "05 25 26 44 66 09", + "2" + ], + [ + 863, + "A4B7173B-5E0C-4E9D-BCA4-618A323FB42D", + 863, + 1463022106, + "708543", + 1463022106, + "708543", + null, + "2016-05-11T00:00:00Z", + "20 32 52 66 69 23", + "3" + ], + [ + 864, + "CE5AB6A5-25F9-4388-9467-BD0445459BC4", + 864, + 1463281288, + "708543", + 1463281288, + "708543", + null, + "2016-05-14T00:00:00Z", + "13 27 47 64 65 09", + "3" + ], + [ + 865, + "3F367781-B30A-47AE-B947-B0D2AE4FFB10", + 865, + 1463626906, + "708543", + 1463626906, + "708543", + null, + "2016-05-18T00:00:00Z", + "23 25 39 54 67 11", + "3" + ], + [ + 866, + "2B6846C3-B065-4EEB-B321-68C75294F7C9", + 866, + 1463886110, + "708543", + 1463886110, + "708543", + null, + "2016-05-21T00:00:00Z", + "05 07 09 23 32 26", + "4" + ], + [ + 867, + "0774E3AA-3772-43E0-B98B-05EAB69847A1", + 867, + 1464231708, + "708543", + 1464231708, + "708543", + null, + "2016-05-25T00:00:00Z", + "11 24 41 59 64 15", + "3" + ], + [ + 868, + "3796D800-4922-4280-8B88-E85ED906B4DF", + 868, + 1464490907, + "708543", + 1464490907, + "708543", + null, + "2016-05-28T00:00:00Z", + "06 33 34 58 59 12", + "2" + ], + [ + 869, + "EEB99A68-457E-4AFF-A13F-427EEE2D4EB1", + 869, + 1464836507, + "708543", + 1464836507, + "708543", + null, + "2016-06-01T00:00:00Z", + "23 30 33 40 69 12", + "5" + ], + [ + 870, + "74D58C48-7E89-4118-BD99-6DBD5043656D", + 870, + 1465095690, + "708543", + 1465095690, + "708543", + null, + "2016-06-04T00:00:00Z", + "16 20 22 43 64 17", + "2" + ], + [ + 871, + "0E17BFD1-5263-4495-9CFD-817A48C251A4", + 871, + 1465441306, + "708543", + 1465441306, + "708543", + null, + "2016-06-08T00:00:00Z", + "12 25 37 60 69 20", + "3" + ], + [ + 872, + "5324C432-0CA5-46C6-8980-F6D6516D07A3", + 872, + 1465700507, + "708543", + 1465700507, + "708543", + null, + "2016-06-11T00:00:00Z", + "20 27 36 41 58 07", + "2" + ], + [ + 873, + "424D6940-1854-4E17-A840-FB6E3EFB0BC7", + 873, + 1466046088, + "708543", + 1466046088, + "708543", + null, + "2016-06-15T00:00:00Z", + "04 22 24 31 33 10", + "2" + ], + [ + 874, + "801FF99A-39BA-44A5-B34F-7A40CCC981F4", + 874, + 1466305308, + "708543", + 1466305308, + "708543", + null, + "2016-06-18T00:00:00Z", + "02 23 41 53 63 11", + "2" + ], + [ + 875, + "32B8607F-979E-4C0E-846D-5074E00DFEAB", + 875, + 1466650887, + "708543", + 1466650887, + "708543", + null, + "2016-06-22T00:00:00Z", + "14 40 42 43 52 17", + "3" + ], + [ + 876, + "FDFEF46C-8E7E-4BF8-B000-C0D8C5749D4E", + 876, + 1466910089, + "708543", + 1466910089, + "708543", + null, + "2016-06-25T00:00:00Z", + "03 27 36 56 69 25", + "2" + ], + [ + 877, + "A1087993-4142-44E5-8FF3-F8A77DEFFB06", + 877, + 1467255707, + "708543", + 1467255707, + "708543", + null, + "2016-06-29T00:00:00Z", + "23 29 37 60 64 06", + "2" + ], + [ + 878, + "4BF9DA07-A878-4846-A461-B8B46ABD9792", + 878, + 1467514914, + "708543", + 1467514914, + "708543", + null, + "2016-07-02T00:00:00Z", + "10 34 39 59 63 04", + "2" + ], + [ + 879, + "81D9BD05-0115-4833-A484-F5F5764AE5B1", + 879, + 1467860567, + "708543", + 1467860567, + "708543", + null, + "2016-07-06T00:00:00Z", + "02 24 31 57 66 18", + "3" + ], + [ + 880, + "1B7693CA-B277-4943-AC44-DBDDFE46E05B", + 880, + 1468119706, + "708543", + 1468119706, + "708543", + null, + "2016-07-09T00:00:00Z", + "10 28 32 61 64 12", + "3" + ], + [ + 881, + "82FEF08C-D90C-4582-B8C9-9703FEB75A77", + 881, + 1468465309, + "708543", + 1468465309, + "708543", + null, + "2016-07-13T00:00:00Z", + "03 15 29 54 57 10", + "3" + ], + [ + 882, + "DEF18268-C8D4-428E-A79B-A0E0AF3CBD4B", + 882, + 1468724507, + "708543", + 1468724507, + "708543", + null, + "2016-07-16T00:00:00Z", + "11 17 40 50 62 26", + "2" + ], + [ + 883, + "45A8B2F3-217E-4D2B-90A3-AE8D1B4C6174", + 883, + 1469070107, + "708543", + 1469070107, + "708543", + null, + "2016-07-20T00:00:00Z", + "06 25 35 58 66 05", + "2" + ], + [ + 884, + "B58A1782-C764-46F1-B9B9-3BFE1D6B4E52", + 884, + 1469329307, + "708543", + 1469329307, + "708543", + null, + "2016-07-23T00:00:00Z", + "05 07 23 35 39 11", + "2" + ], + [ + 885, + "7D4F8200-DF95-4382-8748-33E050967A9D", + 885, + 1469674886, + "708543", + 1469674886, + "708543", + null, + "2016-07-27T00:00:00Z", + "10 47 50 65 68 24", + "2" + ], + [ + 886, + "79F3C5B3-FD8F-49A9-A796-60542668C200", + 886, + 1469934107, + "708543", + 1469934107, + "708543", + null, + "2016-07-30T00:00:00Z", + "11 17 21 23 32 05", + "2" + ], + [ + 887, + "A5A0BD2D-64AB-4811-82AB-D61EEF1AF7B1", + 887, + 1470279686, + "708543", + 1470279686, + "708543", + null, + "2016-08-03T00:00:00Z", + "09 11 27 66 67 02", + "3" + ], + [ + 888, + "BD4C1208-94E5-4D63-9D5A-586C1A3822B7", + 888, + 1470538909, + "708543", + 1470538909, + "708543", + null, + "2016-08-06T00:00:00Z", + "20 33 36 47 52 12", + "3" + ], + [ + 889, + "A9CAA420-DE01-412C-A756-F1A663F4AA29", + 889, + 1470884507, + "708543", + 1470884507, + "708543", + null, + "2016-08-10T00:00:00Z", + "23 56 61 64 67 12", + "5" + ], + [ + 890, + "8E27E501-E185-4712-BCDC-F3FB1230EDF8", + 890, + 1471143709, + "708543", + 1471143709, + "708543", + null, + "2016-08-13T00:00:00Z", + "38 44 60 64 69 06", + "2" + ], + [ + 891, + "BD66F02B-64EE-4CC2-BD17-556CA0E719C7", + 891, + 1471489307, + "708543", + 1471489307, + "708543", + null, + "2016-08-17T00:00:00Z", + "33 44 49 50 52 08", + "3" + ], + [ + 892, + "A479CB83-1789-467D-B719-50667324A737", + 892, + 1471773690, + "708543", + 1471773690, + "708543", + null, + "2016-08-20T00:00:00Z", + "03 06 21 60 68 24", + "2" + ], + [ + 893, + "9839668D-4E14-477E-9048-78609B14F262", + 893, + 1472119267, + "708543", + 1472119267, + "708543", + null, + "2016-08-24T00:00:00Z", + "09 11 25 64 65 16", + "3" + ], + [ + 894, + "7BE65F8C-50FB-4760-B95B-5AA9C7D7BDEB", + 894, + 1472378508, + "708543", + 1472378508, + "708543", + null, + "2016-08-27T00:00:00Z", + "04 32 48 49 63 20", + "2" + ], + [ + 895, + "64CEEEC0-29D4-4F27-BAB1-A71CA938691D", + 895, + 1472724066, + "708543", + 1472724066, + "708543", + null, + "2016-08-31T00:00:00Z", + "05 10 24 56 61 12", + "2" + ], + [ + 896, + "29B26B2B-D58E-44AD-A903-DBEBE05E2B0B", + 896, + 1472983266, + "708543", + 1472983266, + "708543", + null, + "2016-09-03T00:00:00Z", + "07 39 50 59 67 25", + "3" + ], + [ + 897, + "D37CF53F-C59C-41D3-9C80-6FF81CE73730", + 897, + 1473363020, + "708543", + 1473363020, + "708543", + null, + "2016-09-07T00:00:00Z", + "22 23 29 33 55 21", + "2" + ], + [ + 898, + "22706198-5E98-4646-987C-26275EA758CA", + 898, + 1473588064, + "708543", + 1473588064, + "708543", + null, + "2016-09-10T00:00:00Z", + "03 17 49 55 68 08", + "2" + ], + [ + 899, + "BC2D6956-1D23-4DB9-9286-BB5EEAEF83A4", + 899, + 1473933706, + "708543", + 1473933706, + "708543", + null, + "2016-09-14T00:00:00Z", + "10 11 23 28 31 14", + "2" + ], + [ + 900, + "3CAD5A54-A6F9-43B5-A212-1D9B57C576B0", + 900, + 1474192866, + "708543", + 1474192866, + "708543", + null, + "2016-09-17T00:00:00Z", + "09 19 51 55 62 14", + "4" + ], + [ + 901, + "6BAC9382-FE49-4853-80FB-52C1A70CD422", + 901, + 1474538472, + "708543", + 1474538472, + "708543", + null, + "2016-09-21T00:00:00Z", + "01 28 63 67 69 17", + "4" + ], + [ + 902, + "ACB5DEF7-15F4-45FD-B2E9-242C8B909E9D", + 902, + 1474797668, + "708543", + 1474797668, + "708543", + null, + "2016-09-24T00:00:00Z", + "07 15 20 29 41 22", + "2" + ], + [ + 903, + "8FD3E76A-DEED-458A-A9CA-D6CAA1AA7A6B", + 903, + 1475143268, + "708543", + 1475143268, + "708543", + null, + "2016-09-28T00:00:00Z", + "30 38 52 53 62 01", + "3" + ], + [ + 904, + "BB31C897-1552-494E-B27E-BEC1B7D72C29", + 904, + 1475402464, + "708543", + 1475402464, + "708543", + null, + "2016-10-01T00:00:00Z", + "02 12 50 61 64 01", + "2" + ], + [ + 905, + "DB9A260F-8EDD-4D7E-B6F4-D24AD0FF3A4C", + 905, + 1475748063, + "708543", + 1475748063, + "708543", + null, + "2016-10-05T00:00:00Z", + "08 18 27 29 60 15", + "2" + ], + [ + 906, + "7CC48100-C232-464E-9A23-034B8F0B4147", + 906, + 1476007263, + "708543", + 1476007263, + "708543", + null, + "2016-10-08T00:00:00Z", + "03 54 61 64 68 09", + "2" + ], + [ + 907, + "D88F9F9B-B5D0-464F-BF4A-B08BABF3D7B3", + 907, + 1476352884, + "708543", + 1476352884, + "708543", + null, + "2016-10-12T00:00:00Z", + "16 30 34 37 44 16", + "2" + ], + [ + 908, + "963109BF-96C7-4BAC-8F60-B825FAE4A346", + 908, + 1476612067, + "708543", + 1476612067, + "708543", + null, + "2016-10-15T00:00:00Z", + "23 49 57 64 67 20", + "2" + ], + [ + 909, + "6A69340B-A601-40C8-99AB-D4E8E8742B08", + 909, + 1476957664, + "708543", + 1476957664, + "708543", + null, + "2016-10-19T00:00:00Z", + "10 16 38 43 63 23", + "2" + ], + [ + 910, + "C336DBED-7B5B-41B0-8662-E6E71F97730E", + 910, + 1477216866, + "708543", + 1477216866, + "708543", + null, + "2016-10-22T00:00:00Z", + "01 28 33 55 56 22", + "2" + ], + [ + 911, + "5F475ADD-6DC7-4259-B794-980960C64696", + 911, + 1477562508, + "708543", + 1477562508, + "708543", + null, + "2016-10-26T00:00:00Z", + "02 03 16 48 56 24", + "2" + ], + [ + 912, + "1913132B-72F1-4BBB-BFC5-B6F920804656", + 912, + 1477821707, + "708543", + 1477821707, + "708543", + null, + "2016-10-29T00:00:00Z", + "19 20 21 42 48 23", + "3" + ], + [ + 913, + "E3F60567-F814-45BC-BD16-548B5B430BED", + 913, + 1478167263, + "708543", + 1478167263, + "708543", + null, + "2016-11-02T00:00:00Z", + "13 18 37 54 61 05", + "2" + ], + [ + 914, + "DA422B46-9D32-4BA3-8400-68B1AD0215E9", + 914, + 1478430063, + "708543", + 1478430063, + "708543", + null, + "2016-11-05T00:00:00Z", + "21 31 50 51 69 08", + "3" + ], + [ + 915, + "268D2F3C-7C91-462C-8ECC-6E8E3DF20A22", + 915, + 1478775664, + "708543", + 1478775664, + "708543", + null, + "2016-11-09T00:00:00Z", + "01 25 28 31 54 02", + "2" + ], + [ + 916, + "98AC28EB-755D-42C9-A445-3F6285AD7196", + 916, + 1479034863, + "708543", + 1479034863, + "708543", + null, + "2016-11-12T00:00:00Z", + "08 17 20 27 52 24", + "2" + ], + [ + 917, + "7B229FE5-AC63-4D4A-91A6-0A7CB86DD532", + 917, + 1479380463, + "708543", + 1479380463, + "708543", + null, + "2016-11-16T00:00:00Z", + "28 41 61 63 65 07", + "2" + ], + [ + 918, + "431C3CF5-B68F-4457-889F-49B20F9CF1C4", + 918, + 1479639663, + "708543", + 1479639663, + "708543", + null, + "2016-11-19T00:00:00Z", + "16 24 28 43 61 21", + "2" + ], + [ + 919, + "E0432E50-E19E-4DC3-9A18-36806C7A88C1", + 919, + 1479985514, + "708543", + 1479985514, + "708543", + null, + "2016-11-23T00:00:00Z", + "07 32 41 47 61 03", + "2" + ], + [ + 920, + "B6B9C15A-C30F-4CC0-B1BD-CA3920340503", + 920, + 1480244703, + "708543", + 1480244703, + "708543", + null, + "2016-11-26T00:00:00Z", + "17 19 21 37 44 16", + "2" + ], + [ + 921, + "D40A1619-0832-4A6E-9EAF-3844B23092F0", + 921, + 1480590068, + "708543", + 1480590068, + "708543", + null, + "2016-11-30T00:00:00Z", + "03 14 18 25 45 07", + "2" + ], + [ + 922, + "CBE0E3C4-72D7-446F-B787-B9A04E347C3C", + 922, + 1480849263, + "708543", + 1480849263, + "708543", + null, + "2016-12-03T00:00:00Z", + "08 10 26 27 33 22", + "2" + ], + [ + 923, + "C75F0236-8827-4F14-ADA7-7061AFE4AA04", + 923, + 1481194864, + "708543", + 1481194864, + "708543", + null, + "2016-12-07T00:00:00Z", + "41 48 49 53 64 20", + "2" + ], + [ + 924, + "B9908F6E-3EA8-4093-8210-E306D05F1BD2", + 924, + 1481583706, + "708543", + 1481583706, + "708543", + null, + "2016-12-10T00:00:00Z", + "12 21 32 44 66 15", + "2" + ], + [ + 925, + "542E365D-8B02-4B55-AF96-8592595E12BD", + 925, + 1481799665, + "708543", + 1481799665, + "708543", + null, + "2016-12-14T00:00:00Z", + "18 26 37 39 66 15", + "3" + ], + [ + 926, + "C7997154-C315-455F-AACB-B172F622C6C4", + 926, + 1482058866, + "708543", + 1482058866, + "708543", + null, + "2016-12-17T00:00:00Z", + "01 08 16 40 48 10", + "2" + ], + [ + 927, + "30F782F6-E623-453A-BB19-1BF9A649CDD0", + 927, + 1482404464, + "708543", + 1482404464, + "708543", + null, + "2016-12-21T00:00:00Z", + "25 33 40 54 68 03", + "5" + ], + [ + 928, + "1BCFE588-BF10-4E9E-8B10-A1508D2A3E38", + 928, + 1482663674, + "708543", + 1482663674, + "708543", + null, + "2016-12-24T00:00:00Z", + "28 38 42 51 52 21", + "2" + ], + [ + 929, + "7DC520AF-2E56-4939-94EB-B17EA2DEF8B9", + 929, + 1483009263, + "708543", + 1483009263, + "708543", + null, + "2016-12-28T00:00:00Z", + "16 23 30 44 58 04", + "2" + ], + [ + 930, + "C3C90ACB-7ADE-46A9-80C2-5A06431C7568", + 930, + 1483268548, + "708543", + 1483268548, + "708543", + null, + "2016-12-31T00:00:00Z", + "01 03 28 57 67 09", + "2" + ], + [ + 931, + "ABE7162C-2AB8-4CF1-B7DD-00D473BC7960", + 931, + 1483614084, + "708543", + 1483614084, + "708543", + null, + "2017-01-04T00:00:00Z", + "16 17 29 41 42 04", + "3" + ], + [ + 932, + "2D90D0BC-7841-4342-87DE-8CC03B2262BD", + 932, + 1483873291, + "708543", + 1483873291, + "708543", + null, + "2017-01-07T00:00:00Z", + "03 12 24 37 63 10", + "2" + ], + [ + 933, + "15E71373-4AA1-4CF4-AC87-5DA454A0CAC6", + 933, + 1484218864, + "708543", + 1484218864, + "708543", + null, + "2017-01-11T00:00:00Z", + "01 03 13 16 43 24", + "2" + ], + [ + 934, + "49050BC6-0AF3-421D-8F0E-D1F98D18B740", + 934, + 1484478065, + "708543", + 1484478065, + "708543", + null, + "2017-01-14T00:00:00Z", + "23 55 59 64 69 13", + "5" + ], + [ + 935, + "4CF6D807-30BD-4EFE-9C6C-1858F45CCB7C", + 935, + 1484823665, + "708543", + 1484823665, + "708543", + null, + "2017-01-18T00:00:00Z", + "09 40 41 53 58 12", + "2" + ], + [ + 936, + "557F2798-865C-4016-99BC-C5B9EC0E528C", + 936, + 1485342103, + "708543", + 1485342103, + "708543", + null, + "2017-01-21T00:00:00Z", + "23 25 45 52 67 02", + "2" + ], + [ + 937, + "8FF07805-7014-4F6C-91D3-8240564F1F00", + 937, + 1485428466, + "708543", + 1485428466, + "708543", + null, + "2017-01-25T00:00:00Z", + "18 28 62 66 68 22", + "2" + ], + [ + 938, + "B68D2427-E10F-472C-96BA-71FD05A3823C", + 938, + 1485687664, + "708543", + 1485687664, + "708543", + null, + "2017-01-28T00:00:00Z", + "12 20 39 49 69 17", + "2" + ], + [ + 939, + "5E2A695D-EBAD-494B-8EDC-E97501635708", + 939, + 1486033265, + "708543", + 1486033265, + "708543", + null, + "2017-02-01T00:00:00Z", + "09 43 57 60 64 10", + "2" + ], + [ + 940, + "71AF5B59-A1DF-4E4C-88D6-88E85D019C7E", + 940, + 1486292464, + "708543", + 1486292464, + "708543", + null, + "2017-02-04T00:00:00Z", + "06 13 16 17 52 25", + "3" + ], + [ + 941, + "BB1F871B-84F6-4A98-9DFA-C09389B4AC6D", + 941, + 1486638064, + "708543", + 1486638064, + "708543", + null, + "2017-02-08T00:00:00Z", + "14 20 42 49 66 05", + "2" + ], + [ + 942, + "124D9420-F9FB-4E51-8302-CF6997D70053", + 942, + 1486897266, + "708543", + 1486897266, + "708543", + null, + "2017-02-11T00:00:00Z", + "05 09 17 37 64 02", + "2" + ], + [ + 943, + "34C29F3D-DC81-4AD4-9942-E65828561FA9", + 943, + 1487242864, + "708543", + 1487242864, + "708543", + null, + "2017-02-15T00:00:00Z", + "05 28 33 38 42 19", + "2" + ], + [ + 944, + "BB3B4322-B5BA-4647-9877-9F6D4C59D91D", + 944, + 1487502064, + "708543", + 1487502064, + "708543", + null, + "2017-02-18T00:00:00Z", + "03 07 09 31 33 20", + "3" + ], + [ + 945, + "3BE3ADB4-4BC2-4905-8E2B-24AB6C37F11A", + 945, + 1487847663, + "708543", + 1487847663, + "708543", + null, + "2017-02-22T00:00:00Z", + "10 13 28 52 61 02", + "2" + ], + [ + 946, + "136928E1-7518-42CE-B39B-8B7ED5B0D8DD", + 946, + 1488106865, + "708543", + 1488106865, + "708543", + null, + "2017-02-25T00:00:00Z", + "06 32 47 62 65 19", + "2" + ], + [ + 947, + "8B2F46F7-EFF2-4A56-B800-54CF2B0360CA", + 947, + 1488452443, + "708543", + 1488452443, + "708543", + null, + "2017-03-01T00:00:00Z", + "10 16 40 52 55 17", + "10" + ], + [ + 948, + "E5C90653-DA50-490A-B98C-97A181AE0A02", + 948, + 1488495663, + "708543", + 1488495663, + "708543", + null, + "2017-03-01T00:00:00Z", + "10 16 40 52 55 17", + "10" + ], + [ + 949, + "BC492FFD-A7B3-4529-9EDB-4C6F0E5BF617", + 949, + 1488711665, + "708543", + 1488711665, + "708543", + null, + "2017-03-04T00:00:00Z", + "02 18 19 22 63 19", + "3" + ], + [ + 950, + "BBD64C58-81CB-43B1-90F5-304A7C892D7B", + 950, + 1489057264, + "708543", + 1489057264, + "708543", + null, + "2017-03-08T00:00:00Z", + "23 33 42 46 59 04", + "2" + ], + [ + 951, + "B904A0CA-EA0D-4B49-99CB-5178E6201491", + 951, + 1489312863, + "708543", + 1489312863, + "708543", + null, + "2017-03-11T00:00:00Z", + "01 26 41 50 57 11", + "2" + ], + [ + 952, + "81F3E52B-1A76-487E-BBD0-D8711CBD083B", + 952, + 1489658465, + "708543", + 1489658465, + "708543", + null, + "2017-03-15T00:00:00Z", + "16 30 41 48 53 16", + "3" + ], + [ + 953, + "E73A1F78-9908-4DCA-9125-D40CE4EC5EAB", + 953, + 1489917663, + "708543", + 1489917663, + "708543", + null, + "2017-03-18T00:00:00Z", + "13 25 44 54 67 05", + "3" + ], + [ + 954, + "6122F4BB-2ACA-4F48-86A1-E6A482D02BF9", + 954, + 1490263262, + "708543", + 1490263262, + "708543", + null, + "2017-03-22T00:00:00Z", + "02 09 27 29 42 09", + "2" + ], + [ + 955, + "23640056-0969-4331-ACAA-001E96789E90", + 955, + 1490522463, + "708543", + 1490522463, + "708543", + null, + "2017-03-25T00:00:00Z", + "18 31 32 45 48 16", + "4" + ], + [ + 956, + "7B9AB081-962E-40DD-9C0F-6C974AE5997D", + 956, + 1490868063, + "708543", + 1490868063, + "708543", + null, + "2017-03-29T00:00:00Z", + "08 15 31 36 62 11", + "3" + ], + [ + 957, + "F20FEE86-0911-4C09-A1DB-290609482563", + 957, + 1491127263, + "708543", + 1491127263, + "708543", + null, + "2017-04-01T00:00:00Z", + "09 32 36 44 65 01", + "3" + ], + [ + 958, + "AF7C0244-1CBA-4A9C-A238-4D47750567F7", + 958, + 1491472863, + "708543", + 1491472863, + "708543", + null, + "2017-04-05T00:00:00Z", + "08 20 46 53 54 13", + "2" + ], + [ + 959, + "256878FD-772B-48D3-B7A4-4FE86DFAC088", + 959, + 1491732063, + "708543", + 1491732063, + "708543", + null, + "2017-04-08T00:00:00Z", + "23 36 51 53 60 15", + "2" + ], + [ + 960, + "F114AF8A-05DB-47BA-9B9E-53ABC867CCFE", + 960, + 1492077663, + "708543", + 1492077663, + "708543", + null, + "2017-04-12T00:00:00Z", + "08 14 61 63 68 24", + "2" + ], + [ + 961, + "6F58C329-42D3-4512-8117-203CECC2ECDF", + 961, + 1492336863, + "708543", + 1492336863, + "708543", + null, + "2017-04-15T00:00:00Z", + "05 22 26 45 61 13", + "3" + ], + [ + 962, + "7473DF48-9E9C-4557-90FE-239C749A5B8B", + 962, + 1492682463, + "708543", + 1492682463, + "708543", + null, + "2017-04-19T00:00:00Z", + "01 19 37 40 52 15", + "3" + ], + [ + 963, + "7664B507-4ADA-4AF4-A7E6-8AA8D000F05B", + 963, + 1492941664, + "708543", + 1492941664, + "708543", + null, + "2017-04-22T00:00:00Z", + "21 39 41 48 63 06", + "3" + ], + [ + 964, + "4C556EA2-12CB-4C4D-B80E-E635D3413A69", + 964, + 1493287265, + "708543", + 1493287265, + "708543", + null, + "2017-04-26T00:00:00Z", + "01 15 18 26 51 26", + "4" + ], + [ + 965, + "B32D3AED-6C68-4330-B70C-2B6859EBB1FB", + 965, + 1493546465, + "708543", + 1493546465, + "708543", + null, + "2017-04-29T00:00:00Z", + "22 23 24 45 62 05", + "2" + ], + [ + 966, + "A6F5C3ED-3225-4FAF-8D27-01E7068A50F0", + 966, + 1493892066, + "708543", + 1493892066, + "708543", + null, + "2017-05-03T00:00:00Z", + "17 18 49 59 66 09", + "2" + ], + [ + 967, + "BDFF5C57-C2CE-4439-AFA2-3FDC539BF791", + 967, + 1494151264, + "708543", + 1494151264, + "708543", + null, + "2017-05-06T00:00:00Z", + "11 21 31 41 59 21", + "3" + ], + [ + 968, + "3E057E13-4199-4445-A7A1-344AAF197C36", + 968, + 1494496865, + "708543", + 1494496865, + "708543", + null, + "2017-05-10T00:00:00Z", + "29 31 46 56 62 08", + "2" + ], + [ + 969, + "0C104D21-34FC-42D7-8632-40E67B3522F6", + 969, + 1494756065, + "708543", + 1494756065, + "708543", + null, + "2017-05-13T00:00:00Z", + "17 20 32 63 68 19", + "5" + ], + [ + 970, + "7194A14E-F3A2-4FAB-9E38-16E88E8B5A23", + 970, + 1495101664, + "708543", + 1495101664, + "708543", + null, + "2017-05-17T00:00:00Z", + "04 11 39 45 48 09", + "3" + ], + [ + 971, + "08FE9220-F04E-42BB-85FC-0D50107BE201", + 971, + 1495360866, + "708543", + 1495360866, + "708543", + null, + "2017-05-20T00:00:00Z", + "05 22 45 47 54 03", + "2" + ], + [ + 972, + "6160C9E9-ACE0-44B7-9AAA-B2DDA2C83C45", + 972, + 1495706464, + "708543", + 1495706464, + "708543", + null, + "2017-05-24T00:00:00Z", + "28 32 33 38 62 15", + "2" + ], + [ + 973, + "D27C5ED7-46A0-4864-ADF6-E490F3CE4F36", + 973, + 1495965664, + "708543", + 1495965664, + "708543", + null, + "2017-05-27T00:00:00Z", + "05 10 28 55 67 09", + "3" + ], + [ + 974, + "C7B5F47C-2EA8-44BB-B04C-B19D4794BBA9", + 974, + 1496311265, + "708543", + 1496311265, + "708543", + null, + "2017-05-31T00:00:00Z", + "04 33 39 46 60 06", + "2" + ], + [ + 975, + "F69D8094-D1AB-4E64-873F-046ED5867980", + 975, + 1496570464, + "708543", + 1496570464, + "708543", + null, + "2017-06-03T00:00:00Z", + "03 09 21 41 54 25", + "4" + ], + [ + 976, + "A3F85596-082C-4FF9-BF20-3E51FF9A98F9", + 976, + 1496916064, + "708543", + 1496916064, + "708543", + null, + "2017-06-07T00:00:00Z", + "05 21 57 66 69 13", + "3" + ], + [ + 977, + "0C90284F-764D-483A-B4E9-AD1C0FEDB6DA", + 977, + 1497520864, + "708543", + 1497520864, + "708543", + null, + "2017-06-14T00:00:00Z", + "05 22 43 57 63 24", + "2" + ], + [ + 978, + "8167BC74-6790-4223-A42B-2CC3739EB537", + 978, + 1497780063, + "708543", + 1497780063, + "708543", + null, + "2017-06-17T00:00:00Z", + "10 13 32 53 62 21", + "2" + ], + [ + 979, + "73CA9EB8-79D6-40B3-A8FE-8470793B4E4B", + 979, + 1498125664, + "708543", + 1498125664, + "708543", + null, + "2017-06-21T00:00:00Z", + "14 46 61 65 68 13", + "2" + ], + [ + 980, + "F77798EC-77A9-4A22-B06B-DB617FA70AAA", + 980, + 1498384863, + "708543", + 1498384863, + "708543", + null, + "2017-06-24T00:00:00Z", + "10 22 32 36 58 10", + "4" + ], + [ + 981, + "029B1864-680A-4388-9C25-CD03A2AEFCAC", + 981, + 1498730464, + "708543", + 1498730464, + "708543", + null, + "2017-06-28T00:00:00Z", + "29 37 46 53 68 08", + "2" + ], + [ + 982, + "61DB0FF6-A6E6-4A2F-84D8-9DEF8670EB8F", + 982, + 1498989663, + "708543", + 1498989663, + "708543", + null, + "2017-07-01T00:00:00Z", + "19 42 45 48 53 16", + "3" + ], + [ + 983, + "1C831F5D-3977-47E0-AB0A-84CBF17D0EAF", + 983, + 1499335263, + "708543", + 1499335263, + "708543", + null, + "2017-07-05T00:00:00Z", + "04 09 16 54 68 21", + "2" + ], + [ + 984, + "80CBBECD-4E5A-41A1-A75C-791756039A6F", + 984, + 1499594464, + "708543", + 1499594464, + "708543", + null, + "2017-07-08T00:00:00Z", + "08 10 29 40 59 26", + "2" + ], + [ + 985, + "93717B8E-CA86-4447-B74E-095E20FB5C9C", + 985, + 1499940064, + "708543", + 1499940064, + "708543", + null, + "2017-07-12T00:00:00Z", + "01 02 18 23 61 09", + "2" + ], + [ + 986, + "B66C4317-9207-433C-A498-BABB79D8D144", + 986, + 1500199263, + "708543", + 1500199263, + "708543", + null, + "2017-07-15T00:00:00Z", + "09 40 63 64 66 17", + "2" + ], + [ + 987, + "8724EA9E-C2EE-4F63-8CCD-2A572EBE09BB", + 987, + 1500544863, + "708543", + 1500544863, + "708543", + null, + "2017-07-19T00:00:00Z", + "50 51 59 61 63 04", + "5" + ], + [ + 988, + "D19EE0BA-A71F-457E-AD3F-64AC41202A57", + 988, + 1500804063, + "708543", + 1500804063, + "708543", + null, + "2017-07-22T00:00:00Z", + "05 32 44 53 60 09", + "3" + ], + [ + 989, + "78BCC11D-0F1F-46B5-A18C-847558335E13", + 989, + 1501149663, + "708543", + 1501149663, + "708543", + null, + "2017-07-26T00:00:00Z", + "07 19 21 42 69 12", + "2" + ] + ] +} diff --git a/test/inputs/json/misc/32d5c.json b/test/inputs/json/misc/32d5c.json index 47b30cbfd..7a89461ac 100644 --- a/test/inputs/json/misc/32d5c.json +++ b/test/inputs/json/misc/32d5c.json @@ -1 +1,3052 @@ -[{"PersonID":1735,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820129812","Notes":"","BirthDate":"1970-07-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Constance, Angela","PreferredName":"Angela","GenderTypeID":1},{"PersonID":1741,"PhotoURL":"","Notes":"","BirthDate":"1950-02-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Goldie, Annabel","PreferredName":"Annabel","GenderTypeID":1},{"PersonID":1742,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960261933","Notes":"","BirthDate":"1960-08-20T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ewing, Annabelle","PreferredName":"Annabelle","GenderTypeID":1},{"PersonID":1751,"PhotoURL":"","Notes":"","BirthDate":"1954-04-14T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Craigie, Cathie","PreferredName":"Cathie","GenderTypeID":1},{"PersonID":1752,"PhotoURL":"","Notes":"","BirthDate":"1956-11-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Jamieson, Cathy","PreferredName":"Cathy","GenderTypeID":1},{"PersonID":1754,"PhotoURL":"","Notes":"","BirthDate":"1951-11-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Peattie, Cathy","PreferredName":"Cathy","GenderTypeID":1},{"PersonID":1756,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35819883370","Notes":"","BirthDate":"1944-09-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Grahame, Christine","PreferredName":"Christine","GenderTypeID":1},{"PersonID":1759,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820937650","Notes":"Twitter @Claudiabeamish\\r\\nFacebook: www.facebook.com/claudiabeamish","BirthDate":"1952-08-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Beamish, Claudia","PreferredName":"Claudia","GenderTypeID":1},{"PersonID":1762,"PhotoURL":"","Notes":"","BirthDate":"1942-08-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Elder, Dorothy-Grace","PreferredName":"Dorothy-Grace","GenderTypeID":1},{"PersonID":1768,"PhotoURL":"","Notes":"","BirthDate":"1954-12-22T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Murray, Elaine","PreferredName":"Elaine","GenderTypeID":1},{"PersonID":1769,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35817927427","Notes":"","BirthDate":"1963-05-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Smith, Elaine","PreferredName":"Elaine","GenderTypeID":1},{"PersonID":1770,"PhotoURL":"","Notes":"","BirthDate":"1957-08-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Thomson, Elaine","PreferredName":"Elaine","GenderTypeID":1},{"PersonID":1771,"PhotoURL":"","Notes":"","BirthDate":"1951-07-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Scott, Eleanor","PreferredName":"Eleanor","GenderTypeID":1},{"PersonID":1773,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660228","Notes":"","BirthDate":"1964-08-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Hyslop, Fiona","PreferredName":"Fiona","GenderTypeID":1},{"PersonID":1775,"PhotoURL":"","Notes":"","BirthDate":"1957-12-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McLeod, Fiona","PreferredName":"Fiona","GenderTypeID":1},{"PersonID":1778,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Eadie, Helen","PreferredName":"Helen","GenderTypeID":1},{"PersonID":1781,"PhotoURL":"","Notes":"","BirthDate":"1952-08-29T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McGugan, Irene","PreferredName":"Irene","GenderTypeID":1},{"PersonID":1782,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Oldfather, Irene","PreferredName":"Irene","GenderTypeID":1},{"PersonID":1783,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660953","Notes":"http://www.facebook.com/jackie.baillie","BirthDate":"1964-01-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Baillie, Jackie","PreferredName":"Jackie","GenderTypeID":1},{"PersonID":1791,"PhotoURL":"","Notes":"","BirthDate":"1958-05-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Hughes, Janis","PreferredName":"Janis","GenderTypeID":1},{"PersonID":1793,"PhotoURL":"","Notes":"Facebook: http://www.facebook.com/JeanUrquhartMSP\\r\\nTwitter: https://twitter.com/JeanUrquhartMSP","BirthDate":"1949-05-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Urquhart, Jean","PreferredName":"Jean","GenderTypeID":1},{"PersonID":1803,"PhotoURL":"","Notes":"","BirthDate":"1967-08-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gillon, Karen","PreferredName":"Karen","GenderTypeID":1},{"PersonID":1805,"PhotoURL":"","Notes":"","BirthDate":"1970-01-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Whitefield, Karen","PreferredName":"Karen","GenderTypeID":1},{"PersonID":1807,"PhotoURL":"","Notes":"","BirthDate":"1958-02-16T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Maclean, Kate","PreferredName":"Kate","GenderTypeID":1},{"PersonID":1811,"PhotoURL":"","Notes":"","BirthDate":"1943-05-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ullrich, Kay","PreferredName":"Kay","GenderTypeID":1},{"PersonID":1814,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942002662","Notes":"Declared ethnicity as Scottish.","BirthDate":"1956-12-14T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Fabiani, Linda","PreferredName":"Linda","GenderTypeID":1},{"PersonID":1820,"PhotoURL":"","Notes":"","BirthDate":"1958-11-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Curran, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":1821,"PhotoURL":"","Notes":"\\r\\nDeclared ethnicity as Scottish.","BirthDate":"1945-09-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ewing, Mrs Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":1823,"PhotoURL":"","Notes":"","BirthDate":"1953-04-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Jamieson, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":1826,"PhotoURL":"","Notes":"","BirthDate":"1961-02-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Smith, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":1828,"PhotoURL":"","Notes":"","BirthDate":"1943-04-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"MacDonald, Margo","PreferredName":"Margo","GenderTypeID":1},{"PersonID":1831,"PhotoURL":"","Notes":"","BirthDate":"1951-09-30T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Glen, Marlyn","PreferredName":"Marlyn","GenderTypeID":1},{"PersonID":1832,"PhotoURL":"","Notes":"","BirthDate":"1952-09-30T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Livingstone, Marilyn","PreferredName":"Marilyn","GenderTypeID":1},{"PersonID":1837,"PhotoURL":"","Notes":"","BirthDate":"1960-02-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mulligan, Mary","PreferredName":"Mary","GenderTypeID":1},{"PersonID":1839,"PhotoURL":"","Notes":"","BirthDate":"1947-05-25T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Scanlon, Mary","PreferredName":"Mary","GenderTypeID":1},{"PersonID":1840,"PhotoURL":"","Notes":"\\r\\nDeclared ethnicity as European/Caucasion.","BirthDate":"1943-02-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Macmillan, Maureen","PreferredName":"Maureen","GenderTypeID":1},{"PersonID":1841,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820938288","Notes":"","BirthDate":"1951-06-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Watt, Maureen","PreferredName":"Maureen","GenderTypeID":1},{"PersonID":1845,"PhotoURL":"","Notes":"","BirthDate":"1942-04-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Milne, Nanette","PreferredName":"Nanette","GenderTypeID":1},{"PersonID":1848,"PhotoURL":"http://scottishparliament.thirdlight.com/file/9853640645","Notes":"","BirthDate":"1970-07-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Sturgeon, Nicola","PreferredName":"Nicola","GenderTypeID":1},{"PersonID":1850,"PhotoURL":"","Notes":"District Councillor Gordon District 1988-92","BirthDate":"1946-03-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Radcliffe, Nora","PreferredName":"Nora","GenderTypeID":1},{"PersonID":1853,"PhotoURL":"","Notes":"","BirthDate":"1958-09-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ferguson, Patricia","PreferredName":"Patricia","GenderTypeID":1},{"PersonID":1854,"PhotoURL":"","Notes":"","BirthDate":"1939-10-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Godman, Trish","PreferredName":"Trish","GenderTypeID":1},{"PersonID":1857,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960261831","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"McNeill, Pauline","PreferredName":"Pauline","GenderTypeID":1},{"PersonID":1860,"PhotoURL":"http://scottishparliament.thirdlight.com/file/41869411513","Notes":"","BirthDate":"1963-06-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Grant, Rhoda","PreferredName":"Rhoda","GenderTypeID":1},{"PersonID":1862,"PhotoURL":"","Notes":"","BirthDate":"1950-01-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brankin, Rhona","PreferredName":"Rhona","GenderTypeID":1},{"PersonID":1863,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942247222","Notes":"","BirthDate":"1951-07-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Cunningham, Roseanna","PreferredName":"Roseanna","GenderTypeID":1},{"PersonID":1865,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35922877182","Notes":"","BirthDate":"1951-08-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"White, Sandra","PreferredName":"Sandra","GenderTypeID":1},{"PersonID":1866,"PhotoURL":"","Notes":"","BirthDate":"1961-05-16T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Boyack, Sarah","PreferredName":"Sarah","GenderTypeID":1},{"PersonID":1869,"PhotoURL":"","Notes":"2003 Affirmation","BirthDate":"1946-09-14T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Baird, Shiona","PreferredName":"Shiona","GenderTypeID":1},{"PersonID":1870,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820938944","Notes":"","BirthDate":"1966-05-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Robison, Shona","PreferredName":"Shona","GenderTypeID":1},{"PersonID":1871,"PhotoURL":"","Notes":"","BirthDate":"1964-02-02T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Deacon, Susan","PreferredName":"Susan","GenderTypeID":1},{"PersonID":1873,"PhotoURL":"","Notes":"","BirthDate":"1946-12-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Jackson, Dr Sylvia","PreferredName":"Sylvia","GenderTypeID":1},{"PersonID":1876,"PhotoURL":"","Notes":"","BirthDate":"1953-11-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Marwick, Tricia","PreferredName":"Tricia","GenderTypeID":1},{"PersonID":1877,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Alexander, Ms Wendy","PreferredName":"Wendy","GenderTypeID":1},{"PersonID":1878,"PhotoURL":"","Notes":"\\r\\nMade a solemn affirmation in Gaelic.","BirthDate":"1929-07-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ewing, Dr Winnie","PreferredName":"Winnie","GenderTypeID":1},{"PersonID":1882,"PhotoURL":"","Notes":"","BirthDate":"1951-05-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ingram, Adam","PreferredName":"Adam","GenderTypeID":2},{"PersonID":1888,"PhotoURL":"","Notes":"","BirthDate":"1945-04-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Morgan, Alasdair","PreferredName":"Alasdair","GenderTypeID":2},{"PersonID":1889,"PhotoURL":"","Notes":"\\r\\nRepeated the Oath in Gaelic.","BirthDate":"1968-11-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Morrison, Mr Alasdair","PreferredName":"Alasdair","GenderTypeID":2},{"PersonID":1892,"PhotoURL":"","Notes":"","BirthDate":"1949-04-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Fergusson, Alex","PreferredName":"Alex","GenderTypeID":2},{"PersonID":1893,"PhotoURL":"","Notes":"","BirthDate":"1961-07-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Johnstone, Alex","PreferredName":"Alex","GenderTypeID":2},{"PersonID":1894,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820937596","Notes":"\\r\\nDeclared ethnicity as Scottish.","BirthDate":"1951-08-22T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Neil, Alex","PreferredName":"Alex","GenderTypeID":2},{"PersonID":1895,"PhotoURL":"","Notes":"","BirthDate":"1954-12-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Salmond, Alex","PreferredName":"Alex","GenderTypeID":2},{"PersonID":1901,"PhotoURL":"","Notes":"","BirthDate":"1954-08-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wilson, Allan","PreferredName":"Allan","GenderTypeID":2},{"PersonID":1906,"PhotoURL":"","Notes":"","BirthDate":"1944-04-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Welsh, Andrew","PreferredName":"Andrew","GenderTypeID":2},{"PersonID":1907,"PhotoURL":"","Notes":"","BirthDate":"1970-12-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wilson, Andrew","PreferredName":"Andrew","GenderTypeID":2},{"PersonID":1908,"PhotoURL":"","Notes":"","BirthDate":"1962-03-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Kerr, Andy","PreferredName":"Andy","GenderTypeID":2},{"PersonID":1911,"PhotoURL":"","Notes":"","BirthDate":"1964-09-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"MacKay, Angus","PreferredName":"Angus","GenderTypeID":2},{"PersonID":1915,"PhotoURL":"","Notes":"","BirthDate":"1940-02-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ahmad, Bashir","PreferredName":"Bashir","GenderTypeID":2},{"PersonID":1916,"PhotoURL":"","Notes":"","BirthDate":"1970-05-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wallace, Ben","PreferredName":"Ben","GenderTypeID":2},{"PersonID":1921,"PhotoURL":"","Notes":"","BirthDate":"1963-12-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wilson, Bill","PreferredName":"Bill","GenderTypeID":2},{"PersonID":1926,"PhotoURL":"","Notes":"2003 Affirmation","BirthDate":"1948-06-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Adam, Brian","PreferredName":"Brian","GenderTypeID":2},{"PersonID":1928,"PhotoURL":"","Notes":"","BirthDate":"1961-06-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Fitzpatrick, Brian","PreferredName":"Brian","GenderTypeID":2},{"PersonID":1930,"PhotoURL":"","Notes":"","BirthDate":"1958-01-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Monteith, Mr Brian","PreferredName":"Brian","GenderTypeID":2},{"PersonID":1931,"PhotoURL":"","Notes":"","BirthDate":"1964-03-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Muldoon, Bristow","PreferredName":"Bristow","GenderTypeID":2},{"PersonID":1932,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818634739","Notes":"","BirthDate":"1955-02-16T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Crawford, Bruce","PreferredName":"Bruce","GenderTypeID":2},{"PersonID":1943,"PhotoURL":"","Notes":"","BirthDate":"1944-05-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brodie, Chic","PreferredName":"Chic","GenderTypeID":2},{"PersonID":1944,"PhotoURL":"","Notes":"2003 Affirmation","BirthDate":"1952-07-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ballance, Chris","PreferredName":"Chris","GenderTypeID":2},{"PersonID":1950,"PhotoURL":"","Notes":"","BirthDate":"1938-08-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Campbell, Colin","PreferredName":"Colin","GenderTypeID":2},{"PersonID":1956,"PhotoURL":"","Notes":"","BirthDate":"1943-01-25T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Davidson, Mr David","PreferredName":"David","GenderTypeID":2},{"PersonID":1961,"PhotoURL":"","Notes":"","BirthDate":"1952-08-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McLetchie, David","PreferredName":"David","GenderTypeID":2},{"PersonID":1962,"PhotoURL":"","Notes":"","BirthDate":"1962-05-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mundell, David","PreferredName":"David","GenderTypeID":2},{"PersonID":1963,"PhotoURL":"","Notes":"","BirthDate":"1946-12-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Petrie, Dave","PreferredName":"Dave","GenderTypeID":2},{"PersonID":1968,"PhotoURL":"","Notes":"","BirthDate":"1942-08-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Canavan, Dennis","PreferredName":"Dennis","GenderTypeID":2},{"PersonID":1970,"PhotoURL":"","Notes":"","BirthDate":"1952-07-28T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McNulty, Des","PreferredName":"Des","GenderTypeID":2},{"PersonID":1972,"PhotoURL":"","Notes":"Brahler ID changed from 0027 to 0027000 by AJP on 06/12/00 because Bill Butler assigned brahler ID of 0027.","BirthDate":"1937-08-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Dewar, Donald","PreferredName":"Donald","GenderTypeID":2},{"PersonID":1973,"PhotoURL":"","Notes":"","BirthDate":"1933-04-02T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gorrie, Donald","PreferredName":"Donald","GenderTypeID":2},{"PersonID":1985,"PhotoURL":"","Notes":"","BirthDate":"1973-10-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Hamilton, Mr Duncan","PreferredName":"Duncan","GenderTypeID":2},{"PersonID":1986,"PhotoURL":"","Notes":"","BirthDate":"1950-09-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McNeil, Duncan","PreferredName":"Duncan","GenderTypeID":2},{"PersonID":1988,"PhotoURL":"","Notes":"","BirthDate":"1942-09-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brocklebank, Ted","PreferredName":"Ted","GenderTypeID":2},{"PersonID":1990,"PhotoURL":"","Notes":"","BirthDate":"1954-02-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Robson, Euan","PreferredName":"Euan","GenderTypeID":2},{"PersonID":1994,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35943512647","Notes":"Information on Fergus Ewing can also be found on http://www.snp.org","BirthDate":"1957-09-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ewing, Fergus","PreferredName":"Fergus","GenderTypeID":2},{"PersonID":1996,"PhotoURL":"","Notes":"","BirthDate":"1962-07-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McAveety, Mr Frank","PreferredName":"Frank","GenderTypeID":2},{"PersonID":2003,"PhotoURL":"","Notes":"","BirthDate":"1956-07-16T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Lyon, George","PreferredName":"George","GenderTypeID":2},{"PersonID":2005,"PhotoURL":"","Notes":"","BirthDate":"1939-06-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Reid, Mr George","PreferredName":"George","GenderTypeID":2},{"PersonID":2010,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855484744","Notes":"","BirthDate":"1942-11-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Paterson, Gil","PreferredName":"Gil","GenderTypeID":2},{"PersonID":2013,"PhotoURL":"","Notes":"","BirthDate":"1948-08-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Jackson, Gordon","PreferredName":"Gordon","GenderTypeID":2},{"PersonID":2015,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571580","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Lindhurst, Gordon","PreferredName":"Gordon","GenderTypeID":2},{"PersonID":2028,"PhotoURL":"","Notes":"","BirthDate":"1948-06-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McLeish, Henry","PreferredName":"Henry","GenderTypeID":2},{"PersonID":2029,"PhotoURL":"","Notes":"","BirthDate":"1952-02-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Henry, Hugh","PreferredName":"Hugh","GenderTypeID":2},{"PersonID":2030,"PhotoURL":"","Notes":"","BirthDate":"1952-05-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"O'Donnell, Hugh","PreferredName":"Hugh","GenderTypeID":2},{"PersonID":2033,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35817741283","Notes":"","BirthDate":"1957-06-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gray, Iain","PreferredName":"Iain","GenderTypeID":2},{"PersonID":2038,"PhotoURL":"","Notes":"","BirthDate":"1960-05-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Smith, Iain","PreferredName":"Iain","GenderTypeID":2},{"PersonID":2044,"PhotoURL":"","Notes":"","BirthDate":"1941-03-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Jenkins, Ian","PreferredName":"Ian","GenderTypeID":2},{"PersonID":2049,"PhotoURL":"","Notes":"","BirthDate":"1940-04-02T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McKee, Ian","PreferredName":"Ian","GenderTypeID":2},{"PersonID":2051,"PhotoURL":"","Notes":"23-Nov-53\\r\\nBrahler ID as Elected MSP was 0119","BirthDate":"1953-11-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Welsh, Ian","PreferredName":"Ian","GenderTypeID":2},{"PersonID":2052,"PhotoURL":"","Notes":"","BirthDate":"1960-06-30T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McConnell, Jack","PreferredName":"Jack","GenderTypeID":2},{"PersonID":2056,"PhotoURL":"","Notes":"","BirthDate":"1942-07-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Douglas-Hamilton, Lord James","PreferredName":"James","GenderTypeID":2},{"PersonID":2059,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783690470","Notes":"","BirthDate":"1963-10-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Kelly, James","PreferredName":"James","GenderTypeID":2},{"PersonID":2066,"PhotoURL":"","Notes":"","BirthDate":"1949-10-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McGrigor, Jamie","PreferredName":"Jamie","GenderTypeID":2},{"PersonID":2068,"PhotoURL":"","Notes":"","BirthDate":"1954-06-16T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Stone, Jamie","PreferredName":"Jamie","GenderTypeID":2},{"PersonID":2074,"PhotoURL":"","Notes":"","BirthDate":"1947-03-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mather, Jim","PreferredName":"Jim","GenderTypeID":2},{"PersonID":2077,"PhotoURL":"","Notes":"","BirthDate":"1954-08-25T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wallace, Mr Jim","PreferredName":"Jim","GenderTypeID":2},{"PersonID":2080,"PhotoURL":"http://scottishparliament.thirdlight.com/file/9853504141","Notes":"","BirthDate":"1957-07-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Lamont, Johann","PreferredName":"Johann","GenderTypeID":1},{"PersonID":2085,"PhotoURL":"","Notes":"Repeated the Oath in Gaelic.","BirthDate":"1934-08-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Munro, John Farquhar","PreferredName":"John Farquhar","GenderTypeID":2},{"PersonID":2090,"PhotoURL":"","Notes":"","BirthDate":"1948-02-13T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McAllion, Mr John","PreferredName":"John","GenderTypeID":2},{"PersonID":2098,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35943496226","Notes":"","BirthDate":"1964-04-13T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Swinney, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2099,"PhotoURL":"","Notes":"","BirthDate":"1930-12-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Young, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2100,"PhotoURL":"","Notes":"","BirthDate":"1948-12-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Home Robertson, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2103,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960260789","Notes":"","BirthDate":"1961-12-20T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brown, Keith","PreferredName":"Keith","GenderTypeID":2},{"PersonID":2105,"PhotoURL":"","Notes":"Resigned from Conservative Party and Joined Scottish Peoples Alliance 31 March 2003","BirthDate":"1938-11-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Harding, Mr Keith","PreferredName":"Keith","GenderTypeID":2},{"PersonID":2106,"PhotoURL":"","Notes":"","BirthDate":"1949-06-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Raffan, Mr Keith","PreferredName":"Keith","GenderTypeID":2},{"PersonID":2108,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35921454568","Notes":"Twitter - http://twitter.com/kenmacintoshmsp \\r\\nFacebook - http://www.facebook.com/pages/Ken-Macintosh-MSP/135822889783835","BirthDate":"1962-01-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Macintosh, Ken","PreferredName":"Ken","GenderTypeID":2},{"PersonID":2110,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855484389","Notes":"","BirthDate":"1961-09-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gibson, Kenneth","PreferredName":"Kenneth","GenderTypeID":2},{"PersonID":2112,"PhotoURL":"","Notes":"","BirthDate":"1958-04-28T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"MacAskill, Kenny","PreferredName":"Kenny","GenderTypeID":2},{"PersonID":2117,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942002807","Notes":"","BirthDate":"1957-01-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Macdonald, Lewis","PreferredName":"Lewis","GenderTypeID":2},{"PersonID":2118,"PhotoURL":"","Notes":"","BirthDate":"1957-04-29T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Quinan, Mr Lloyd","PreferredName":"Lloyd","GenderTypeID":2},{"PersonID":2122,"PhotoURL":"","Notes":"","BirthDate":"1955-06-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McIntosh, Mrs Lyndsay","PreferredName":"Lyndsay","GenderTypeID":1},{"PersonID":2123,"PhotoURL":"","Notes":"","BirthDate":"1949-03-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Chisholm, Malcolm","PreferredName":"Malcolm","GenderTypeID":2},{"PersonID":2126,"PhotoURL":"","Notes":"","BirthDate":"1971-06-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Ballard, Mark","PreferredName":"Mark","GenderTypeID":2},{"PersonID":2127,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781781662","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Ruskell, Mark","PreferredName":"Mark","GenderTypeID":2},{"PersonID":2133,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660631","Notes":"","BirthDate":"1970-09-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Matheson, Michael","PreferredName":"Michael","GenderTypeID":2},{"PersonID":2134,"PhotoURL":"","Notes":"","BirthDate":"1961-09-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McMahon, Michael","PreferredName":"Michael","GenderTypeID":2},{"PersonID":2135,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35819641476","Notes":"Declared ethnicity as European, Scottish & British.\\r\\nRepeated the Oath in Gaelic.","BirthDate":"1953-08-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Russell, Michael","PreferredName":"Michael","GenderTypeID":2},{"PersonID":2140,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783809943","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Rumbles, Mike","PreferredName":"Mike","GenderTypeID":2},{"PersonID":2142,"PhotoURL":"","Notes":"","BirthDate":"1949-05-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Watson, Mike","PreferredName":"Mike","GenderTypeID":2},{"PersonID":2148,"PhotoURL":"","Notes":"","BirthDate":"1950-09-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Tosh, Murray","PreferredName":"Murray","GenderTypeID":2},{"PersonID":2152,"PhotoURL":"","Notes":"\\r\\nRepeated the Oath in Catalan\\r\\nResigned 10/08/01","BirthDate":"1948-01-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Johnston, Nick","PreferredName":"Nick","GenderTypeID":2},{"PersonID":2154,"PhotoURL":"","Notes":"","BirthDate":"1960-03-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Stephen, Nicol","PreferredName":"Nicol","GenderTypeID":2},{"PersonID":2159,"PhotoURL":"","Notes":"","BirthDate":"1967-03-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Martin, Paul","PreferredName":"Paul","GenderTypeID":2},{"PersonID":2167,"PhotoURL":"","Notes":"","BirthDate":"1952-02-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Peacock, Peter","PreferredName":"Peter","GenderTypeID":2},{"PersonID":2172,"PhotoURL":"","Notes":"","BirthDate":"1939-06-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gallie, Phil","PreferredName":"Phil","GenderTypeID":2},{"PersonID":2180,"PhotoURL":"http://scottishparliament.thirdlight.com/file/9853506741","Notes":"","BirthDate":"1969-05-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Lochhead, Richard","PreferredName":"Richard","GenderTypeID":2},{"PersonID":2182,"PhotoURL":"","Notes":"","BirthDate":"1942-10-22T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Simpson, Dr Richard","PreferredName":"Richard","GenderTypeID":2},{"PersonID":2185,"PhotoURL":"","Notes":"","BirthDate":"1947-12-25T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brown, Robert","PreferredName":"Robert","GenderTypeID":2},{"PersonID":2188,"PhotoURL":"","Notes":"","BirthDate":"1940-08-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Harper, Robin","PreferredName":"Robin","GenderTypeID":2},{"PersonID":2201,"PhotoURL":"","Notes":"","BirthDate":"1961-06-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Kane, Rosie","PreferredName":"Rosie","GenderTypeID":1},{"PersonID":2202,"PhotoURL":"","Notes":"","BirthDate":"1947-02-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Finnie, Ross","PreferredName":"Ross","GenderTypeID":2},{"PersonID":2205,"PhotoURL":"","Notes":"Brahler ID prior to 14/05/2001 when resigned was 0037","BirthDate":"1945-08-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Galbraith, Mr Sam","PreferredName":"Sam","GenderTypeID":2},{"PersonID":2207,"PhotoURL":"","Notes":"","BirthDate":"1962-03-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Barrie, Scott","PreferredName":"Scott","GenderTypeID":2},{"PersonID":2215,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820478663","Notes":"","BirthDate":"1946-10-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Stevenson, Stewart","PreferredName":"Stewart","GenderTypeID":2},{"PersonID":2223,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820938602","Notes":"","BirthDate":"1966-05-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Scott, Tavish","PreferredName":"Tavish","GenderTypeID":2},{"PersonID":2225,"PhotoURL":"","Notes":"","BirthDate":"1964-03-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Sheridan, Tommy","PreferredName":"Tommy","GenderTypeID":2},{"PersonID":2228,"PhotoURL":"","Notes":"","BirthDate":"1954-04-28T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McCabe, Tom","PreferredName":"Tom","GenderTypeID":2},{"PersonID":2234,"PhotoURL":"","Notes":"","BirthDate":"1947-04-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Aitken, Bill","PreferredName":"Bill","GenderTypeID":2},{"PersonID":2247,"PhotoURL":"","Notes":"","BirthDate":"1944-04-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Arbuckle, Mr Andrew","PreferredName":"Andrew","GenderTypeID":2},{"PersonID":2252,"PhotoURL":"","Notes":"","BirthDate":"1945-12-25T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Pringle, Mike","PreferredName":"Mike","GenderTypeID":2},{"PersonID":2263,"PhotoURL":"","Notes":"","BirthDate":"1938-03-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Steel, Sir David","PreferredName":"David","GenderTypeID":2},{"PersonID":2345,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35786761546","Notes":"See also http://www.vote-tory-for-ayr.org/johnscott.html","BirthDate":"1951-06-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Scott, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2364,"PhotoURL":"","Notes":"assigned Brahler ID 0027 from 29/11/00 -","BirthDate":"1956-03-30T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Butler, Bill","PreferredName":"Bill","GenderTypeID":2},{"PersonID":2390,"PhotoURL":"","Notes":"","BirthDate":"1939-12-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Turner, Dr Jean","PreferredName":"Jean","GenderTypeID":1},{"PersonID":2394,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35800892126","Notes":"Formally returned as regional MSP Mid-Scotland and Fife on 14/08/01\\r\\nTwitter: @murdo_fraser\\r\\nFacebook: www.facebook.com/MSPMurdoFraser","BirthDate":"1965-09-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Fraser, Murdo","PreferredName":"Murdo","GenderTypeID":2},{"PersonID":2487,"PhotoURL":"","Notes":"","BirthDate":"1971-08-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McLeod, Aileen","PreferredName":"Aileen","GenderTypeID":1},{"PersonID":2595,"PhotoURL":"","Notes":"","BirthDate":"1975-06-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brown, Gavin","PreferredName":"Gavin","GenderTypeID":2},{"PersonID":2596,"PhotoURL":"","Notes":"","BirthDate":"1974-08-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Brownlee, Derek","PreferredName":"Derek","GenderTypeID":2},{"PersonID":2603,"PhotoURL":"","Notes":"","BirthDate":"1974-05-29T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Baker, Richard","PreferredName":"Richard","GenderTypeID":2},{"PersonID":2610,"PhotoURL":"","Notes":"","BirthDate":"1956-11-28T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wilson, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2615,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820937738","Notes":"Twitter @GeorgeAdam","BirthDate":"1969-06-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Adam, George","PreferredName":"George","GenderTypeID":2},{"PersonID":2633,"PhotoURL":"http://scottishparliament.thirdlight.com/file/9853240684","Notes":"","BirthDate":"1971-03-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Baker, Claire","PreferredName":"Claire","GenderTypeID":1},{"PersonID":2641,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35800892437","Notes":"","BirthDate":"1971-05-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Allan, Dr Alasdair","PreferredName":"Alasdair","GenderTypeID":2},{"PersonID":2651,"PhotoURL":"","Notes":"","BirthDate":"1965-05-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Tolson, Jim","PreferredName":"Jim","GenderTypeID":2},{"PersonID":2665,"PhotoURL":"","Notes":"","BirthDate":"1948-03-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Byrne, Ms Rosemary","PreferredName":"Rosemary","GenderTypeID":1},{"PersonID":2673,"PhotoURL":"","Notes":"","BirthDate":"1953-06-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Campbell, Roderick","PreferredName":"Roderick","GenderTypeID":2},{"PersonID":2674,"PhotoURL":"","Notes":"","BirthDate":"1949-09-20T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Thompson, Dave","PreferredName":"Dave","GenderTypeID":2},{"PersonID":2675,"PhotoURL":"","Notes":"","BirthDate":"1945-10-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gibson, Rob","PreferredName":"Rob","GenderTypeID":2},{"PersonID":2678,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35799295215","Notes":"","BirthDate":"1959-04-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Carlaw, Jackson","PreferredName":"Jackson","GenderTypeID":2},{"PersonID":2686,"PhotoURL":"","Notes":"BBC","BirthDate":"1930-07-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Swinburne, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2767,"PhotoURL":"","Notes":"","BirthDate":"1961-05-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Curran, Frances","PreferredName":"Frances","GenderTypeID":1},{"PersonID":2826,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942003780","Notes":"","BirthDate":"1953-03-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Dornan, James","PreferredName":"James","GenderTypeID":2},{"PersonID":2853,"PhotoURL":"","Notes":"","BirthDate":"1946-12-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Pentland, John","PreferredName":"John","GenderTypeID":2},{"PersonID":2866,"PhotoURL":"","Notes":"","BirthDate":"1974-01-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Purvis, Jeremy","PreferredName":"Jeremy","GenderTypeID":2},{"PersonID":2876,"PhotoURL":"","Notes":"","BirthDate":"1963-12-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Maxwell, Stewart","PreferredName":"Stewart","GenderTypeID":2},{"PersonID":2877,"PhotoURL":"","Notes":"","BirthDate":"1948-03-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"May, Christine","PreferredName":"Christine","GenderTypeID":1},{"PersonID":2892,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783690519","Notes":"","BirthDate":"1973-03-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Harvie, Patrick","PreferredName":"Patrick","GenderTypeID":2},{"PersonID":2902,"PhotoURL":"","Notes":"","BirthDate":"1965-03-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Leckie, Carolyn","PreferredName":"Carolyn","GenderTypeID":1},{"PersonID":2947,"PhotoURL":"","Notes":"","BirthDate":"1961-05-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McFee, Mr Bruce","PreferredName":"Bruce","GenderTypeID":2},{"PersonID":2963,"PhotoURL":"","Notes":"","BirthDate":"1966-03-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McLaughlin, Anne","PreferredName":"Anne","GenderTypeID":1},{"PersonID":3004,"PhotoURL":"","Notes":"","BirthDate":"1959-06-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Fox, Colin","PreferredName":"Colin","GenderTypeID":2},{"PersonID":3061,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783809913","Notes":"Facebook- https://www.facebook.com/margaretmitchell2016","BirthDate":"1952-11-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mitchell, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":3101,"PhotoURL":"","Notes":"","BirthDate":"1956-11-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Malik, Hanzala","PreferredName":"Hanzala","GenderTypeID":2},{"PersonID":3103,"PhotoURL":"","Notes":"","BirthDate":"1960-03-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Martin, Campbell","PreferredName":"Campbell","GenderTypeID":2},{"PersonID":3129,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35799134774 ","Notes":"","BirthDate":"1956-07-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Kidd, Bill","PreferredName":"Bill","GenderTypeID":2},{"PersonID":3538,"PhotoURL":"","Notes":"","BirthDate":"1951-10-28T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Gordon, Charlie","PreferredName":"Charlie","GenderTypeID":2},{"PersonID":3743,"PhotoURL":"","Notes":"","BirthDate":"1954-04-16T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Don, Nigel","PreferredName":"Nigel","GenderTypeID":2},{"PersonID":3745,"PhotoURL":"","Notes":"","BirthDate":"1956-08-14T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Robertson, Dennis","PreferredName":"Dennis","GenderTypeID":2},{"PersonID":3746,"PhotoURL":"","Notes":"","BirthDate":"1944-09-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Harvie, Christopher","PreferredName":"Christopher","GenderTypeID":2},{"PersonID":3749,"PhotoURL":"","Notes":"","BirthDate":"1959-09-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Tymkewycz, Stefan","PreferredName":"Stefan","GenderTypeID":2},{"PersonID":3750,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783690940","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Somerville, Shirley-Anne","PreferredName":"Shirley-Anne","GenderTypeID":1},{"PersonID":3751,"PhotoURL":"http://scottishparliament.thirdlight.com/file/38395638303","Notes":"","BirthDate":"1951-10-17T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Beattie, Colin","PreferredName":"Colin","GenderTypeID":2},{"PersonID":3758,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820938486 ","Notes":"","BirthDate":"1979-05-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Hepburn, Jamie","PreferredName":"Jamie","GenderTypeID":2},{"PersonID":3759,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960260890","Notes":"","BirthDate":"1968-03-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McKelvie, Christina","PreferredName":"Christina","GenderTypeID":1},{"PersonID":3763,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820938765","Notes":"Twitter: @StuMcMillanSNP\\r\\nFacebook: Stuart McMillan MSP","BirthDate":"1972-05-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McMillan, Stuart","PreferredName":"Stuart","GenderTypeID":2},{"PersonID":3771,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820939764","Notes":"","BirthDate":"1973-05-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Doris, Bob","PreferredName":"Bob","GenderTypeID":2},{"PersonID":3775,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960260104","Notes":"","BirthDate":"1980-05-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Campbell, Aileen","PreferredName":"Aileen","GenderTypeID":1},{"PersonID":3806,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942002372","Notes":"","BirthDate":"1956-05-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Stewart, David","PreferredName":"David","GenderTypeID":2},{"PersonID":3811,"PhotoURL":"","Notes":"","BirthDate":"1942-01-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Foulkes, George","PreferredName":"George","GenderTypeID":2},{"PersonID":3812,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781781656","Notes":"","BirthDate":"1981-08-28T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Dugdale, Kezia","PreferredName":"Kezia","GenderTypeID":1},{"PersonID":3815,"PhotoURL":"","Notes":"","BirthDate":"1973-09-14T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Park, John","PreferredName":"John","GenderTypeID":2},{"PersonID":3824,"PhotoURL":"","Notes":"","BirthDate":"1949-01-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McDougall, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":3896,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855661618","Notes":"","BirthDate":"1967-08-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McArthur, Liam","PreferredName":"Liam","GenderTypeID":2},{"PersonID":3901,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35800493586","Notes":"","BirthDate":"1967-04-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"FitzPatrick, Joe","PreferredName":"Joe","GenderTypeID":2},{"PersonID":3907,"PhotoURL":"http://scottishparliament.thirdlight.com/file/36076831535","Notes":"","BirthDate":"1958-05-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Coffey, Willie","PreferredName":"Willie","GenderTypeID":2},{"PersonID":3983,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687661","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Golden, Maurice","PreferredName":"Maurice","GenderTypeID":2},{"PersonID":3985,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783689384","Notes":"","BirthDate":"1987-09-21T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Thomson, Ross","PreferredName":"Ross","GenderTypeID":2},{"PersonID":3994,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783686696","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Simpson, Graham","PreferredName":"Graham","GenderTypeID":2},{"PersonID":4014,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818225410","Notes":"","BirthDate":"1960-02-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Smith, Liz","PreferredName":"Liz","GenderTypeID":1},{"PersonID":4016,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35922877680","Notes":"facebook.com/JohnLamontBorders/\\r\\nTwitter: @john2win","BirthDate":"1976-04-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Lamont, John","PreferredName":"John","GenderTypeID":2},{"PersonID":4074,"PhotoURL":"","Notes":"","BirthDate":"1952-04-22T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Whitton, David","PreferredName":"David","GenderTypeID":2},{"PersonID":4080,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"McInnes, Alison","PreferredName":"Alison","GenderTypeID":1},{"PersonID":4086,"PhotoURL":"","Notes":"","BirthDate":"1962-11-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Hume, Jim","PreferredName":"Jim","GenderTypeID":2},{"PersonID":4934,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818497919","Notes":"","BirthDate":"1965-10-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Johnstone, Alison","PreferredName":"Alison","GenderTypeID":1},{"PersonID":4938,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960260779","Notes":"","BirthDate":"1950-06-12T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Lyle, Richard","PreferredName":"Richard","GenderTypeID":2},{"PersonID":4939,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660763","Notes":"","BirthDate":"1963-10-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"MacDonald, Angus","PreferredName":"Angus","GenderTypeID":2},{"PersonID":4940,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820938229","Notes":"","BirthDate":"1967-08-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Adamson, Clare","PreferredName":"Clare","GenderTypeID":1},{"PersonID":4941,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35922512428 ","Notes":"","BirthDate":"1985-04-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Yousaf, Humza","PreferredName":"Humza","GenderTypeID":2},{"PersonID":4947,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783690556","Notes":"","BirthDate":"1956-12-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Finnie, John","PreferredName":"John","GenderTypeID":2},{"PersonID":4948,"PhotoURL":"","Notes":"","BirthDate":"1958-11-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"MacKenzie, Mike","PreferredName":"Mike","GenderTypeID":2},{"PersonID":4951,"PhotoURL":"http://scottishparliament.thirdlight.com/file/9853519283","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"McAlpine, Joan","PreferredName":"Joan","GenderTypeID":1},{"PersonID":4952,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818225376","Notes":"twitter@paulwheelhouse\\r\\nf: PaulWheelhouseMSP","BirthDate":"1970-06-22T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wheelhouse, Paul","PreferredName":"Paul","GenderTypeID":2},{"PersonID":4955,"PhotoURL":"","Notes":"","BirthDate":"1968-02-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Eadie, Jim","PreferredName":"Jim","GenderTypeID":2},{"PersonID":4956,"PhotoURL":"","Notes":"","BirthDate":"1959-12-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Keir, Colin","PreferredName":"Colin","GenderTypeID":2},{"PersonID":4964,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35817648204","Notes":"","BirthDate":"1980-06-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McDonald, Mark","PreferredName":"Mark","GenderTypeID":2},{"PersonID":4965,"PhotoURL":"","Notes":"","BirthDate":"1964-03-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Allard, Christian","PreferredName":"Christian","GenderTypeID":2},{"PersonID":4966,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660444","Notes":"Facebook – derekmackaysnp\\r\\nTwitter - derekmackaysnp","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Mackay, Derek","PreferredName":"Derek","GenderTypeID":2},{"PersonID":4976,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783689179","Notes":"","BirthDate":"1978-11-10T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Davidson, Ruth","PreferredName":"Ruth","GenderTypeID":1},{"PersonID":4981,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687368","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Ross, Douglas","PreferredName":"Douglas","GenderTypeID":2},{"PersonID":4982,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783689774","Notes":"","BirthDate":"1961-03-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mountain, Edward","PreferredName":"Edward","GenderTypeID":2},{"PersonID":4984,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Buchanan, Cameron","PreferredName":"Cameron","GenderTypeID":2},{"PersonID":4987,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783685351","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Briggs, Miles","PreferredName":"Miles","GenderTypeID":2},{"PersonID":5009,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687229","Notes":"","BirthDate":"1967-09-27T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Rennie, Willie","PreferredName":"Willie","GenderTypeID":2},{"PersonID":5034,"PhotoURL":"http://scottishparliament.thirdlight.com/file/9853514522","Notes":"Facebook: facebook.com/jennymarramsp\\r\\nTwitter: @jennymarra","BirthDate":"1977-11-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Marra, Jenny","PreferredName":"Jenny","GenderTypeID":1},{"PersonID":5035,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Brennan, Lesley","PreferredName":"Lesley","GenderTypeID":1},{"PersonID":5038,"PhotoURL":"","Notes":"","BirthDate":"1955-11-05T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Baxter, Jayne","PreferredName":"Jayne","GenderTypeID":1},{"PersonID":5041,"PhotoURL":"","Notes":"","BirthDate":"1984-07-04T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McMahon, Siobhan","PreferredName":"Siobhan","GenderTypeID":1},{"PersonID":5042,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660595","Notes":"","BirthDate":"1985-10-19T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Griffin, Mark","PreferredName":"Mark","GenderTypeID":2},{"PersonID":5047,"PhotoURL":"","Notes":"","BirthDate":"1970-01-30T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McTaggart, Anne","PreferredName":"Anne","GenderTypeID":1},{"PersonID":5054,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35817927315","Notes":"","BirthDate":"1969-03-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Findlay, Neil","PreferredName":"Neil","GenderTypeID":2},{"PersonID":5057,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Pearson, Graeme","PreferredName":"Graeme","GenderTypeID":2},{"PersonID":5059,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818225238","Notes":"","BirthDate":"1954-03-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Fee, Mary","PreferredName":"Mary","GenderTypeID":1},{"PersonID":5060,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35960261503","Notes":"","BirthDate":"1983-09-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Bibby, Neil","PreferredName":"Neil","GenderTypeID":2},{"PersonID":5074,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35817741458","Notes":"","BirthDate":"1960-01-02T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"MacDonald, Gordon","PreferredName":"Gordon","GenderTypeID":2},{"PersonID":5075,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35800414488","Notes":"","BirthDate":"1961-03-13T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Torrance, David","PreferredName":"David","GenderTypeID":2},{"PersonID":5078,"PhotoURL":"","Notes":"","BirthDate":"1942-03-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Walker, Bill","PreferredName":"Bill","GenderTypeID":2},{"PersonID":5079,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Smith, Drew","PreferredName":"Drew","GenderTypeID":2},{"PersonID":5080,"PhotoURL":"","Notes":"","BirthDate":"1952-05-09T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"McCulloch, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":5106,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818497490","Notes":"","BirthDate":"1968-06-03T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Stewart, Kevin","PreferredName":"Kevin","GenderTypeID":2},{"PersonID":5107,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35802798381","Notes":"","BirthDate":"1962-10-29T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Dey, Graeme","PreferredName":"Graeme","GenderTypeID":2},{"PersonID":5108,"PhotoURL":"","Notes":"","BirthDate":"1949-12-07T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Burgess, Margaret","PreferredName":"Margaret","GenderTypeID":1},{"PersonID":5109,"PhotoURL":"","Notes":"","BirthDate":"1982-07-31T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Biagi, Marco","PreferredName":"Marco","GenderTypeID":2},{"PersonID":5110,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820937486","Notes":"","BirthDate":"1957-05-15T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mason, John","PreferredName":"John","GenderTypeID":2},{"PersonID":5119,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35786781393 ","Notes":"","BirthDate":"1963-11-30T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Rowley, Alex","PreferredName":"Alex","GenderTypeID":2},{"PersonID":5556,"PhotoURL":"","Notes":"https://twitter.com/cara_hilton","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Hilton, Cara","PreferredName":"Cara","GenderTypeID":1},{"PersonID":5578,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571350","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Martin, Gillian","PreferredName":"Gillian","GenderTypeID":1},{"PersonID":5579,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942063441","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Leonard, Richard","PreferredName":"Richard","GenderTypeID":2},{"PersonID":5580,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687362","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Lennon, Monica","PreferredName":"Monica","GenderTypeID":1},{"PersonID":5586,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783690447","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Sarwar, Anas","PreferredName":"Anas","GenderTypeID":2},{"PersonID":5587,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35921454674","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Evans, Mairi","PreferredName":"Mairi","GenderTypeID":1},{"PersonID":5591,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35855660525","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Ross, Gail","PreferredName":"Gail","GenderTypeID":1},{"PersonID":5592,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688795","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Freeman, Jeane","PreferredName":"Jeane","GenderTypeID":1},{"PersonID":5596,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783689308","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"MacGregor, Fulton","PreferredName":"Fulton","GenderTypeID":2},{"PersonID":5598,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783686177","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Maguire, Ruth","PreferredName":"Ruth","GenderTypeID":1},{"PersonID":5604,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35820937956","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Johnson, Daniel","PreferredName":"Daniel","GenderTypeID":2},{"PersonID":5605,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783686850","Notes":"","BirthDate":"1974-03-08T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Denham, Ash","PreferredName":"Ash","GenderTypeID":1},{"PersonID":5608,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783686780","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Macpherson, Ben","PreferredName":"Ben","GenderTypeID":2},{"PersonID":5612,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688223","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"McKee, Ivan","PreferredName":"Ivan","GenderTypeID":2},{"PersonID":5613,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783686815","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Gilruth, Jenny","PreferredName":"Jenny","GenderTypeID":1},{"PersonID":5618,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687418","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Haughey, Clare","PreferredName":"Clare","GenderTypeID":1},{"PersonID":5621,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35942002221","Notes":"","BirthDate":"1990-04-06T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Forbes, Kate","PreferredName":"Kate","GenderTypeID":1},{"PersonID":5622,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687929","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Mackay, Rona","PreferredName":"Rona","GenderTypeID":1},{"PersonID":5638,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688355","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Smyth, Colin","PreferredName":"Colin","GenderTypeID":2},{"PersonID":5651,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687854","Notes":"","BirthDate":"1975-01-23T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Kerr, Liam","PreferredName":"Liam","GenderTypeID":2},{"PersonID":5665,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688483","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Burnett, Alexander","PreferredName":"Alexander","GenderTypeID":2},{"PersonID":5669,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783691275","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Todd, Maree","PreferredName":"Maree","GenderTypeID":1},{"PersonID":5677,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35786761150","Notes":"","BirthDate":"1976-11-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Cameron, Donald","PreferredName":"Donald","GenderTypeID":2},{"PersonID":5679,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783689357","Notes":"","BirthDate":"1950-05-13T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Chapman, Peter","PreferredName":"Peter","GenderTypeID":2},{"PersonID":5695,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571691","Notes":"","BirthDate":"1963-05-29T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wightman, Andy","PreferredName":"Andy","GenderTypeID":2},{"PersonID":5698,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35681770981","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Greene, Jamie","PreferredName":"Jamie","GenderTypeID":2},{"PersonID":5700,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783689572","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Corry, Maurice","PreferredName":"Maurice","GenderTypeID":2},{"PersonID":5709,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571941","Notes":"","BirthDate":"1989-12-01T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Mundell, Oliver","PreferredName":"Oliver","GenderTypeID":2},{"PersonID":5757,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783687836","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Greer, Ross","PreferredName":"Ross","GenderTypeID":2},{"PersonID":5769,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571479","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Hamilton, Rachael","PreferredName":"Rachael","GenderTypeID":1},{"PersonID":5771,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35818497399","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Harper, Emma","PreferredName":"Emma","GenderTypeID":1},{"PersonID":5781,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783690200","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Harris, Alison","PreferredName":"Alison","GenderTypeID":1},{"PersonID":5782,"PhotoURL":"http://scottishparliament.thirdlight.com/file/40400707229","Notes":"","BirthDate":"1967-10-18T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Carson, Finlay","PreferredName":"Finlay","GenderTypeID":2},{"PersonID":5783,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781655804","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Tomkins, Adam","PreferredName":"Adam","GenderTypeID":2},{"PersonID":5788,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783686421","Notes":"","BirthDate":"1972-02-24T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Wells, Annie","PreferredName":"Annie","GenderTypeID":1},{"PersonID":5793,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688325","Notes":"","BirthDate":"1964-04-26T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Whittle, Brian","PreferredName":"Brian","GenderTypeID":2},{"PersonID":5797,"PhotoURL":"http://scottishparliament.thirdlight.com/file/42332640174","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Ballantyne, Michelle","PreferredName":"Michelle","GenderTypeID":1},{"PersonID":5800,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":false,"ParliamentaryName":"Halcro Johnston, Jamie","PreferredName":"Jamie","GenderTypeID":2},{"PersonID":5809,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688782","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Lockhart, Dean","PreferredName":"Dean","GenderTypeID":2},{"PersonID":5815,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571595","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Cole-Hamilton, Alex","PreferredName":"Alex","GenderTypeID":2},{"PersonID":5866,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35781571135","Notes":"","BirthDate":"1962-11-29T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Stewart, Alexander","PreferredName":"Alexander","GenderTypeID":2},{"PersonID":5868,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688599","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Arthur, Tom","PreferredName":"Tom","GenderTypeID":2},{"PersonID":5877,"PhotoURL":"http://scottishparliament.thirdlight.com/file/35783688260","Notes":"","BirthDate":"1967-03-11T00:00:00","BirthDateIsProtected":false,"ParliamentaryName":"Balfour, Jeremy","PreferredName":"Jeremy","GenderTypeID":2},{"PersonID":5929,"PhotoURL":"","Notes":"","BirthDate":null,"BirthDateIsProtected":false,"ParliamentaryName":"Mason, Tom","PreferredName":"Tom","GenderTypeID":2},{"PersonID":6090,"PhotoURL":"http://scottishparliament.thirdlight.com/file/39689732792","Notes":"","BirthDate":null,"BirthDateIsProtected":true,"ParliamentaryName":"Bowman, Bill","PreferredName":"Bill","GenderTypeID":2}] \ No newline at end of file +[ + { + "PersonID": 1735, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820129812", + "Notes": "", + "BirthDate": "1970-07-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Constance, Angela", + "PreferredName": "Angela", + "GenderTypeID": 1 + }, + { + "PersonID": 1741, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1950-02-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Goldie, Annabel", + "PreferredName": "Annabel", + "GenderTypeID": 1 + }, + { + "PersonID": 1742, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960261933", + "Notes": "", + "BirthDate": "1960-08-20T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ewing, Annabelle", + "PreferredName": "Annabelle", + "GenderTypeID": 1 + }, + { + "PersonID": 1751, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-04-14T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Craigie, Cathie", + "PreferredName": "Cathie", + "GenderTypeID": 1 + }, + { + "PersonID": 1752, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1956-11-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Jamieson, Cathy", + "PreferredName": "Cathy", + "GenderTypeID": 1 + }, + { + "PersonID": 1754, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1951-11-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Peattie, Cathy", + "PreferredName": "Cathy", + "GenderTypeID": 1 + }, + { + "PersonID": 1756, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35819883370", + "Notes": "", + "BirthDate": "1944-09-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Grahame, Christine", + "PreferredName": "Christine", + "GenderTypeID": 1 + }, + { + "PersonID": 1759, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820937650", + "Notes": "Twitter @Claudiabeamish\\r\\nFacebook: www.facebook.com/claudiabeamish", + "BirthDate": "1952-08-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Beamish, Claudia", + "PreferredName": "Claudia", + "GenderTypeID": 1 + }, + { + "PersonID": 1762, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-08-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Elder, Dorothy-Grace", + "PreferredName": "Dorothy-Grace", + "GenderTypeID": 1 + }, + { + "PersonID": 1768, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-12-22T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Murray, Elaine", + "PreferredName": "Elaine", + "GenderTypeID": 1 + }, + { + "PersonID": 1769, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35817927427", + "Notes": "", + "BirthDate": "1963-05-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Smith, Elaine", + "PreferredName": "Elaine", + "GenderTypeID": 1 + }, + { + "PersonID": 1770, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1957-08-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Thomson, Elaine", + "PreferredName": "Elaine", + "GenderTypeID": 1 + }, + { + "PersonID": 1771, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1951-07-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Scott, Eleanor", + "PreferredName": "Eleanor", + "GenderTypeID": 1 + }, + { + "PersonID": 1773, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660228", + "Notes": "", + "BirthDate": "1964-08-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Hyslop, Fiona", + "PreferredName": "Fiona", + "GenderTypeID": 1 + }, + { + "PersonID": 1775, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1957-12-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McLeod, Fiona", + "PreferredName": "Fiona", + "GenderTypeID": 1 + }, + { + "PersonID": 1778, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Eadie, Helen", + "PreferredName": "Helen", + "GenderTypeID": 1 + }, + { + "PersonID": 1781, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-08-29T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McGugan, Irene", + "PreferredName": "Irene", + "GenderTypeID": 1 + }, + { + "PersonID": 1782, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Oldfather, Irene", + "PreferredName": "Irene", + "GenderTypeID": 1 + }, + { + "PersonID": 1783, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660953", + "Notes": "http://www.facebook.com/jackie.baillie", + "BirthDate": "1964-01-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Baillie, Jackie", + "PreferredName": "Jackie", + "GenderTypeID": 1 + }, + { + "PersonID": 1791, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-05-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Hughes, Janis", + "PreferredName": "Janis", + "GenderTypeID": 1 + }, + { + "PersonID": 1793, + "PhotoURL": "", + "Notes": "Facebook: http://www.facebook.com/JeanUrquhartMSP\\r\\nTwitter: https://twitter.com/JeanUrquhartMSP", + "BirthDate": "1949-05-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Urquhart, Jean", + "PreferredName": "Jean", + "GenderTypeID": 1 + }, + { + "PersonID": 1803, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1967-08-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gillon, Karen", + "PreferredName": "Karen", + "GenderTypeID": 1 + }, + { + "PersonID": 1805, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1970-01-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Whitefield, Karen", + "PreferredName": "Karen", + "GenderTypeID": 1 + }, + { + "PersonID": 1807, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-02-16T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Maclean, Kate", + "PreferredName": "Kate", + "GenderTypeID": 1 + }, + { + "PersonID": 1811, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1943-05-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ullrich, Kay", + "PreferredName": "Kay", + "GenderTypeID": 1 + }, + { + "PersonID": 1814, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942002662", + "Notes": "Declared ethnicity as Scottish.", + "BirthDate": "1956-12-14T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Fabiani, Linda", + "PreferredName": "Linda", + "GenderTypeID": 1 + }, + { + "PersonID": 1820, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-11-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Curran, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 1821, + "PhotoURL": "", + "Notes": "\\r\\nDeclared ethnicity as Scottish.", + "BirthDate": "1945-09-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ewing, Mrs Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 1823, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1953-04-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Jamieson, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 1826, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-02-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Smith, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 1828, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1943-04-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "MacDonald, Margo", + "PreferredName": "Margo", + "GenderTypeID": 1 + }, + { + "PersonID": 1831, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1951-09-30T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Glen, Marlyn", + "PreferredName": "Marlyn", + "GenderTypeID": 1 + }, + { + "PersonID": 1832, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-09-30T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Livingstone, Marilyn", + "PreferredName": "Marilyn", + "GenderTypeID": 1 + }, + { + "PersonID": 1837, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1960-02-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mulligan, Mary", + "PreferredName": "Mary", + "GenderTypeID": 1 + }, + { + "PersonID": 1839, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1947-05-25T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Scanlon, Mary", + "PreferredName": "Mary", + "GenderTypeID": 1 + }, + { + "PersonID": 1840, + "PhotoURL": "", + "Notes": "\\r\\nDeclared ethnicity as European/Caucasion.", + "BirthDate": "1943-02-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Macmillan, Maureen", + "PreferredName": "Maureen", + "GenderTypeID": 1 + }, + { + "PersonID": 1841, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820938288", + "Notes": "", + "BirthDate": "1951-06-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Watt, Maureen", + "PreferredName": "Maureen", + "GenderTypeID": 1 + }, + { + "PersonID": 1845, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-04-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Milne, Nanette", + "PreferredName": "Nanette", + "GenderTypeID": 1 + }, + { + "PersonID": 1848, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/9853640645", + "Notes": "", + "BirthDate": "1970-07-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Sturgeon, Nicola", + "PreferredName": "Nicola", + "GenderTypeID": 1 + }, + { + "PersonID": 1850, + "PhotoURL": "", + "Notes": "District Councillor Gordon District 1988-92", + "BirthDate": "1946-03-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Radcliffe, Nora", + "PreferredName": "Nora", + "GenderTypeID": 1 + }, + { + "PersonID": 1853, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-09-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ferguson, Patricia", + "PreferredName": "Patricia", + "GenderTypeID": 1 + }, + { + "PersonID": 1854, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1939-10-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Godman, Trish", + "PreferredName": "Trish", + "GenderTypeID": 1 + }, + { + "PersonID": 1857, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960261831", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "McNeill, Pauline", + "PreferredName": "Pauline", + "GenderTypeID": 1 + }, + { + "PersonID": 1860, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/41869411513", + "Notes": "", + "BirthDate": "1963-06-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Grant, Rhoda", + "PreferredName": "Rhoda", + "GenderTypeID": 1 + }, + { + "PersonID": 1862, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1950-01-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brankin, Rhona", + "PreferredName": "Rhona", + "GenderTypeID": 1 + }, + { + "PersonID": 1863, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942247222", + "Notes": "", + "BirthDate": "1951-07-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Cunningham, Roseanna", + "PreferredName": "Roseanna", + "GenderTypeID": 1 + }, + { + "PersonID": 1865, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35922877182", + "Notes": "", + "BirthDate": "1951-08-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "White, Sandra", + "PreferredName": "Sandra", + "GenderTypeID": 1 + }, + { + "PersonID": 1866, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-05-16T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Boyack, Sarah", + "PreferredName": "Sarah", + "GenderTypeID": 1 + }, + { + "PersonID": 1869, + "PhotoURL": "", + "Notes": "2003 Affirmation", + "BirthDate": "1946-09-14T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Baird, Shiona", + "PreferredName": "Shiona", + "GenderTypeID": 1 + }, + { + "PersonID": 1870, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820938944", + "Notes": "", + "BirthDate": "1966-05-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Robison, Shona", + "PreferredName": "Shona", + "GenderTypeID": 1 + }, + { + "PersonID": 1871, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1964-02-02T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Deacon, Susan", + "PreferredName": "Susan", + "GenderTypeID": 1 + }, + { + "PersonID": 1873, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1946-12-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Jackson, Dr Sylvia", + "PreferredName": "Sylvia", + "GenderTypeID": 1 + }, + { + "PersonID": 1876, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1953-11-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Marwick, Tricia", + "PreferredName": "Tricia", + "GenderTypeID": 1 + }, + { + "PersonID": 1877, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Alexander, Ms Wendy", + "PreferredName": "Wendy", + "GenderTypeID": 1 + }, + { + "PersonID": 1878, + "PhotoURL": "", + "Notes": "\\r\\nMade a solemn affirmation in Gaelic.", + "BirthDate": "1929-07-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ewing, Dr Winnie", + "PreferredName": "Winnie", + "GenderTypeID": 1 + }, + { + "PersonID": 1882, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1951-05-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ingram, Adam", + "PreferredName": "Adam", + "GenderTypeID": 2 + }, + { + "PersonID": 1888, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1945-04-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Morgan, Alasdair", + "PreferredName": "Alasdair", + "GenderTypeID": 2 + }, + { + "PersonID": 1889, + "PhotoURL": "", + "Notes": "\\r\\nRepeated the Oath in Gaelic.", + "BirthDate": "1968-11-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Morrison, Mr Alasdair", + "PreferredName": "Alasdair", + "GenderTypeID": 2 + }, + { + "PersonID": 1892, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-04-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Fergusson, Alex", + "PreferredName": "Alex", + "GenderTypeID": 2 + }, + { + "PersonID": 1893, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-07-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Johnstone, Alex", + "PreferredName": "Alex", + "GenderTypeID": 2 + }, + { + "PersonID": 1894, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820937596", + "Notes": "\\r\\nDeclared ethnicity as Scottish.", + "BirthDate": "1951-08-22T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Neil, Alex", + "PreferredName": "Alex", + "GenderTypeID": 2 + }, + { + "PersonID": 1895, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-12-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Salmond, Alex", + "PreferredName": "Alex", + "GenderTypeID": 2 + }, + { + "PersonID": 1901, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-08-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wilson, Allan", + "PreferredName": "Allan", + "GenderTypeID": 2 + }, + { + "PersonID": 1906, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1944-04-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Welsh, Andrew", + "PreferredName": "Andrew", + "GenderTypeID": 2 + }, + { + "PersonID": 1907, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1970-12-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wilson, Andrew", + "PreferredName": "Andrew", + "GenderTypeID": 2 + }, + { + "PersonID": 1908, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1962-03-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Kerr, Andy", + "PreferredName": "Andy", + "GenderTypeID": 2 + }, + { + "PersonID": 1911, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1964-09-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "MacKay, Angus", + "PreferredName": "Angus", + "GenderTypeID": 2 + }, + { + "PersonID": 1915, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1940-02-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ahmad, Bashir", + "PreferredName": "Bashir", + "GenderTypeID": 2 + }, + { + "PersonID": 1916, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1970-05-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wallace, Ben", + "PreferredName": "Ben", + "GenderTypeID": 2 + }, + { + "PersonID": 1921, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1963-12-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wilson, Bill", + "PreferredName": "Bill", + "GenderTypeID": 2 + }, + { + "PersonID": 1926, + "PhotoURL": "", + "Notes": "2003 Affirmation", + "BirthDate": "1948-06-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Adam, Brian", + "PreferredName": "Brian", + "GenderTypeID": 2 + }, + { + "PersonID": 1928, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-06-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Fitzpatrick, Brian", + "PreferredName": "Brian", + "GenderTypeID": 2 + }, + { + "PersonID": 1930, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-01-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Monteith, Mr Brian", + "PreferredName": "Brian", + "GenderTypeID": 2 + }, + { + "PersonID": 1931, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1964-03-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Muldoon, Bristow", + "PreferredName": "Bristow", + "GenderTypeID": 2 + }, + { + "PersonID": 1932, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818634739", + "Notes": "", + "BirthDate": "1955-02-16T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Crawford, Bruce", + "PreferredName": "Bruce", + "GenderTypeID": 2 + }, + { + "PersonID": 1943, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1944-05-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brodie, Chic", + "PreferredName": "Chic", + "GenderTypeID": 2 + }, + { + "PersonID": 1944, + "PhotoURL": "", + "Notes": "2003 Affirmation", + "BirthDate": "1952-07-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ballance, Chris", + "PreferredName": "Chris", + "GenderTypeID": 2 + }, + { + "PersonID": 1950, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1938-08-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Campbell, Colin", + "PreferredName": "Colin", + "GenderTypeID": 2 + }, + { + "PersonID": 1956, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1943-01-25T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Davidson, Mr David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 1961, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-08-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McLetchie, David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 1962, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1962-05-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mundell, David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 1963, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1946-12-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Petrie, Dave", + "PreferredName": "Dave", + "GenderTypeID": 2 + }, + { + "PersonID": 1968, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-08-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Canavan, Dennis", + "PreferredName": "Dennis", + "GenderTypeID": 2 + }, + { + "PersonID": 1970, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-07-28T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McNulty, Des", + "PreferredName": "Des", + "GenderTypeID": 2 + }, + { + "PersonID": 1972, + "PhotoURL": "", + "Notes": "Brahler ID changed from 0027 to 0027000 by AJP on 06/12/00 because Bill Butler assigned brahler ID of 0027.", + "BirthDate": "1937-08-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Dewar, Donald", + "PreferredName": "Donald", + "GenderTypeID": 2 + }, + { + "PersonID": 1973, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1933-04-02T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gorrie, Donald", + "PreferredName": "Donald", + "GenderTypeID": 2 + }, + { + "PersonID": 1985, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1973-10-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Hamilton, Mr Duncan", + "PreferredName": "Duncan", + "GenderTypeID": 2 + }, + { + "PersonID": 1986, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1950-09-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McNeil, Duncan", + "PreferredName": "Duncan", + "GenderTypeID": 2 + }, + { + "PersonID": 1988, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-09-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brocklebank, Ted", + "PreferredName": "Ted", + "GenderTypeID": 2 + }, + { + "PersonID": 1990, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-02-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Robson, Euan", + "PreferredName": "Euan", + "GenderTypeID": 2 + }, + { + "PersonID": 1994, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35943512647", + "Notes": "Information on Fergus Ewing can also be found on http://www.snp.org", + "BirthDate": "1957-09-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ewing, Fergus", + "PreferredName": "Fergus", + "GenderTypeID": 2 + }, + { + "PersonID": 1996, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1962-07-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McAveety, Mr Frank", + "PreferredName": "Frank", + "GenderTypeID": 2 + }, + { + "PersonID": 2003, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1956-07-16T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Lyon, George", + "PreferredName": "George", + "GenderTypeID": 2 + }, + { + "PersonID": 2005, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1939-06-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Reid, Mr George", + "PreferredName": "George", + "GenderTypeID": 2 + }, + { + "PersonID": 2010, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855484744", + "Notes": "", + "BirthDate": "1942-11-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Paterson, Gil", + "PreferredName": "Gil", + "GenderTypeID": 2 + }, + { + "PersonID": 2013, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1948-08-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Jackson, Gordon", + "PreferredName": "Gordon", + "GenderTypeID": 2 + }, + { + "PersonID": 2015, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571580", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Lindhurst, Gordon", + "PreferredName": "Gordon", + "GenderTypeID": 2 + }, + { + "PersonID": 2028, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1948-06-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McLeish, Henry", + "PreferredName": "Henry", + "GenderTypeID": 2 + }, + { + "PersonID": 2029, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-02-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Henry, Hugh", + "PreferredName": "Hugh", + "GenderTypeID": 2 + }, + { + "PersonID": 2030, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-05-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "O'Donnell, Hugh", + "PreferredName": "Hugh", + "GenderTypeID": 2 + }, + { + "PersonID": 2033, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35817741283", + "Notes": "", + "BirthDate": "1957-06-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gray, Iain", + "PreferredName": "Iain", + "GenderTypeID": 2 + }, + { + "PersonID": 2038, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1960-05-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Smith, Iain", + "PreferredName": "Iain", + "GenderTypeID": 2 + }, + { + "PersonID": 2044, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1941-03-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Jenkins, Ian", + "PreferredName": "Ian", + "GenderTypeID": 2 + }, + { + "PersonID": 2049, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1940-04-02T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McKee, Ian", + "PreferredName": "Ian", + "GenderTypeID": 2 + }, + { + "PersonID": 2051, + "PhotoURL": "", + "Notes": "23-Nov-53\\r\\nBrahler ID as Elected MSP was 0119", + "BirthDate": "1953-11-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Welsh, Ian", + "PreferredName": "Ian", + "GenderTypeID": 2 + }, + { + "PersonID": 2052, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1960-06-30T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McConnell, Jack", + "PreferredName": "Jack", + "GenderTypeID": 2 + }, + { + "PersonID": 2056, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-07-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Douglas-Hamilton, Lord James", + "PreferredName": "James", + "GenderTypeID": 2 + }, + { + "PersonID": 2059, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783690470", + "Notes": "", + "BirthDate": "1963-10-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Kelly, James", + "PreferredName": "James", + "GenderTypeID": 2 + }, + { + "PersonID": 2066, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-10-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McGrigor, Jamie", + "PreferredName": "Jamie", + "GenderTypeID": 2 + }, + { + "PersonID": 2068, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-06-16T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Stone, Jamie", + "PreferredName": "Jamie", + "GenderTypeID": 2 + }, + { + "PersonID": 2074, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1947-03-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mather, Jim", + "PreferredName": "Jim", + "GenderTypeID": 2 + }, + { + "PersonID": 2077, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-08-25T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wallace, Mr Jim", + "PreferredName": "Jim", + "GenderTypeID": 2 + }, + { + "PersonID": 2080, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/9853504141", + "Notes": "", + "BirthDate": "1957-07-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Lamont, Johann", + "PreferredName": "Johann", + "GenderTypeID": 1 + }, + { + "PersonID": 2085, + "PhotoURL": "", + "Notes": "Repeated the Oath in Gaelic.", + "BirthDate": "1934-08-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Munro, John Farquhar", + "PreferredName": "John Farquhar", + "GenderTypeID": 2 + }, + { + "PersonID": 2090, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1948-02-13T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McAllion, Mr John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2098, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35943496226", + "Notes": "", + "BirthDate": "1964-04-13T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Swinney, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2099, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1930-12-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Young, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2100, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1948-12-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Home Robertson, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2103, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960260789", + "Notes": "", + "BirthDate": "1961-12-20T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brown, Keith", + "PreferredName": "Keith", + "GenderTypeID": 2 + }, + { + "PersonID": 2105, + "PhotoURL": "", + "Notes": "Resigned from Conservative Party and Joined Scottish Peoples Alliance 31 March 2003", + "BirthDate": "1938-11-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Harding, Mr Keith", + "PreferredName": "Keith", + "GenderTypeID": 2 + }, + { + "PersonID": 2106, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-06-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Raffan, Mr Keith", + "PreferredName": "Keith", + "GenderTypeID": 2 + }, + { + "PersonID": 2108, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35921454568", + "Notes": "Twitter - http://twitter.com/kenmacintoshmsp \\r\\nFacebook - http://www.facebook.com/pages/Ken-Macintosh-MSP/135822889783835", + "BirthDate": "1962-01-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Macintosh, Ken", + "PreferredName": "Ken", + "GenderTypeID": 2 + }, + { + "PersonID": 2110, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855484389", + "Notes": "", + "BirthDate": "1961-09-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gibson, Kenneth", + "PreferredName": "Kenneth", + "GenderTypeID": 2 + }, + { + "PersonID": 2112, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-04-28T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "MacAskill, Kenny", + "PreferredName": "Kenny", + "GenderTypeID": 2 + }, + { + "PersonID": 2117, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942002807", + "Notes": "", + "BirthDate": "1957-01-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Macdonald, Lewis", + "PreferredName": "Lewis", + "GenderTypeID": 2 + }, + { + "PersonID": 2118, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1957-04-29T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Quinan, Mr Lloyd", + "PreferredName": "Lloyd", + "GenderTypeID": 2 + }, + { + "PersonID": 2122, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1955-06-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McIntosh, Mrs Lyndsay", + "PreferredName": "Lyndsay", + "GenderTypeID": 1 + }, + { + "PersonID": 2123, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-03-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Chisholm, Malcolm", + "PreferredName": "Malcolm", + "GenderTypeID": 2 + }, + { + "PersonID": 2126, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1971-06-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Ballard, Mark", + "PreferredName": "Mark", + "GenderTypeID": 2 + }, + { + "PersonID": 2127, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781781662", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Ruskell, Mark", + "PreferredName": "Mark", + "GenderTypeID": 2 + }, + { + "PersonID": 2133, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660631", + "Notes": "", + "BirthDate": "1970-09-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Matheson, Michael", + "PreferredName": "Michael", + "GenderTypeID": 2 + }, + { + "PersonID": 2134, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-09-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McMahon, Michael", + "PreferredName": "Michael", + "GenderTypeID": 2 + }, + { + "PersonID": 2135, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35819641476", + "Notes": "Declared ethnicity as European, Scottish & British.\\r\\nRepeated the Oath in Gaelic.", + "BirthDate": "1953-08-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Russell, Michael", + "PreferredName": "Michael", + "GenderTypeID": 2 + }, + { + "PersonID": 2140, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783809943", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Rumbles, Mike", + "PreferredName": "Mike", + "GenderTypeID": 2 + }, + { + "PersonID": 2142, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-05-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Watson, Mike", + "PreferredName": "Mike", + "GenderTypeID": 2 + }, + { + "PersonID": 2148, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1950-09-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Tosh, Murray", + "PreferredName": "Murray", + "GenderTypeID": 2 + }, + { + "PersonID": 2152, + "PhotoURL": "", + "Notes": "\\r\\nRepeated the Oath in Catalan\\r\\nResigned 10/08/01", + "BirthDate": "1948-01-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Johnston, Nick", + "PreferredName": "Nick", + "GenderTypeID": 2 + }, + { + "PersonID": 2154, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1960-03-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Stephen, Nicol", + "PreferredName": "Nicol", + "GenderTypeID": 2 + }, + { + "PersonID": 2159, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1967-03-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Martin, Paul", + "PreferredName": "Paul", + "GenderTypeID": 2 + }, + { + "PersonID": 2167, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-02-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Peacock, Peter", + "PreferredName": "Peter", + "GenderTypeID": 2 + }, + { + "PersonID": 2172, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1939-06-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gallie, Phil", + "PreferredName": "Phil", + "GenderTypeID": 2 + }, + { + "PersonID": 2180, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/9853506741", + "Notes": "", + "BirthDate": "1969-05-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Lochhead, Richard", + "PreferredName": "Richard", + "GenderTypeID": 2 + }, + { + "PersonID": 2182, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-10-22T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Simpson, Dr Richard", + "PreferredName": "Richard", + "GenderTypeID": 2 + }, + { + "PersonID": 2185, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1947-12-25T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brown, Robert", + "PreferredName": "Robert", + "GenderTypeID": 2 + }, + { + "PersonID": 2188, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1940-08-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Harper, Robin", + "PreferredName": "Robin", + "GenderTypeID": 2 + }, + { + "PersonID": 2201, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-06-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Kane, Rosie", + "PreferredName": "Rosie", + "GenderTypeID": 1 + }, + { + "PersonID": 2202, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1947-02-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Finnie, Ross", + "PreferredName": "Ross", + "GenderTypeID": 2 + }, + { + "PersonID": 2205, + "PhotoURL": "", + "Notes": "Brahler ID prior to 14/05/2001 when resigned was 0037", + "BirthDate": "1945-08-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Galbraith, Mr Sam", + "PreferredName": "Sam", + "GenderTypeID": 2 + }, + { + "PersonID": 2207, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1962-03-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Barrie, Scott", + "PreferredName": "Scott", + "GenderTypeID": 2 + }, + { + "PersonID": 2215, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820478663", + "Notes": "", + "BirthDate": "1946-10-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Stevenson, Stewart", + "PreferredName": "Stewart", + "GenderTypeID": 2 + }, + { + "PersonID": 2223, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820938602", + "Notes": "", + "BirthDate": "1966-05-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Scott, Tavish", + "PreferredName": "Tavish", + "GenderTypeID": 2 + }, + { + "PersonID": 2225, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1964-03-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Sheridan, Tommy", + "PreferredName": "Tommy", + "GenderTypeID": 2 + }, + { + "PersonID": 2228, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-04-28T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McCabe, Tom", + "PreferredName": "Tom", + "GenderTypeID": 2 + }, + { + "PersonID": 2234, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1947-04-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Aitken, Bill", + "PreferredName": "Bill", + "GenderTypeID": 2 + }, + { + "PersonID": 2247, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1944-04-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Arbuckle, Mr Andrew", + "PreferredName": "Andrew", + "GenderTypeID": 2 + }, + { + "PersonID": 2252, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1945-12-25T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Pringle, Mike", + "PreferredName": "Mike", + "GenderTypeID": 2 + }, + { + "PersonID": 2263, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1938-03-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Steel, Sir David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 2345, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35786761546", + "Notes": "See also http://www.vote-tory-for-ayr.org/johnscott.html", + "BirthDate": "1951-06-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Scott, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2364, + "PhotoURL": "", + "Notes": "assigned Brahler ID 0027 from 29/11/00 -", + "BirthDate": "1956-03-30T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Butler, Bill", + "PreferredName": "Bill", + "GenderTypeID": 2 + }, + { + "PersonID": 2390, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1939-12-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Turner, Dr Jean", + "PreferredName": "Jean", + "GenderTypeID": 1 + }, + { + "PersonID": 2394, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35800892126", + "Notes": "Formally returned as regional MSP Mid-Scotland and Fife on 14/08/01\\r\\nTwitter: @murdo_fraser\\r\\nFacebook: www.facebook.com/MSPMurdoFraser", + "BirthDate": "1965-09-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Fraser, Murdo", + "PreferredName": "Murdo", + "GenderTypeID": 2 + }, + { + "PersonID": 2487, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1971-08-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McLeod, Aileen", + "PreferredName": "Aileen", + "GenderTypeID": 1 + }, + { + "PersonID": 2595, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1975-06-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brown, Gavin", + "PreferredName": "Gavin", + "GenderTypeID": 2 + }, + { + "PersonID": 2596, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1974-08-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Brownlee, Derek", + "PreferredName": "Derek", + "GenderTypeID": 2 + }, + { + "PersonID": 2603, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1974-05-29T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Baker, Richard", + "PreferredName": "Richard", + "GenderTypeID": 2 + }, + { + "PersonID": 2610, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1956-11-28T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wilson, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2615, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820937738", + "Notes": "Twitter @GeorgeAdam", + "BirthDate": "1969-06-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Adam, George", + "PreferredName": "George", + "GenderTypeID": 2 + }, + { + "PersonID": 2633, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/9853240684", + "Notes": "", + "BirthDate": "1971-03-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Baker, Claire", + "PreferredName": "Claire", + "GenderTypeID": 1 + }, + { + "PersonID": 2641, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35800892437", + "Notes": "", + "BirthDate": "1971-05-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Allan, Dr Alasdair", + "PreferredName": "Alasdair", + "GenderTypeID": 2 + }, + { + "PersonID": 2651, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1965-05-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Tolson, Jim", + "PreferredName": "Jim", + "GenderTypeID": 2 + }, + { + "PersonID": 2665, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1948-03-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Byrne, Ms Rosemary", + "PreferredName": "Rosemary", + "GenderTypeID": 1 + }, + { + "PersonID": 2673, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1953-06-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Campbell, Roderick", + "PreferredName": "Roderick", + "GenderTypeID": 2 + }, + { + "PersonID": 2674, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-09-20T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Thompson, Dave", + "PreferredName": "Dave", + "GenderTypeID": 2 + }, + { + "PersonID": 2675, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1945-10-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gibson, Rob", + "PreferredName": "Rob", + "GenderTypeID": 2 + }, + { + "PersonID": 2678, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35799295215", + "Notes": "", + "BirthDate": "1959-04-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Carlaw, Jackson", + "PreferredName": "Jackson", + "GenderTypeID": 2 + }, + { + "PersonID": 2686, + "PhotoURL": "", + "Notes": "BBC", + "BirthDate": "1930-07-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Swinburne, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2767, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-05-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Curran, Frances", + "PreferredName": "Frances", + "GenderTypeID": 1 + }, + { + "PersonID": 2826, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942003780", + "Notes": "", + "BirthDate": "1953-03-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Dornan, James", + "PreferredName": "James", + "GenderTypeID": 2 + }, + { + "PersonID": 2853, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1946-12-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Pentland, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 2866, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1974-01-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Purvis, Jeremy", + "PreferredName": "Jeremy", + "GenderTypeID": 2 + }, + { + "PersonID": 2876, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1963-12-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Maxwell, Stewart", + "PreferredName": "Stewart", + "GenderTypeID": 2 + }, + { + "PersonID": 2877, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1948-03-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "May, Christine", + "PreferredName": "Christine", + "GenderTypeID": 1 + }, + { + "PersonID": 2892, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783690519", + "Notes": "", + "BirthDate": "1973-03-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Harvie, Patrick", + "PreferredName": "Patrick", + "GenderTypeID": 2 + }, + { + "PersonID": 2902, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1965-03-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Leckie, Carolyn", + "PreferredName": "Carolyn", + "GenderTypeID": 1 + }, + { + "PersonID": 2947, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1961-05-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McFee, Mr Bruce", + "PreferredName": "Bruce", + "GenderTypeID": 2 + }, + { + "PersonID": 2963, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1966-03-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McLaughlin, Anne", + "PreferredName": "Anne", + "GenderTypeID": 1 + }, + { + "PersonID": 3004, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1959-06-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Fox, Colin", + "PreferredName": "Colin", + "GenderTypeID": 2 + }, + { + "PersonID": 3061, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783809913", + "Notes": "Facebook- https://www.facebook.com/margaretmitchell2016", + "BirthDate": "1952-11-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mitchell, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 3101, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1956-11-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Malik, Hanzala", + "PreferredName": "Hanzala", + "GenderTypeID": 2 + }, + { + "PersonID": 3103, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1960-03-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Martin, Campbell", + "PreferredName": "Campbell", + "GenderTypeID": 2 + }, + { + "PersonID": 3129, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35799134774 ", + "Notes": "", + "BirthDate": "1956-07-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Kidd, Bill", + "PreferredName": "Bill", + "GenderTypeID": 2 + }, + { + "PersonID": 3538, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1951-10-28T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Gordon, Charlie", + "PreferredName": "Charlie", + "GenderTypeID": 2 + }, + { + "PersonID": 3743, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1954-04-16T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Don, Nigel", + "PreferredName": "Nigel", + "GenderTypeID": 2 + }, + { + "PersonID": 3745, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1956-08-14T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Robertson, Dennis", + "PreferredName": "Dennis", + "GenderTypeID": 2 + }, + { + "PersonID": 3746, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1944-09-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Harvie, Christopher", + "PreferredName": "Christopher", + "GenderTypeID": 2 + }, + { + "PersonID": 3749, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1959-09-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Tymkewycz, Stefan", + "PreferredName": "Stefan", + "GenderTypeID": 2 + }, + { + "PersonID": 3750, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783690940", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Somerville, Shirley-Anne", + "PreferredName": "Shirley-Anne", + "GenderTypeID": 1 + }, + { + "PersonID": 3751, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/38395638303", + "Notes": "", + "BirthDate": "1951-10-17T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Beattie, Colin", + "PreferredName": "Colin", + "GenderTypeID": 2 + }, + { + "PersonID": 3758, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820938486 ", + "Notes": "", + "BirthDate": "1979-05-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Hepburn, Jamie", + "PreferredName": "Jamie", + "GenderTypeID": 2 + }, + { + "PersonID": 3759, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960260890", + "Notes": "", + "BirthDate": "1968-03-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McKelvie, Christina", + "PreferredName": "Christina", + "GenderTypeID": 1 + }, + { + "PersonID": 3763, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820938765", + "Notes": "Twitter: @StuMcMillanSNP\\r\\nFacebook: Stuart McMillan MSP", + "BirthDate": "1972-05-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McMillan, Stuart", + "PreferredName": "Stuart", + "GenderTypeID": 2 + }, + { + "PersonID": 3771, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820939764", + "Notes": "", + "BirthDate": "1973-05-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Doris, Bob", + "PreferredName": "Bob", + "GenderTypeID": 2 + }, + { + "PersonID": 3775, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960260104", + "Notes": "", + "BirthDate": "1980-05-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Campbell, Aileen", + "PreferredName": "Aileen", + "GenderTypeID": 1 + }, + { + "PersonID": 3806, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942002372", + "Notes": "", + "BirthDate": "1956-05-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Stewart, David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 3811, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-01-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Foulkes, George", + "PreferredName": "George", + "GenderTypeID": 2 + }, + { + "PersonID": 3812, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781781656", + "Notes": "", + "BirthDate": "1981-08-28T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Dugdale, Kezia", + "PreferredName": "Kezia", + "GenderTypeID": 1 + }, + { + "PersonID": 3815, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1973-09-14T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Park, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 3824, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-01-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McDougall, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 3896, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855661618", + "Notes": "", + "BirthDate": "1967-08-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McArthur, Liam", + "PreferredName": "Liam", + "GenderTypeID": 2 + }, + { + "PersonID": 3901, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35800493586", + "Notes": "", + "BirthDate": "1967-04-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "FitzPatrick, Joe", + "PreferredName": "Joe", + "GenderTypeID": 2 + }, + { + "PersonID": 3907, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/36076831535", + "Notes": "", + "BirthDate": "1958-05-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Coffey, Willie", + "PreferredName": "Willie", + "GenderTypeID": 2 + }, + { + "PersonID": 3983, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687661", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Golden, Maurice", + "PreferredName": "Maurice", + "GenderTypeID": 2 + }, + { + "PersonID": 3985, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783689384", + "Notes": "", + "BirthDate": "1987-09-21T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Thomson, Ross", + "PreferredName": "Ross", + "GenderTypeID": 2 + }, + { + "PersonID": 3994, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783686696", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Simpson, Graham", + "PreferredName": "Graham", + "GenderTypeID": 2 + }, + { + "PersonID": 4014, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818225410", + "Notes": "", + "BirthDate": "1960-02-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Smith, Liz", + "PreferredName": "Liz", + "GenderTypeID": 1 + }, + { + "PersonID": 4016, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35922877680", + "Notes": "facebook.com/JohnLamontBorders/\\r\\nTwitter: @john2win", + "BirthDate": "1976-04-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Lamont, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 4074, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-04-22T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Whitton, David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 4080, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "McInnes, Alison", + "PreferredName": "Alison", + "GenderTypeID": 1 + }, + { + "PersonID": 4086, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1962-11-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Hume, Jim", + "PreferredName": "Jim", + "GenderTypeID": 2 + }, + { + "PersonID": 4934, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818497919", + "Notes": "", + "BirthDate": "1965-10-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Johnstone, Alison", + "PreferredName": "Alison", + "GenderTypeID": 1 + }, + { + "PersonID": 4938, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960260779", + "Notes": "", + "BirthDate": "1950-06-12T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Lyle, Richard", + "PreferredName": "Richard", + "GenderTypeID": 2 + }, + { + "PersonID": 4939, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660763", + "Notes": "", + "BirthDate": "1963-10-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "MacDonald, Angus", + "PreferredName": "Angus", + "GenderTypeID": 2 + }, + { + "PersonID": 4940, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820938229", + "Notes": "", + "BirthDate": "1967-08-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Adamson, Clare", + "PreferredName": "Clare", + "GenderTypeID": 1 + }, + { + "PersonID": 4941, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35922512428 ", + "Notes": "", + "BirthDate": "1985-04-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Yousaf, Humza", + "PreferredName": "Humza", + "GenderTypeID": 2 + }, + { + "PersonID": 4947, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783690556", + "Notes": "", + "BirthDate": "1956-12-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Finnie, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 4948, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1958-11-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "MacKenzie, Mike", + "PreferredName": "Mike", + "GenderTypeID": 2 + }, + { + "PersonID": 4951, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/9853519283", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "McAlpine, Joan", + "PreferredName": "Joan", + "GenderTypeID": 1 + }, + { + "PersonID": 4952, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818225376", + "Notes": "twitter@paulwheelhouse\\r\\nf: PaulWheelhouseMSP", + "BirthDate": "1970-06-22T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wheelhouse, Paul", + "PreferredName": "Paul", + "GenderTypeID": 2 + }, + { + "PersonID": 4955, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1968-02-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Eadie, Jim", + "PreferredName": "Jim", + "GenderTypeID": 2 + }, + { + "PersonID": 4956, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1959-12-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Keir, Colin", + "PreferredName": "Colin", + "GenderTypeID": 2 + }, + { + "PersonID": 4964, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35817648204", + "Notes": "", + "BirthDate": "1980-06-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McDonald, Mark", + "PreferredName": "Mark", + "GenderTypeID": 2 + }, + { + "PersonID": 4965, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1964-03-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Allard, Christian", + "PreferredName": "Christian", + "GenderTypeID": 2 + }, + { + "PersonID": 4966, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660444", + "Notes": "Facebook – derekmackaysnp\\r\\nTwitter - derekmackaysnp", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Mackay, Derek", + "PreferredName": "Derek", + "GenderTypeID": 2 + }, + { + "PersonID": 4976, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783689179", + "Notes": "", + "BirthDate": "1978-11-10T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Davidson, Ruth", + "PreferredName": "Ruth", + "GenderTypeID": 1 + }, + { + "PersonID": 4981, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687368", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Ross, Douglas", + "PreferredName": "Douglas", + "GenderTypeID": 2 + }, + { + "PersonID": 4982, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783689774", + "Notes": "", + "BirthDate": "1961-03-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mountain, Edward", + "PreferredName": "Edward", + "GenderTypeID": 2 + }, + { + "PersonID": 4984, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Buchanan, Cameron", + "PreferredName": "Cameron", + "GenderTypeID": 2 + }, + { + "PersonID": 4987, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783685351", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Briggs, Miles", + "PreferredName": "Miles", + "GenderTypeID": 2 + }, + { + "PersonID": 5009, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687229", + "Notes": "", + "BirthDate": "1967-09-27T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Rennie, Willie", + "PreferredName": "Willie", + "GenderTypeID": 2 + }, + { + "PersonID": 5034, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/9853514522", + "Notes": "Facebook: facebook.com/jennymarramsp\\r\\nTwitter: @jennymarra", + "BirthDate": "1977-11-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Marra, Jenny", + "PreferredName": "Jenny", + "GenderTypeID": 1 + }, + { + "PersonID": 5035, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Brennan, Lesley", + "PreferredName": "Lesley", + "GenderTypeID": 1 + }, + { + "PersonID": 5038, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1955-11-05T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Baxter, Jayne", + "PreferredName": "Jayne", + "GenderTypeID": 1 + }, + { + "PersonID": 5041, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1984-07-04T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McMahon, Siobhan", + "PreferredName": "Siobhan", + "GenderTypeID": 1 + }, + { + "PersonID": 5042, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660595", + "Notes": "", + "BirthDate": "1985-10-19T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Griffin, Mark", + "PreferredName": "Mark", + "GenderTypeID": 2 + }, + { + "PersonID": 5047, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1970-01-30T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McTaggart, Anne", + "PreferredName": "Anne", + "GenderTypeID": 1 + }, + { + "PersonID": 5054, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35817927315", + "Notes": "", + "BirthDate": "1969-03-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Findlay, Neil", + "PreferredName": "Neil", + "GenderTypeID": 2 + }, + { + "PersonID": 5057, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Pearson, Graeme", + "PreferredName": "Graeme", + "GenderTypeID": 2 + }, + { + "PersonID": 5059, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818225238", + "Notes": "", + "BirthDate": "1954-03-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Fee, Mary", + "PreferredName": "Mary", + "GenderTypeID": 1 + }, + { + "PersonID": 5060, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35960261503", + "Notes": "", + "BirthDate": "1983-09-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Bibby, Neil", + "PreferredName": "Neil", + "GenderTypeID": 2 + }, + { + "PersonID": 5074, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35817741458", + "Notes": "", + "BirthDate": "1960-01-02T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "MacDonald, Gordon", + "PreferredName": "Gordon", + "GenderTypeID": 2 + }, + { + "PersonID": 5075, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35800414488", + "Notes": "", + "BirthDate": "1961-03-13T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Torrance, David", + "PreferredName": "David", + "GenderTypeID": 2 + }, + { + "PersonID": 5078, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1942-03-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Walker, Bill", + "PreferredName": "Bill", + "GenderTypeID": 2 + }, + { + "PersonID": 5079, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Smith, Drew", + "PreferredName": "Drew", + "GenderTypeID": 2 + }, + { + "PersonID": 5080, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1952-05-09T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "McCulloch, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 5106, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818497490", + "Notes": "", + "BirthDate": "1968-06-03T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Stewart, Kevin", + "PreferredName": "Kevin", + "GenderTypeID": 2 + }, + { + "PersonID": 5107, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35802798381", + "Notes": "", + "BirthDate": "1962-10-29T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Dey, Graeme", + "PreferredName": "Graeme", + "GenderTypeID": 2 + }, + { + "PersonID": 5108, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1949-12-07T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Burgess, Margaret", + "PreferredName": "Margaret", + "GenderTypeID": 1 + }, + { + "PersonID": 5109, + "PhotoURL": "", + "Notes": "", + "BirthDate": "1982-07-31T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Biagi, Marco", + "PreferredName": "Marco", + "GenderTypeID": 2 + }, + { + "PersonID": 5110, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820937486", + "Notes": "", + "BirthDate": "1957-05-15T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mason, John", + "PreferredName": "John", + "GenderTypeID": 2 + }, + { + "PersonID": 5119, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35786781393 ", + "Notes": "", + "BirthDate": "1963-11-30T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Rowley, Alex", + "PreferredName": "Alex", + "GenderTypeID": 2 + }, + { + "PersonID": 5556, + "PhotoURL": "", + "Notes": "https://twitter.com/cara_hilton", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Hilton, Cara", + "PreferredName": "Cara", + "GenderTypeID": 1 + }, + { + "PersonID": 5578, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571350", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Martin, Gillian", + "PreferredName": "Gillian", + "GenderTypeID": 1 + }, + { + "PersonID": 5579, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942063441", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Leonard, Richard", + "PreferredName": "Richard", + "GenderTypeID": 2 + }, + { + "PersonID": 5580, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687362", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Lennon, Monica", + "PreferredName": "Monica", + "GenderTypeID": 1 + }, + { + "PersonID": 5586, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783690447", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Sarwar, Anas", + "PreferredName": "Anas", + "GenderTypeID": 2 + }, + { + "PersonID": 5587, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35921454674", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Evans, Mairi", + "PreferredName": "Mairi", + "GenderTypeID": 1 + }, + { + "PersonID": 5591, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35855660525", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Ross, Gail", + "PreferredName": "Gail", + "GenderTypeID": 1 + }, + { + "PersonID": 5592, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688795", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Freeman, Jeane", + "PreferredName": "Jeane", + "GenderTypeID": 1 + }, + { + "PersonID": 5596, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783689308", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "MacGregor, Fulton", + "PreferredName": "Fulton", + "GenderTypeID": 2 + }, + { + "PersonID": 5598, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783686177", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Maguire, Ruth", + "PreferredName": "Ruth", + "GenderTypeID": 1 + }, + { + "PersonID": 5604, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35820937956", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Johnson, Daniel", + "PreferredName": "Daniel", + "GenderTypeID": 2 + }, + { + "PersonID": 5605, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783686850", + "Notes": "", + "BirthDate": "1974-03-08T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Denham, Ash", + "PreferredName": "Ash", + "GenderTypeID": 1 + }, + { + "PersonID": 5608, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783686780", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Macpherson, Ben", + "PreferredName": "Ben", + "GenderTypeID": 2 + }, + { + "PersonID": 5612, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688223", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "McKee, Ivan", + "PreferredName": "Ivan", + "GenderTypeID": 2 + }, + { + "PersonID": 5613, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783686815", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Gilruth, Jenny", + "PreferredName": "Jenny", + "GenderTypeID": 1 + }, + { + "PersonID": 5618, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687418", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Haughey, Clare", + "PreferredName": "Clare", + "GenderTypeID": 1 + }, + { + "PersonID": 5621, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35942002221", + "Notes": "", + "BirthDate": "1990-04-06T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Forbes, Kate", + "PreferredName": "Kate", + "GenderTypeID": 1 + }, + { + "PersonID": 5622, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687929", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Mackay, Rona", + "PreferredName": "Rona", + "GenderTypeID": 1 + }, + { + "PersonID": 5638, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688355", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Smyth, Colin", + "PreferredName": "Colin", + "GenderTypeID": 2 + }, + { + "PersonID": 5651, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687854", + "Notes": "", + "BirthDate": "1975-01-23T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Kerr, Liam", + "PreferredName": "Liam", + "GenderTypeID": 2 + }, + { + "PersonID": 5665, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688483", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Burnett, Alexander", + "PreferredName": "Alexander", + "GenderTypeID": 2 + }, + { + "PersonID": 5669, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783691275", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Todd, Maree", + "PreferredName": "Maree", + "GenderTypeID": 1 + }, + { + "PersonID": 5677, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35786761150", + "Notes": "", + "BirthDate": "1976-11-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Cameron, Donald", + "PreferredName": "Donald", + "GenderTypeID": 2 + }, + { + "PersonID": 5679, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783689357", + "Notes": "", + "BirthDate": "1950-05-13T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Chapman, Peter", + "PreferredName": "Peter", + "GenderTypeID": 2 + }, + { + "PersonID": 5695, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571691", + "Notes": "", + "BirthDate": "1963-05-29T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wightman, Andy", + "PreferredName": "Andy", + "GenderTypeID": 2 + }, + { + "PersonID": 5698, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35681770981", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Greene, Jamie", + "PreferredName": "Jamie", + "GenderTypeID": 2 + }, + { + "PersonID": 5700, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783689572", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Corry, Maurice", + "PreferredName": "Maurice", + "GenderTypeID": 2 + }, + { + "PersonID": 5709, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571941", + "Notes": "", + "BirthDate": "1989-12-01T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Mundell, Oliver", + "PreferredName": "Oliver", + "GenderTypeID": 2 + }, + { + "PersonID": 5757, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783687836", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Greer, Ross", + "PreferredName": "Ross", + "GenderTypeID": 2 + }, + { + "PersonID": 5769, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571479", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Hamilton, Rachael", + "PreferredName": "Rachael", + "GenderTypeID": 1 + }, + { + "PersonID": 5771, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35818497399", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Harper, Emma", + "PreferredName": "Emma", + "GenderTypeID": 1 + }, + { + "PersonID": 5781, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783690200", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Harris, Alison", + "PreferredName": "Alison", + "GenderTypeID": 1 + }, + { + "PersonID": 5782, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/40400707229", + "Notes": "", + "BirthDate": "1967-10-18T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Carson, Finlay", + "PreferredName": "Finlay", + "GenderTypeID": 2 + }, + { + "PersonID": 5783, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781655804", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Tomkins, Adam", + "PreferredName": "Adam", + "GenderTypeID": 2 + }, + { + "PersonID": 5788, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783686421", + "Notes": "", + "BirthDate": "1972-02-24T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Wells, Annie", + "PreferredName": "Annie", + "GenderTypeID": 1 + }, + { + "PersonID": 5793, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688325", + "Notes": "", + "BirthDate": "1964-04-26T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Whittle, Brian", + "PreferredName": "Brian", + "GenderTypeID": 2 + }, + { + "PersonID": 5797, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/42332640174", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Ballantyne, Michelle", + "PreferredName": "Michelle", + "GenderTypeID": 1 + }, + { + "PersonID": 5800, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": false, + "ParliamentaryName": "Halcro Johnston, Jamie", + "PreferredName": "Jamie", + "GenderTypeID": 2 + }, + { + "PersonID": 5809, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688782", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Lockhart, Dean", + "PreferredName": "Dean", + "GenderTypeID": 2 + }, + { + "PersonID": 5815, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571595", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Cole-Hamilton, Alex", + "PreferredName": "Alex", + "GenderTypeID": 2 + }, + { + "PersonID": 5866, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35781571135", + "Notes": "", + "BirthDate": "1962-11-29T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Stewart, Alexander", + "PreferredName": "Alexander", + "GenderTypeID": 2 + }, + { + "PersonID": 5868, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688599", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Arthur, Tom", + "PreferredName": "Tom", + "GenderTypeID": 2 + }, + { + "PersonID": 5877, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/35783688260", + "Notes": "", + "BirthDate": "1967-03-11T00:00:00Z", + "BirthDateIsProtected": false, + "ParliamentaryName": "Balfour, Jeremy", + "PreferredName": "Jeremy", + "GenderTypeID": 2 + }, + { + "PersonID": 5929, + "PhotoURL": "", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": false, + "ParliamentaryName": "Mason, Tom", + "PreferredName": "Tom", + "GenderTypeID": 2 + }, + { + "PersonID": 6090, + "PhotoURL": "http://scottishparliament.thirdlight.com/file/39689732792", + "Notes": "", + "BirthDate": null, + "BirthDateIsProtected": true, + "ParliamentaryName": "Bowman, Bill", + "PreferredName": "Bill", + "GenderTypeID": 2 + } +] diff --git a/test/inputs/json/misc/337ed.json b/test/inputs/json/misc/337ed.json index 66727da13..eae968669 100644 --- a/test/inputs/json/misc/337ed.json +++ b/test/inputs/json/misc/337ed.json @@ -1 +1,1876 @@ -{"count": 17266, "facets": {}, "results": [{"other_sources_donation": 385213, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-09-18T00:49:01.406041", "cost_min": 100000, "direct_rep_costs_max": null, "representative": "013b6cca4abc4e25b5e8bb66dc77e38e", "cost_absolute": null, "eur_sources_grants_src": null, "id": "fffabd366dd44c4fb7379481a638eecd", "customIncomes": [], "total_budget": 660960, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": 385213, "cost_max": 199999, "created_at": "2015-09-18T00:49:01.409679", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/fffabd366dd44c4fb7379481a638eecd", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": 275747, "other_sources_total": 385213, "other_financial_information": "We used a \u20ac/CHF exchange rate of 1.10, as per info from the ECB on 16 September 2015.", "public_financing_national": 275747, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": 99999, "updated_at": "2016-05-05T01:35:10.407461", "cost_min": null, "direct_rep_costs_max": null, "representative": "f1622c9caf54453d9a6c04804863ce0e", "cost_absolute": null, "eur_sources_grants_src": null, "id": "fff1768c0aa64f0799667e2522c3f340", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-05-24T21:46:36.026780", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/fff1768c0aa64f0799667e2522c3f340", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataLawyer", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2016-01-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-06-01T01:55:18.942873", "cost_min": null, "direct_rep_costs_max": null, "representative": "12750bb632484a9ca2b66d2d0c697f42", "cost_absolute": 100, "eur_sources_grants_src": null, "id": "ffe6a717d0494855b30df00b0aa364dd", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": null, "created_at": "2016-06-01T01:55:18.946640", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffe6a717d0494855b30df00b0aa364dd", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-30T00:31:22.089325", "cost_min": null, "direct_rep_costs_max": null, "representative": "ee3f932f5f9a46b793f4575d3c4a1ba1", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffdd7866367541999ce4ed1de30bad50", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-03-30T00:31:22.091930", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffdd7866367541999ce4ed1de30bad50", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "Les comptes financiers du GIGREL sont certifi\u00e9s par un expert comptable", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-09T01:03:26.456171", "cost_min": null, "direct_rep_costs_max": null, "representative": "4a97ff579f39418b8ac1ab3aaed88932", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffdb787db80d45cb9f1988f9dffd3d79", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-04-24T01:52:29.207871", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffdb787db80d45cb9f1988f9dffd3d79", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-21T02:00:24.411627", "cost_min": 25000, "direct_rep_costs_max": null, "representative": "e0cf2c23c0974c689bb92910659121d4", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffd5741012184e55b901bfa4774ca121", "customIncomes": [], "total_budget": null, "turnover_absolute": 45122748, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 49999, "created_at": "2016-02-09T02:56:30.457858", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffd5741012184e55b901bfa4774ca121", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataLawyer", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": 54154, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-05-24T23:54:56.661915", "cost_min": null, "direct_rep_costs_max": null, "representative": "fc6ba4bc05754730b435e3ad248475ae", "cost_absolute": null, "eur_sources_grants_src": "EIDHR", "id": "ffd55c90a2eb4e5fa0aef212f9e1e46d", "customIncomes": [{"status": "active", "name": "UN bodies", "created_at": "2015-05-28T02:15:19.669323", "updated_at": "2015-05-28T02:15:19.668220", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/9a969481456647d68653dd83aac11246", "amount": 243151, "type": "public", "id": "9a969481456647d68653dd83aac11246"}, {"status": "active", "name": "Trusts and foundations", "created_at": "2015-05-28T02:15:19.683645", "updated_at": "2015-05-28T02:15:19.682195", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/d6555ad554614b8685609d5780f6b575", "amount": 241759, "type": "public", "id": "d6555ad554614b8685609d5780f6b575"}, {"status": "active", "name": "Publishing rights", "created_at": "2015-05-28T02:15:19.689808", "updated_at": "2015-05-28T02:15:19.688752", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/889cfd75b53c4c26a52db0c84c6db2ab", "amount": 590, "type": "public", "id": "889cfd75b53c4c26a52db0c84c6db2ab"}, {"status": "active", "name": "Interest", "created_at": "2015-05-28T02:15:19.695412", "updated_at": "2015-05-28T02:15:19.694444", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/4da5bb10577f498aa12d7ac9d3fcfbb1", "amount": 344, "type": "public", "id": "4da5bb10577f498aa12d7ac9d3fcfbb1"}, {"status": "active", "name": "Other INGOS & NGOs", "created_at": "2015-05-28T02:15:19.701039", "updated_at": "2015-05-28T02:15:19.700107", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/3cd306bd22394082b4f819c027d3b74f", "amount": 44147, "type": "public", "id": "3cd306bd22394082b4f819c027d3b74f"}], "total_budget": 4504192, "turnover_absolute": null, "eur_sources_grants": 1317691, "other_sources_contributions": 54154, "cost_max": 9999, "created_at": "2015-05-07T21:30:43.767784", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffd55c90a2eb4e5fa0aef212f9e1e46d", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": 4450038, "other_sources_total": 54154, "other_financial_information": null, "public_financing_national": 2602356, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-09T01:49:19.041473", "cost_min": 25000, "direct_rep_costs_max": null, "representative": "6ffd2947b99e49559eccd74a21e7f508", "cost_absolute": null, "eur_sources_grants_src": "Intelligent Energy Europe (IEE), LIFE Operating grant, Executive Agency for Small and Medium-sized Enterprises (EASME)", "id": "ffd1d420375949a68d4eb2283aca2d5d", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 470000, "other_sources_contributions": null, "cost_max": 49999, "created_at": "2016-03-09T01:49:19.045719", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffd1d420375949a68d4eb2283aca2d5d", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-06-18T00:54:28.859949", "cost_min": null, "direct_rep_costs_max": null, "representative": "eb7a9c91b2da4c1da909d04ac1bb1466", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffcd0088616146d6baf3a0c2ccc2e7a9", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-06-18T00:54:28.863595", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffcd0088616146d6baf3a0c2ccc2e7a9", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-17T01:15:00.692458", "cost_min": null, "direct_rep_costs_max": null, "representative": "97bd0a0054a64b02a2a8d7aa01d9e88a", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffcc874f7b75440ca06df46679b6deca", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-03-17T01:15:00.696615", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffcc874f7b75440ca06df46679b6deca", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-06-09T00:26:54.823237", "cost_min": null, "direct_rep_costs_max": null, "representative": "ae97df280eab44b5b40098197708efe6", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffc19765007c4f3aba8eaa48c684a554", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-04-24T02:30:25.668792", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffc19765007c4f3aba8eaa48c684a554", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-17T01:58:15.973638", "cost_min": null, "direct_rep_costs_max": null, "representative": "6092b03e7105428cb513e9e249d5c4d7", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffc16d5a6e344038b5377e45960be787", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-03-17T01:58:15.977827", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffc16d5a6e344038b5377e45960be787", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": 100000, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": 499999, "updated_at": "2016-04-08T01:00:23.785525", "cost_min": 300000, "direct_rep_costs_max": null, "representative": "c75f8e81295d4cbb880758d6e18b3589", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffb97483dfbe470cbda4933c09260bde", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 399999, "created_at": "2016-04-08T01:00:23.787495", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffb97483dfbe470cbda4933c09260bde", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataLawyer", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": 0, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2013-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-07T00:14:47.973821", "cost_min": null, "direct_rep_costs_max": null, "representative": "6a2d6670e2ce4af1882c75ddd9666fc5", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffaf85a0e6a94685964f432cdd142bef", "customIncomes": [], "total_budget": 13000000, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": 0, "cost_max": 9999, "created_at": "2015-04-24T01:59:26.164126", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffaf85a0e6a94685964f432cdd142bef", "public_financing_infranational": 0, "direct_rep_costs_min": null, "public_financing_total": 13000000, "other_sources_total": 0, "other_financial_information": "We are 100 percent funded by the Norwegian state and our staff only work part time on EU advocacy. ", "public_financing_national": 13000000, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2013-01-01T00:00:00"}, {"other_sources_donation": 29047000, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-06-25T00:13:19.257034", "cost_min": 300000, "direct_rep_costs_max": null, "representative": "a1f2638c81034e07a2ab3ed2c54e6097", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffaf83bd49424f3baa0716d70e1da1f9", "customIncomes": [], "total_budget": 29047000, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": 29047000, "cost_max": 399999, "created_at": "2015-06-17T23:52:51.768558", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffaf83bd49424f3baa0716d70e1da1f9", "public_financing_infranational": 0, "direct_rep_costs_min": null, "public_financing_total": 0, "other_sources_total": 29047000, "other_financial_information": "Major funders of the ECF are:\r\n- Children\u2019s Investment Fund Foundation (United Kingdom)\r\n- McCall MacBain Foundation (Switzerland)\r\n- Oak Foundation (Switzerland)\r\n- ClimateWorks Foundation (United States of America)\r\n- Nationale Postcode Loterij (Netherlands)\r\n- Villum Fonden (Denmark)", "public_financing_national": 0, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-09-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-21T01:16:37.966794", "cost_min": null, "direct_rep_costs_max": null, "representative": "51897d28145f4329bf55bf89a8ac50b8", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffa71efed5f74254888217e6a68e7905", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-05-07T21:12:34.739366", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffa71efed5f74254888217e6a68e7905", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2013-10-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": 99999, "updated_at": "2016-05-05T01:23:13.676750", "cost_min": null, "direct_rep_costs_max": null, "representative": "48aa47f2326b4227a5cc9421ab45fd22", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ffa5b73fc4b5448ea6c27cf043991cb6", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-05-07T21:27:39.131564", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffa5b73fc4b5448ea6c27cf043991cb6", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataLawyer", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2016-01-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-17T01:35:12.589885", "cost_min": null, "direct_rep_costs_max": null, "representative": "0b5fe36ecd114b729aab1d8683a34215", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff8f43a4f7e14aadaf98988bc0314d50", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-03-17T01:35:12.593635", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff8f43a4f7e14aadaf98988bc0314d50", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "100% funded by companies active in the UK paper industry.", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": 30000, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-26T02:30:00.483178", "cost_min": null, "direct_rep_costs_max": null, "representative": "8e920e7a62994b1ebd9faec199d5534b", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff8ec78386384e4bb6c56dcead8b764a", "customIncomes": [], "total_budget": 60000, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": 30000, "cost_max": 9999, "created_at": "2015-09-23T00:50:08.119641", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff8ec78386384e4bb6c56dcead8b764a", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": 60000, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-12-04T02:36:08.694295", "cost_min": null, "direct_rep_costs_max": null, "representative": "a3bbdd184d114bd19a444cd72882e635", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff8aac50ab16444cb3e65e75a228f2de", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-12-04T02:36:08.697897", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff8aac50ab16444cb3e65e75a228f2de", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": "0", "new_organisation": null, "turnover_max": null, "updated_at": "2016-02-11T02:56:04.443073", "cost_min": null, "direct_rep_costs_max": null, "representative": "24ccf60ad967421d846dc0c78e8adbb8", "cost_absolute": 50000, "eur_sources_grants_src": "Lifelong learning Programme-Grundtvig", "id": "ff87048f461c460f9d934eb7a530dfba", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 2000, "other_sources_contributions": null, "cost_max": null, "created_at": "2016-02-11T02:56:04.446801", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff87048f461c460f9d934eb7a530dfba", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-12-23T02:43:03.491517", "cost_min": 300000, "direct_rep_costs_max": null, "representative": "29f14de439a848b6a93183888b909da5", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff7baad305284c0b9038ec8838a300a7", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 399999, "created_at": "2015-12-23T02:43:03.495155", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff7baad305284c0b9038ec8838a300a7", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-27T01:01:20.211310", "cost_min": 100000, "direct_rep_costs_max": null, "representative": "e5a7554197164c53886192d861babdd3", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff73bcf48e4e4cc3a3e49a1bd26e98a7", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 199999, "created_at": "2015-05-07T21:12:38.474975", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff73bcf48e4e4cc3a3e49a1bd26e98a7", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "ECG's main source of funding is via its membership fees, and the costs attributable to activities covered by the Register have been estimated according to its Implementing Guidelines as well as the SEAP Guidelines (of which the ECG EU Affairs Adviser is a member in his personal capacity).", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-01-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-05-14T01:25:59.026666", "cost_min": null, "direct_rep_costs_max": null, "representative": "49922f3520e7430abc76aed24f3e3d14", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff661b8905174738859139b1d111b590", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-05-24T21:44:12.205154", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff661b8905174738859139b1d111b590", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2013-02-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-21T00:20:41.720896", "cost_min": 10000, "direct_rep_costs_max": null, "representative": "eb2693775b7a40f09063bb5e35ec3aac", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff655f4300214430b018f37da655bb5c", "customIncomes": [], "total_budget": 0, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 24999, "created_at": "2016-03-17T01:25:55.168580", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff655f4300214430b018f37da655bb5c", "public_financing_infranational": 0, "direct_rep_costs_min": null, "public_financing_total": 0, "other_sources_total": 0, "other_financial_information": "EFIC has own budget from biennial congresses and annual royalties of our medical online journal (European Journal of Pain) and receives unrestricted grants from the pharmaceutical companies. As an organisation representing healthcare professionals working in the field of pain care, only a small proportion of our activities are covered by the Transparency Register, with the rest dedicated to education, training and best practice sharing amongst professionals.", "public_financing_national": 0, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": "-", "new_organisation": null, "turnover_max": null, "updated_at": "2016-08-31T01:12:27.637001", "cost_min": null, "direct_rep_costs_max": null, "representative": "c81d9bc7ee0e4345a5be20393ff9fed6", "cost_absolute": 850000, "eur_sources_grants_src": "Comisi\u00f3n Europea", "id": "ff6429e2edad450786b5a47cc77b5601", "customIncomes": [], "total_budget": null, "turnover_absolute": 850000, "eur_sources_grants": 1107051, "other_sources_contributions": null, "cost_max": null, "created_at": "2016-08-31T01:12:27.641759", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff6429e2edad450786b5a47cc77b5601", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "Las subvenciones recibidas corresponden a proyectos europeos (como el S\u00e9ptimo Programa Marco) en colaboraci\u00f3n en los que Zabala ha participado como l\u00edder o socio.", "public_financing_national": null, "no_clients": "Actividades propias", "type": "FinancialDataLawyer", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-09T01:41:33.481929", "cost_min": 400000, "direct_rep_costs_max": null, "representative": "e1ef1a5ab7f540929f8512c95f0600b0", "cost_absolute": null, "eur_sources_grants_src": "LIFE+, Horizon 2020 programme , Interreg, FP7", "id": "ff63c2f0a1a54fbebd729ce7c53935ad", "customIncomes": [], "total_budget": 372075, "turnover_absolute": null, "eur_sources_grants": 123410, "other_sources_contributions": null, "cost_max": 499999, "created_at": "2016-03-09T01:41:33.485949", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff63c2f0a1a54fbebd729ce7c53935ad", "public_financing_infranational": 100000, "direct_rep_costs_min": null, "public_financing_total": 223410, "other_sources_total": 148665, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-11-13T01:50:37.570747", "cost_min": null, "direct_rep_costs_max": null, "representative": "c3a15479c001435693b4e972f9932dc4", "cost_absolute": 1062180, "eur_sources_grants_src": null, "id": "ff634677ea944e0e9da29280bd1c8e21", "customIncomes": [{"status": "active", "name": "Pays non UE", "created_at": "2015-05-29T00:12:53.126202", "updated_at": "2015-05-29T00:12:53.124173", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/f3a51689636a4015b7ef0c9514db029f", "amount": 263712, "type": "public", "id": "f3a51689636a4015b7ef0c9514db029f"}], "total_budget": 1062180, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": null, "created_at": "2015-05-29T00:12:53.091229", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff634677ea944e0e9da29280bd1c8e21", "public_financing_infranational": 243854, "direct_rep_costs_min": null, "public_financing_total": 1055017, "other_sources_total": 7163, "other_financial_information": null, "public_financing_national": 547451, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-09-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-09T01:07:33.143858", "cost_min": null, "direct_rep_costs_max": null, "representative": "ea9f0c320b13411498459ecfdf75372f", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff631c5d015940a2b27d805ad219aff4", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-04-24T01:54:58.173774", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff631c5d015940a2b27d805ad219aff4", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2013-10-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": 100000, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": 499999, "updated_at": "2016-04-27T01:07:20.498409", "cost_min": 100000, "direct_rep_costs_max": null, "representative": "b7e55c858616434bbb585b0568ced38b", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff61fb9d5de04800a7e52be0c18ac00f", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 199999, "created_at": "2016-04-24T01:06:40.000683", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff61fb9d5de04800a7e52be0c18ac00f", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataLawyer", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-05T01:12:31.130346", "cost_min": null, "direct_rep_costs_max": null, "representative": "7334c9fa6a2e47f7b60523e96ef415ae", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff602bc4988b41c6b703f52b665cd117", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-04-05T01:12:31.132703", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff602bc4988b41c6b703f52b665cd117", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "ENFE is financed by membership fees.", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-07-26T02:14:27.877008", "cost_min": 25000, "direct_rep_costs_max": null, "representative": "36e5d2c3a82d41eab1c70dfd170f186f", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff5cc562357044969f96a169e6d989e9", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 49999, "created_at": "2016-07-26T02:14:27.879571", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff5cc562357044969f96a169e6d989e9", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-09T00:57:05.899581", "cost_min": null, "direct_rep_costs_max": null, "representative": "a55336f005c8483897cf1afea7a77406", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff5bf36cf6a84021ba3dc262cfe9e63e", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-04-24T01:47:51.877769", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff5bf36cf6a84021ba3dc262cfe9e63e", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": 91548, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2011-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-07-29T23:29:35.482487", "cost_min": null, "direct_rep_costs_max": null, "representative": "fee73f7916f94c36b2f90c4e1b294a51", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff59ceb8e0cb4cb19e254cb971358dc7", "customIncomes": [], "total_budget": 141548, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": 91548, "cost_max": 9999, "created_at": "2015-04-24T02:08:08.998718", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff59ceb8e0cb4cb19e254cb971358dc7", "public_financing_infranational": 9000, "direct_rep_costs_min": null, "public_financing_total": 9000, "other_sources_total": 132548, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2010-12-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-09T01:02:22.851486", "cost_min": 4750000, "direct_rep_costs_max": null, "representative": "f5bb3f9a04154a1da09833863e665717", "cost_absolute": null, "eur_sources_grants_src": "EASY (DG EMPL); H2020; FP7", "id": "ff59a2fdf8d14c83ab787b0ced87c730", "customIncomes": [{"status": "active", "name": "Meeting room rental/financial interests", "created_at": "2016-03-09T01:02:22.888002", "updated_at": "2016-03-09T01:02:22.886828", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/11b3d3217d624f3d90541293e217588f", "amount": 23577, "type": "other", "id": "11b3d3217d624f3d90541293e217588f"}], "total_budget": 4809810, "turnover_absolute": null, "eur_sources_grants": 2574753, "other_sources_contributions": null, "cost_max": 4999999, "created_at": "2016-03-09T01:02:22.853972", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff59a2fdf8d14c83ab787b0ced87c730", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": 2574753, "other_sources_total": 2235057, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-06-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-05-20T00:29:19.429630", "cost_min": null, "direct_rep_costs_max": null, "representative": "ff6ce8c03aee44788ce83a6544cdbb4c", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff564fe63435452b80ac8bbd2a079260", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2015-06-18T00:07:53.894598", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff564fe63435452b80ac8bbd2a079260", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-07-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-04-28T00:17:45.663986", "cost_min": 50000, "direct_rep_costs_max": null, "representative": "c34ceb998f4c4b70b7db662165a9de54", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff555374506c4af6ae57bae7e9c1b51a", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 99999, "created_at": "2015-04-24T01:53:09.466077", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff555374506c4af6ae57bae7e9c1b51a", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 5764592, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": "Executive Agency for Competitiveness and Innovation and Directorate General for Enterprise and Industry", "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-26T00:33:54.789304", "cost_min": null, "direct_rep_costs_max": null, "representative": "3c39e2830d4741ed99f4d21ca05872fa", "cost_absolute": 2850000, "eur_sources_grants_src": null, "id": "ff4950d785a94c028b1dfbf4de3e5ec6", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": null, "created_at": "2015-04-24T02:14:56.286856", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff4950d785a94c028b1dfbf4de3e5ec6", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-17T01:23:25.917730", "cost_min": null, "direct_rep_costs_max": null, "representative": "a8459278c5b04861b6b02e8bcca18a4a", "cost_absolute": 200000, "eur_sources_grants_src": null, "id": "ff46b2e339fc4aa1bfb69c79dc4319a2", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": null, "created_at": "2015-04-24T01:52:20.961870", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff46b2e339fc4aa1bfb69c79dc4319a2", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "Der dbb wird im Wesentlichen durch seine europ\u00e4ische Dachorganisation CESI direkt gegen\u00fcber den EU-Organen vertreten. Die CESI ist registriert.", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": 3000, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-06-17T02:04:41.712226", "cost_min": null, "direct_rep_costs_max": null, "representative": "ff1754756bf64805831e8bb4c762109a", "cost_absolute": null, "eur_sources_grants_src": "eu dg home", "id": "ff43a00340f94a11847e8a1183f599f3", "customIncomes": [{"status": "active", "name": "grants", "created_at": "2016-06-17T02:04:41.774315", "updated_at": "2016-06-17T02:04:41.773044", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/b180289e9a144e9ab5b2c26c1c32e926", "amount": 74500, "type": "other", "id": "b180289e9a144e9ab5b2c26c1c32e926"}, {"status": "active", "name": "consultancy", "created_at": "2016-06-17T02:04:41.867067", "updated_at": "2016-06-17T02:04:41.865509", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/ad00aa1b40a5478490b7082f7edccc60", "amount": 6000, "type": "other", "id": "ad00aa1b40a5478490b7082f7edccc60"}, {"status": "active", "name": "others", "created_at": "2016-06-17T02:04:41.885844", "updated_at": "2016-06-17T02:04:41.884649", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/00607b57a2c4476ea3c10c3997ff9177", "amount": 9000, "type": "other", "id": "00607b57a2c4476ea3c10c3997ff9177"}], "total_budget": 121150, "turnover_absolute": null, "eur_sources_grants": 28500, "other_sources_contributions": 3000, "cost_max": 9999, "created_at": "2016-06-17T02:04:41.715911", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff43a00340f94a11847e8a1183f599f3", "public_financing_infranational": 0, "direct_rep_costs_min": null, "public_financing_total": 28500, "other_sources_total": 92650, "other_financial_information": null, "public_financing_national": 0, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-01-09T02:48:48.670185", "cost_min": 100000, "direct_rep_costs_max": null, "representative": "a5c4b373e2dd41309c42b6211cbbed1b", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff3e7bd1d757476babb322207fd89431", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 199999, "created_at": "2016-01-09T02:48:48.673828", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff3e7bd1d757476babb322207fd89431", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "we have submitted in Nov 2015 a project for EC financing under the SME Disruptive Innovation ICT37 track", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-03-26T01:42:52.941422", "cost_min": 100000, "direct_rep_costs_max": null, "representative": "2d1a7981a27f4caeb5a8f43eeb02de47", "cost_absolute": null, "eur_sources_grants_src": "programme MEDIA; fonds FEDER", "id": "ff3d73cd3d674f9ab63882344903c865", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 1935358, "other_sources_contributions": null, "cost_max": 199999, "created_at": "2015-04-24T02:20:10.869745", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff3d73cd3d674f9ab63882344903c865", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "inactive", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2013-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-02T00:07:59.374410", "cost_min": 10000, "direct_rep_costs_max": null, "representative": "e2d7e43581d34104b45bb5ac4d671df5", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff399ec0cd394a0da59444715097da16", "customIncomes": [{"status": "active", "name": "EU funded projects", "created_at": "2015-05-28T01:36:05.276235", "updated_at": "2015-05-28T01:36:05.274118", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/5eb829db8645496eb7da6dd9ba230aa0", "amount": 21655, "type": "public", "id": "5eb829db8645496eb7da6dd9ba230aa0"}], "total_budget": 52455, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 24999, "created_at": "2015-04-24T01:54:42.816653", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff399ec0cd394a0da59444715097da16", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": 21655, "other_sources_total": 30800, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2013-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-07-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": 99999, "updated_at": "2016-03-01T02:27:09.807510", "cost_min": null, "direct_rep_costs_max": null, "representative": "2d11327ea91f426394661d573a3b0823", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff3925bb093f42f3aad57207d507307c", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-03-01T02:27:09.811227", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff3925bb093f42f3aad57207d507307c", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": "nothing to report", "type": "FinancialDataLawyer", "start_date": "2014-07-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2016-05-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-05-14T01:23:57.344764", "cost_min": null, "direct_rep_costs_max": null, "representative": "3b3953455f344ddf983af43d791d30e8", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff32000e621a4160b10fcc71dffb4194", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-05-14T01:23:57.349338", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff32000e621a4160b10fcc71dffb4194", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "EPIC is not dependent on any EU subsidies and has a very limited budget. The secretariat is financed by NVC (meeting room for biannual plenary meetings and backoffice for data-exchange and communication) whereas the member-institutes (including NVC) cover their own expenses (travel, attending meetings, etc.) on a voluntary basis. ", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-06-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-02-18T02:20:45.702640", "cost_min": 25000, "direct_rep_costs_max": null, "representative": "4270dcf1403d40299c380499dddda0a7", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff305f722afd49ea86de0746cc70d3ab", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 49999, "created_at": "2016-02-18T02:20:45.704520", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff305f722afd49ea86de0746cc70d3ab", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-10-29T01:59:24.507191", "cost_min": null, "direct_rep_costs_max": null, "representative": "98dc888ca71240ff93db25822ca0c11a", "cost_absolute": 35000, "eur_sources_grants_src": null, "id": "ff2d7cdd117b43f6ab44e119a1bafca4", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": null, "created_at": "2015-10-29T01:59:24.510841", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2d7cdd117b43f6ab44e119a1bafca4", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": null, "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2014-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2015-10-15T00:49:59.154282", "cost_min": 100000, "direct_rep_costs_max": null, "representative": "a6659a7ac34a46ae8af3c7035e318d5b", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff2c1c60233d4584a30376b886eb6670", "customIncomes": [], "total_budget": 0, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 199999, "created_at": "2015-10-15T00:49:59.159594", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2c1c60233d4584a30376b886eb6670", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "we receive our budget from the Moroccan Finance Department", "public_financing_national": null, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2014-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 0, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": null, "new_organisation": null, "turnover_max": null, "updated_at": "2016-07-14T02:14:13.083569", "cost_min": 50000, "direct_rep_costs_max": null, "representative": "75f442e91d054c00a56c4488b9159c4f", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff2b9ed37dd64e0bba88065da1e2e0b8", "customIncomes": [], "total_budget": null, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 99999, "created_at": "2016-07-14T02:14:13.087248", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2b9ed37dd64e0bba88065da1e2e0b8", "public_financing_infranational": null, "direct_rep_costs_min": null, "public_financing_total": null, "other_sources_total": null, "other_financial_information": "Finazierung aus Mitgliederbeitr\u00e4gen", "public_financing_national": null, "no_clients": null, "type": "FinancialDataTradeAssociation", "start_date": "2015-01-01T00:00:00"}, {"other_sources_donation": null, "status": "active", "turnover_min": null, "eur_sources_procurement": 28378, "end_date": "2015-12-01T00:00:00", "eur_sources_procurement_src": "Daguerreobase Project", "new_organisation": null, "turnover_max": null, "updated_at": "2016-04-23T01:13:50.286315", "cost_min": null, "direct_rep_costs_max": null, "representative": "54a567a6dd454450a5c5e6d9077f1988", "cost_absolute": null, "eur_sources_grants_src": null, "id": "ff2b598043f04061a50bc70240cd6354", "customIncomes": [{"status": "active", "name": "Shopinkomsten", "created_at": "2016-04-23T01:13:50.325922", "updated_at": "2016-04-23T01:13:50.323842", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/5e8bdfbae8794dceb91fbc7fa6025d9a", "amount": 133026, "type": "other", "id": "5e8bdfbae8794dceb91fbc7fa6025d9a"}, {"status": "active", "name": "Zaalverhuur en concessie", "created_at": "2016-04-23T01:13:50.338422", "updated_at": "2016-04-23T01:13:50.336526", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/ca0e76ad7a2644528a875233550fa301", "amount": 37274, "type": "other", "id": "ca0e76ad7a2644528a875233550fa301"}, {"status": "active", "name": "Organisatie publieksactiviteiten", "created_at": "2016-04-23T01:13:50.372977", "updated_at": "2016-04-23T01:13:50.371056", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/acceed6d3ad0465ba2876c2c51161bbe", "amount": 56076, "type": "other", "id": "acceed6d3ad0465ba2876c2c51161bbe"}, {"status": "active", "name": "Personeelsubsidies", "created_at": "2016-04-23T01:13:50.485699", "updated_at": "2016-04-23T01:13:50.483938", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/83f204483e2940ee8bf6815e13c0c5d1", "amount": 3981, "type": "other", "id": "83f204483e2940ee8bf6815e13c0c5d1"}, {"status": "active", "name": "Varia opbrengsten", "created_at": "2016-04-23T01:13:50.516579", "updated_at": "2016-04-23T01:13:50.514618", "uri": "http://api.lobbyfacts.eu/api/1/custom_income/bcddc8a783424f8dadc8628a6a27d7bb", "amount": 67722, "type": "other", "id": "bcddc8a783424f8dadc8628a6a27d7bb"}], "total_budget": 3002447, "turnover_absolute": null, "eur_sources_grants": 0, "other_sources_contributions": null, "cost_max": 9999, "created_at": "2016-04-23T01:13:50.290118", "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2b598043f04061a50bc70240cd6354", "public_financing_infranational": 2260632, "direct_rep_costs_min": null, "public_financing_total": 2496215, "other_sources_total": 506232, "other_financial_information": null, "public_financing_national": 207205, "no_clients": null, "type": "FinancialDataNGO", "start_date": "2015-01-01T00:00:00"}], "next": "http://api.lobbyfacts.eu/api/1/financial_data?limit=50&offset=50", "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 17266, + "facets": {}, + "results": [ + { + "other_sources_donation": 385213, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-09-18T00:49:01.406041Z", + "cost_min": 100000, + "direct_rep_costs_max": null, + "representative": "013b6cca4abc4e25b5e8bb66dc77e38e", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "fffabd366dd44c4fb7379481a638eecd", + "customIncomes": [], + "total_budget": 660960, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": 385213, + "cost_max": 199999, + "created_at": "2015-09-18T00:49:01.409679Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/fffabd366dd44c4fb7379481a638eecd", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": 275747, + "other_sources_total": 385213, + "other_financial_information": "We used a \u20ac/CHF exchange rate of 1.10, as per info from the ECB on 16 September 2015.", + "public_financing_national": 275747, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": 99999, + "updated_at": "2016-05-05T01:35:10.407461Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "f1622c9caf54453d9a6c04804863ce0e", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "fff1768c0aa64f0799667e2522c3f340", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-05-24T21:46:36.026780Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/fff1768c0aa64f0799667e2522c3f340", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataLawyer", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2016-01-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-06-01T01:55:18.942873Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "12750bb632484a9ca2b66d2d0c697f42", + "cost_absolute": 100, + "eur_sources_grants_src": null, + "id": "ffe6a717d0494855b30df00b0aa364dd", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2016-06-01T01:55:18.946640Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffe6a717d0494855b30df00b0aa364dd", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-30T00:31:22.089325Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "ee3f932f5f9a46b793f4575d3c4a1ba1", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffdd7866367541999ce4ed1de30bad50", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-03-30T00:31:22.091930Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffdd7866367541999ce4ed1de30bad50", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "Les comptes financiers du GIGREL sont certifi\u00e9s par un expert comptable", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-09T01:03:26.456171Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "4a97ff579f39418b8ac1ab3aaed88932", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffdb787db80d45cb9f1988f9dffd3d79", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-04-24T01:52:29.207871Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffdb787db80d45cb9f1988f9dffd3d79", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-21T02:00:24.411627Z", + "cost_min": 25000, + "direct_rep_costs_max": null, + "representative": "e0cf2c23c0974c689bb92910659121d4", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffd5741012184e55b901bfa4774ca121", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": 45122748, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 49999, + "created_at": "2016-02-09T02:56:30.457858Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffd5741012184e55b901bfa4774ca121", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataLawyer", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": 54154, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-05-24T23:54:56.661915Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "fc6ba4bc05754730b435e3ad248475ae", + "cost_absolute": null, + "eur_sources_grants_src": "EIDHR", + "id": "ffd55c90a2eb4e5fa0aef212f9e1e46d", + "customIncomes": [ + { + "status": "active", + "name": "UN bodies", + "created_at": "2015-05-28T02:15:19.669323Z", + "updated_at": "2015-05-28T02:15:19.668220Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/9a969481456647d68653dd83aac11246", + "amount": 243151, + "type": "public", + "id": "9a969481456647d68653dd83aac11246" + }, + { + "status": "active", + "name": "Trusts and foundations", + "created_at": "2015-05-28T02:15:19.683645Z", + "updated_at": "2015-05-28T02:15:19.682195Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/d6555ad554614b8685609d5780f6b575", + "amount": 241759, + "type": "public", + "id": "d6555ad554614b8685609d5780f6b575" + }, + { + "status": "active", + "name": "Publishing rights", + "created_at": "2015-05-28T02:15:19.689808Z", + "updated_at": "2015-05-28T02:15:19.688752Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/889cfd75b53c4c26a52db0c84c6db2ab", + "amount": 590, + "type": "public", + "id": "889cfd75b53c4c26a52db0c84c6db2ab" + }, + { + "status": "active", + "name": "Interest", + "created_at": "2015-05-28T02:15:19.695412Z", + "updated_at": "2015-05-28T02:15:19.694444Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/4da5bb10577f498aa12d7ac9d3fcfbb1", + "amount": 344, + "type": "public", + "id": "4da5bb10577f498aa12d7ac9d3fcfbb1" + }, + { + "status": "active", + "name": "Other INGOS & NGOs", + "created_at": "2015-05-28T02:15:19.701039Z", + "updated_at": "2015-05-28T02:15:19.700107Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/3cd306bd22394082b4f819c027d3b74f", + "amount": 44147, + "type": "public", + "id": "3cd306bd22394082b4f819c027d3b74f" + } + ], + "total_budget": 4504192, + "turnover_absolute": null, + "eur_sources_grants": 1317691, + "other_sources_contributions": 54154, + "cost_max": 9999, + "created_at": "2015-05-07T21:30:43.767784Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffd55c90a2eb4e5fa0aef212f9e1e46d", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": 4450038, + "other_sources_total": 54154, + "other_financial_information": null, + "public_financing_national": 2602356, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-09T01:49:19.041473Z", + "cost_min": 25000, + "direct_rep_costs_max": null, + "representative": "6ffd2947b99e49559eccd74a21e7f508", + "cost_absolute": null, + "eur_sources_grants_src": "Intelligent Energy Europe (IEE), LIFE Operating grant, Executive Agency for Small and Medium-sized Enterprises (EASME)", + "id": "ffd1d420375949a68d4eb2283aca2d5d", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 470000, + "other_sources_contributions": null, + "cost_max": 49999, + "created_at": "2016-03-09T01:49:19.045719Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffd1d420375949a68d4eb2283aca2d5d", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-06-18T00:54:28.859949Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "eb7a9c91b2da4c1da909d04ac1bb1466", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffcd0088616146d6baf3a0c2ccc2e7a9", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-06-18T00:54:28.863595Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffcd0088616146d6baf3a0c2ccc2e7a9", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-17T01:15:00.692458Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "97bd0a0054a64b02a2a8d7aa01d9e88a", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffcc874f7b75440ca06df46679b6deca", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-03-17T01:15:00.696615Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffcc874f7b75440ca06df46679b6deca", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-06-09T00:26:54.823237Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "ae97df280eab44b5b40098197708efe6", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffc19765007c4f3aba8eaa48c684a554", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-04-24T02:30:25.668792Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffc19765007c4f3aba8eaa48c684a554", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-17T01:58:15.973638Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "6092b03e7105428cb513e9e249d5c4d7", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffc16d5a6e344038b5377e45960be787", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-03-17T01:58:15.977827Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffc16d5a6e344038b5377e45960be787", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": 100000, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": 499999, + "updated_at": "2016-04-08T01:00:23.785525Z", + "cost_min": 300000, + "direct_rep_costs_max": null, + "representative": "c75f8e81295d4cbb880758d6e18b3589", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffb97483dfbe470cbda4933c09260bde", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 399999, + "created_at": "2016-04-08T01:00:23.787495Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffb97483dfbe470cbda4933c09260bde", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataLawyer", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": 0, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2013-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-07T00:14:47.973821Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "6a2d6670e2ce4af1882c75ddd9666fc5", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffaf85a0e6a94685964f432cdd142bef", + "customIncomes": [], + "total_budget": 13000000, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": 0, + "cost_max": 9999, + "created_at": "2015-04-24T01:59:26.164126Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffaf85a0e6a94685964f432cdd142bef", + "public_financing_infranational": 0, + "direct_rep_costs_min": null, + "public_financing_total": 13000000, + "other_sources_total": 0, + "other_financial_information": "We are 100 percent funded by the Norwegian state and our staff only work part time on EU advocacy. ", + "public_financing_national": 13000000, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2013-01-01T00:00:00Z" + }, + { + "other_sources_donation": 29047000, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-06-25T00:13:19.257034Z", + "cost_min": 300000, + "direct_rep_costs_max": null, + "representative": "a1f2638c81034e07a2ab3ed2c54e6097", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffaf83bd49424f3baa0716d70e1da1f9", + "customIncomes": [], + "total_budget": 29047000, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": 29047000, + "cost_max": 399999, + "created_at": "2015-06-17T23:52:51.768558Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffaf83bd49424f3baa0716d70e1da1f9", + "public_financing_infranational": 0, + "direct_rep_costs_min": null, + "public_financing_total": 0, + "other_sources_total": 29047000, + "other_financial_information": "Major funders of the ECF are:\r\n- Children\u2019s Investment Fund Foundation (United Kingdom)\r\n- McCall MacBain Foundation (Switzerland)\r\n- Oak Foundation (Switzerland)\r\n- ClimateWorks Foundation (United States of America)\r\n- Nationale Postcode Loterij (Netherlands)\r\n- Villum Fonden (Denmark)", + "public_financing_national": 0, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-09-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-21T01:16:37.966794Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "51897d28145f4329bf55bf89a8ac50b8", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffa71efed5f74254888217e6a68e7905", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-05-07T21:12:34.739366Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffa71efed5f74254888217e6a68e7905", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2013-10-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": 99999, + "updated_at": "2016-05-05T01:23:13.676750Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "48aa47f2326b4227a5cc9421ab45fd22", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ffa5b73fc4b5448ea6c27cf043991cb6", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-05-07T21:27:39.131564Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ffa5b73fc4b5448ea6c27cf043991cb6", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataLawyer", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2016-01-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-17T01:35:12.589885Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "0b5fe36ecd114b729aab1d8683a34215", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff8f43a4f7e14aadaf98988bc0314d50", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-03-17T01:35:12.593635Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff8f43a4f7e14aadaf98988bc0314d50", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "100% funded by companies active in the UK paper industry.", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": 30000, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-26T02:30:00.483178Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "8e920e7a62994b1ebd9faec199d5534b", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff8ec78386384e4bb6c56dcead8b764a", + "customIncomes": [], + "total_budget": 60000, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": 30000, + "cost_max": 9999, + "created_at": "2015-09-23T00:50:08.119641Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff8ec78386384e4bb6c56dcead8b764a", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": 60000, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-12-04T02:36:08.694295Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "a3bbdd184d114bd19a444cd72882e635", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff8aac50ab16444cb3e65e75a228f2de", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-12-04T02:36:08.697897Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff8aac50ab16444cb3e65e75a228f2de", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": "0", + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-02-11T02:56:04.443073Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "24ccf60ad967421d846dc0c78e8adbb8", + "cost_absolute": 50000, + "eur_sources_grants_src": "Lifelong learning Programme-Grundtvig", + "id": "ff87048f461c460f9d934eb7a530dfba", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 2000, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2016-02-11T02:56:04.446801Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff87048f461c460f9d934eb7a530dfba", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-12-23T02:43:03.491517Z", + "cost_min": 300000, + "direct_rep_costs_max": null, + "representative": "29f14de439a848b6a93183888b909da5", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff7baad305284c0b9038ec8838a300a7", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 399999, + "created_at": "2015-12-23T02:43:03.495155Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff7baad305284c0b9038ec8838a300a7", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-27T01:01:20.211310Z", + "cost_min": 100000, + "direct_rep_costs_max": null, + "representative": "e5a7554197164c53886192d861babdd3", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff73bcf48e4e4cc3a3e49a1bd26e98a7", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 199999, + "created_at": "2015-05-07T21:12:38.474975Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff73bcf48e4e4cc3a3e49a1bd26e98a7", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "ECG's main source of funding is via its membership fees, and the costs attributable to activities covered by the Register have been estimated according to its Implementing Guidelines as well as the SEAP Guidelines (of which the ECG EU Affairs Adviser is a member in his personal capacity).", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-01-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-05-14T01:25:59.026666Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "49922f3520e7430abc76aed24f3e3d14", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff661b8905174738859139b1d111b590", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-05-24T21:44:12.205154Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff661b8905174738859139b1d111b590", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2013-02-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-21T00:20:41.720896Z", + "cost_min": 10000, + "direct_rep_costs_max": null, + "representative": "eb2693775b7a40f09063bb5e35ec3aac", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff655f4300214430b018f37da655bb5c", + "customIncomes": [], + "total_budget": 0, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 24999, + "created_at": "2016-03-17T01:25:55.168580Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff655f4300214430b018f37da655bb5c", + "public_financing_infranational": 0, + "direct_rep_costs_min": null, + "public_financing_total": 0, + "other_sources_total": 0, + "other_financial_information": "EFIC has own budget from biennial congresses and annual royalties of our medical online journal (European Journal of Pain) and receives unrestricted grants from the pharmaceutical companies. As an organisation representing healthcare professionals working in the field of pain care, only a small proportion of our activities are covered by the Transparency Register, with the rest dedicated to education, training and best practice sharing amongst professionals.", + "public_financing_national": 0, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": "-", + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-08-31T01:12:27.637001Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "c81d9bc7ee0e4345a5be20393ff9fed6", + "cost_absolute": 850000, + "eur_sources_grants_src": "Comisi\u00f3n Europea", + "id": "ff6429e2edad450786b5a47cc77b5601", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": 850000, + "eur_sources_grants": 1107051, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2016-08-31T01:12:27.641759Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff6429e2edad450786b5a47cc77b5601", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "Las subvenciones recibidas corresponden a proyectos europeos (como el S\u00e9ptimo Programa Marco) en colaboraci\u00f3n en los que Zabala ha participado como l\u00edder o socio.", + "public_financing_national": null, + "no_clients": "Actividades propias", + "type": "FinancialDataLawyer", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-09T01:41:33.481929Z", + "cost_min": 400000, + "direct_rep_costs_max": null, + "representative": "e1ef1a5ab7f540929f8512c95f0600b0", + "cost_absolute": null, + "eur_sources_grants_src": "LIFE+, Horizon 2020 programme , Interreg, FP7", + "id": "ff63c2f0a1a54fbebd729ce7c53935ad", + "customIncomes": [], + "total_budget": 372075, + "turnover_absolute": null, + "eur_sources_grants": 123410, + "other_sources_contributions": null, + "cost_max": 499999, + "created_at": "2016-03-09T01:41:33.485949Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff63c2f0a1a54fbebd729ce7c53935ad", + "public_financing_infranational": 100000, + "direct_rep_costs_min": null, + "public_financing_total": 223410, + "other_sources_total": 148665, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-11-13T01:50:37.570747Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "c3a15479c001435693b4e972f9932dc4", + "cost_absolute": 1062180, + "eur_sources_grants_src": null, + "id": "ff634677ea944e0e9da29280bd1c8e21", + "customIncomes": [ + { + "status": "active", + "name": "Pays non UE", + "created_at": "2015-05-29T00:12:53.126202Z", + "updated_at": "2015-05-29T00:12:53.124173Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/f3a51689636a4015b7ef0c9514db029f", + "amount": 263712, + "type": "public", + "id": "f3a51689636a4015b7ef0c9514db029f" + } + ], + "total_budget": 1062180, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2015-05-29T00:12:53.091229Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff634677ea944e0e9da29280bd1c8e21", + "public_financing_infranational": 243854, + "direct_rep_costs_min": null, + "public_financing_total": 1055017, + "other_sources_total": 7163, + "other_financial_information": null, + "public_financing_national": 547451, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-09-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-09T01:07:33.143858Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "ea9f0c320b13411498459ecfdf75372f", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff631c5d015940a2b27d805ad219aff4", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-04-24T01:54:58.173774Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff631c5d015940a2b27d805ad219aff4", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2013-10-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": 100000, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": 499999, + "updated_at": "2016-04-27T01:07:20.498409Z", + "cost_min": 100000, + "direct_rep_costs_max": null, + "representative": "b7e55c858616434bbb585b0568ced38b", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff61fb9d5de04800a7e52be0c18ac00f", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 199999, + "created_at": "2016-04-24T01:06:40.000683Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff61fb9d5de04800a7e52be0c18ac00f", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataLawyer", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-05T01:12:31.130346Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "7334c9fa6a2e47f7b60523e96ef415ae", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff602bc4988b41c6b703f52b665cd117", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-04-05T01:12:31.132703Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff602bc4988b41c6b703f52b665cd117", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "ENFE is financed by membership fees.", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-07-26T02:14:27.877008Z", + "cost_min": 25000, + "direct_rep_costs_max": null, + "representative": "36e5d2c3a82d41eab1c70dfd170f186f", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff5cc562357044969f96a169e6d989e9", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 49999, + "created_at": "2016-07-26T02:14:27.879571Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff5cc562357044969f96a169e6d989e9", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-09T00:57:05.899581Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "a55336f005c8483897cf1afea7a77406", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff5bf36cf6a84021ba3dc262cfe9e63e", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-04-24T01:47:51.877769Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff5bf36cf6a84021ba3dc262cfe9e63e", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": 91548, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2011-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-07-29T23:29:35.482487Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "fee73f7916f94c36b2f90c4e1b294a51", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff59ceb8e0cb4cb19e254cb971358dc7", + "customIncomes": [], + "total_budget": 141548, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": 91548, + "cost_max": 9999, + "created_at": "2015-04-24T02:08:08.998718Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff59ceb8e0cb4cb19e254cb971358dc7", + "public_financing_infranational": 9000, + "direct_rep_costs_min": null, + "public_financing_total": 9000, + "other_sources_total": 132548, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2010-12-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-09T01:02:22.851486Z", + "cost_min": 4750000, + "direct_rep_costs_max": null, + "representative": "f5bb3f9a04154a1da09833863e665717", + "cost_absolute": null, + "eur_sources_grants_src": "EASY (DG EMPL); H2020; FP7", + "id": "ff59a2fdf8d14c83ab787b0ced87c730", + "customIncomes": [ + { + "status": "active", + "name": "Meeting room rental/financial interests", + "created_at": "2016-03-09T01:02:22.888002Z", + "updated_at": "2016-03-09T01:02:22.886828Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/11b3d3217d624f3d90541293e217588f", + "amount": 23577, + "type": "other", + "id": "11b3d3217d624f3d90541293e217588f" + } + ], + "total_budget": 4809810, + "turnover_absolute": null, + "eur_sources_grants": 2574753, + "other_sources_contributions": null, + "cost_max": 4999999, + "created_at": "2016-03-09T01:02:22.853972Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff59a2fdf8d14c83ab787b0ced87c730", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": 2574753, + "other_sources_total": 2235057, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-06-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-05-20T00:29:19.429630Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "ff6ce8c03aee44788ce83a6544cdbb4c", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff564fe63435452b80ac8bbd2a079260", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2015-06-18T00:07:53.894598Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff564fe63435452b80ac8bbd2a079260", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-07-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-04-28T00:17:45.663986Z", + "cost_min": 50000, + "direct_rep_costs_max": null, + "representative": "c34ceb998f4c4b70b7db662165a9de54", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff555374506c4af6ae57bae7e9c1b51a", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 99999, + "created_at": "2015-04-24T01:53:09.466077Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff555374506c4af6ae57bae7e9c1b51a", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 5764592, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": "Executive Agency for Competitiveness and Innovation and Directorate General for Enterprise and Industry", + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-26T00:33:54.789304Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "3c39e2830d4741ed99f4d21ca05872fa", + "cost_absolute": 2850000, + "eur_sources_grants_src": null, + "id": "ff4950d785a94c028b1dfbf4de3e5ec6", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2015-04-24T02:14:56.286856Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff4950d785a94c028b1dfbf4de3e5ec6", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-17T01:23:25.917730Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "a8459278c5b04861b6b02e8bcca18a4a", + "cost_absolute": 200000, + "eur_sources_grants_src": null, + "id": "ff46b2e339fc4aa1bfb69c79dc4319a2", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2015-04-24T01:52:20.961870Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff46b2e339fc4aa1bfb69c79dc4319a2", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "Der dbb wird im Wesentlichen durch seine europ\u00e4ische Dachorganisation CESI direkt gegen\u00fcber den EU-Organen vertreten. Die CESI ist registriert.", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": 3000, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-06-17T02:04:41.712226Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "ff1754756bf64805831e8bb4c762109a", + "cost_absolute": null, + "eur_sources_grants_src": "eu dg home", + "id": "ff43a00340f94a11847e8a1183f599f3", + "customIncomes": [ + { + "status": "active", + "name": "grants", + "created_at": "2016-06-17T02:04:41.774315Z", + "updated_at": "2016-06-17T02:04:41.773044Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/b180289e9a144e9ab5b2c26c1c32e926", + "amount": 74500, + "type": "other", + "id": "b180289e9a144e9ab5b2c26c1c32e926" + }, + { + "status": "active", + "name": "consultancy", + "created_at": "2016-06-17T02:04:41.867067Z", + "updated_at": "2016-06-17T02:04:41.865509Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/ad00aa1b40a5478490b7082f7edccc60", + "amount": 6000, + "type": "other", + "id": "ad00aa1b40a5478490b7082f7edccc60" + }, + { + "status": "active", + "name": "others", + "created_at": "2016-06-17T02:04:41.885844Z", + "updated_at": "2016-06-17T02:04:41.884649Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/00607b57a2c4476ea3c10c3997ff9177", + "amount": 9000, + "type": "other", + "id": "00607b57a2c4476ea3c10c3997ff9177" + } + ], + "total_budget": 121150, + "turnover_absolute": null, + "eur_sources_grants": 28500, + "other_sources_contributions": 3000, + "cost_max": 9999, + "created_at": "2016-06-17T02:04:41.715911Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff43a00340f94a11847e8a1183f599f3", + "public_financing_infranational": 0, + "direct_rep_costs_min": null, + "public_financing_total": 28500, + "other_sources_total": 92650, + "other_financial_information": null, + "public_financing_national": 0, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-01-09T02:48:48.670185Z", + "cost_min": 100000, + "direct_rep_costs_max": null, + "representative": "a5c4b373e2dd41309c42b6211cbbed1b", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff3e7bd1d757476babb322207fd89431", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 199999, + "created_at": "2016-01-09T02:48:48.673828Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff3e7bd1d757476babb322207fd89431", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "we have submitted in Nov 2015 a project for EC financing under the SME Disruptive Innovation ICT37 track", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-03-26T01:42:52.941422Z", + "cost_min": 100000, + "direct_rep_costs_max": null, + "representative": "2d1a7981a27f4caeb5a8f43eeb02de47", + "cost_absolute": null, + "eur_sources_grants_src": "programme MEDIA; fonds FEDER", + "id": "ff3d73cd3d674f9ab63882344903c865", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 1935358, + "other_sources_contributions": null, + "cost_max": 199999, + "created_at": "2015-04-24T02:20:10.869745Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff3d73cd3d674f9ab63882344903c865", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "inactive", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2013-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-02T00:07:59.374410Z", + "cost_min": 10000, + "direct_rep_costs_max": null, + "representative": "e2d7e43581d34104b45bb5ac4d671df5", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff399ec0cd394a0da59444715097da16", + "customIncomes": [ + { + "status": "active", + "name": "EU funded projects", + "created_at": "2015-05-28T01:36:05.276235Z", + "updated_at": "2015-05-28T01:36:05.274118Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/5eb829db8645496eb7da6dd9ba230aa0", + "amount": 21655, + "type": "public", + "id": "5eb829db8645496eb7da6dd9ba230aa0" + } + ], + "total_budget": 52455, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 24999, + "created_at": "2015-04-24T01:54:42.816653Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff399ec0cd394a0da59444715097da16", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": 21655, + "other_sources_total": 30800, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2013-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-07-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": 99999, + "updated_at": "2016-03-01T02:27:09.807510Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "2d11327ea91f426394661d573a3b0823", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff3925bb093f42f3aad57207d507307c", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-03-01T02:27:09.811227Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff3925bb093f42f3aad57207d507307c", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": "nothing to report", + "type": "FinancialDataLawyer", + "start_date": "2014-07-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2016-05-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-05-14T01:23:57.344764Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "3b3953455f344ddf983af43d791d30e8", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff32000e621a4160b10fcc71dffb4194", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-05-14T01:23:57.349338Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff32000e621a4160b10fcc71dffb4194", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "EPIC is not dependent on any EU subsidies and has a very limited budget. The secretariat is financed by NVC (meeting room for biannual plenary meetings and backoffice for data-exchange and communication) whereas the member-institutes (including NVC) cover their own expenses (travel, attending meetings, etc.) on a voluntary basis. ", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-06-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-02-18T02:20:45.702640Z", + "cost_min": 25000, + "direct_rep_costs_max": null, + "representative": "4270dcf1403d40299c380499dddda0a7", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff305f722afd49ea86de0746cc70d3ab", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 49999, + "created_at": "2016-02-18T02:20:45.704520Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff305f722afd49ea86de0746cc70d3ab", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-10-29T01:59:24.507191Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "98dc888ca71240ff93db25822ca0c11a", + "cost_absolute": 35000, + "eur_sources_grants_src": null, + "id": "ff2d7cdd117b43f6ab44e119a1bafca4", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": null, + "created_at": "2015-10-29T01:59:24.510841Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2d7cdd117b43f6ab44e119a1bafca4", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": null, + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2014-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2015-10-15T00:49:59.154282Z", + "cost_min": 100000, + "direct_rep_costs_max": null, + "representative": "a6659a7ac34a46ae8af3c7035e318d5b", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff2c1c60233d4584a30376b886eb6670", + "customIncomes": [], + "total_budget": 0, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 199999, + "created_at": "2015-10-15T00:49:59.159594Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2c1c60233d4584a30376b886eb6670", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "we receive our budget from the Moroccan Finance Department", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2014-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 0, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": null, + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-07-14T02:14:13.083569Z", + "cost_min": 50000, + "direct_rep_costs_max": null, + "representative": "75f442e91d054c00a56c4488b9159c4f", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff2b9ed37dd64e0bba88065da1e2e0b8", + "customIncomes": [], + "total_budget": null, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 99999, + "created_at": "2016-07-14T02:14:13.087248Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2b9ed37dd64e0bba88065da1e2e0b8", + "public_financing_infranational": null, + "direct_rep_costs_min": null, + "public_financing_total": null, + "other_sources_total": null, + "other_financial_information": "Finazierung aus Mitgliederbeitr\u00e4gen", + "public_financing_national": null, + "no_clients": null, + "type": "FinancialDataTradeAssociation", + "start_date": "2015-01-01T00:00:00Z" + }, + { + "other_sources_donation": null, + "status": "active", + "turnover_min": null, + "eur_sources_procurement": 28378, + "end_date": "2015-12-01T00:00:00Z", + "eur_sources_procurement_src": "Daguerreobase Project", + "new_organisation": null, + "turnover_max": null, + "updated_at": "2016-04-23T01:13:50.286315Z", + "cost_min": null, + "direct_rep_costs_max": null, + "representative": "54a567a6dd454450a5c5e6d9077f1988", + "cost_absolute": null, + "eur_sources_grants_src": null, + "id": "ff2b598043f04061a50bc70240cd6354", + "customIncomes": [ + { + "status": "active", + "name": "Shopinkomsten", + "created_at": "2016-04-23T01:13:50.325922Z", + "updated_at": "2016-04-23T01:13:50.323842Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/5e8bdfbae8794dceb91fbc7fa6025d9a", + "amount": 133026, + "type": "other", + "id": "5e8bdfbae8794dceb91fbc7fa6025d9a" + }, + { + "status": "active", + "name": "Zaalverhuur en concessie", + "created_at": "2016-04-23T01:13:50.338422Z", + "updated_at": "2016-04-23T01:13:50.336526Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/ca0e76ad7a2644528a875233550fa301", + "amount": 37274, + "type": "other", + "id": "ca0e76ad7a2644528a875233550fa301" + }, + { + "status": "active", + "name": "Organisatie publieksactiviteiten", + "created_at": "2016-04-23T01:13:50.372977Z", + "updated_at": "2016-04-23T01:13:50.371056Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/acceed6d3ad0465ba2876c2c51161bbe", + "amount": 56076, + "type": "other", + "id": "acceed6d3ad0465ba2876c2c51161bbe" + }, + { + "status": "active", + "name": "Personeelsubsidies", + "created_at": "2016-04-23T01:13:50.485699Z", + "updated_at": "2016-04-23T01:13:50.483938Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/83f204483e2940ee8bf6815e13c0c5d1", + "amount": 3981, + "type": "other", + "id": "83f204483e2940ee8bf6815e13c0c5d1" + }, + { + "status": "active", + "name": "Varia opbrengsten", + "created_at": "2016-04-23T01:13:50.516579Z", + "updated_at": "2016-04-23T01:13:50.514618Z", + "uri": "http://api.lobbyfacts.eu/api/1/custom_income/bcddc8a783424f8dadc8628a6a27d7bb", + "amount": 67722, + "type": "other", + "id": "bcddc8a783424f8dadc8628a6a27d7bb" + } + ], + "total_budget": 3002447, + "turnover_absolute": null, + "eur_sources_grants": 0, + "other_sources_contributions": null, + "cost_max": 9999, + "created_at": "2016-04-23T01:13:50.290118Z", + "uri": "http://api.lobbyfacts.eu/api/1/financial_data/ff2b598043f04061a50bc70240cd6354", + "public_financing_infranational": 2260632, + "direct_rep_costs_min": null, + "public_financing_total": 2496215, + "other_sources_total": 506232, + "other_financial_information": null, + "public_financing_national": 207205, + "no_clients": null, + "type": "FinancialDataNGO", + "start_date": "2015-01-01T00:00:00Z" + } + ], + "next": "http://api.lobbyfacts.eu/api/1/financial_data?limit=50&offset=50", + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/misc/54d32.json b/test/inputs/json/misc/54d32.json index 22dfed2c0..545aaaa70 100644 --- a/test/inputs/json/misc/54d32.json +++ b/test/inputs/json/misc/54d32.json @@ -1 +1,410 @@ -{"count": 15499, "facets": {}, "results": [{"status": "inactive", "person_id": "92887cb8ec924bd98c1f9605f9723d7e", "created_at": "2015-04-24T01:57:40.146184", "representative_id": "e466f4977a294886b1aeedd3c21eafcd", "id": "ffff9201e61b4aeeb9270ce86f44c7d3", "updated_at": "2015-06-06T00:34:33.246147"}, {"status": "inactive", "person_id": "f6ce1642963d4ce5aecdaa7e470c6003", "created_at": "2015-05-07T21:25:53.095506", "representative_id": "58e4be0261c34a9eaf28559ddc94a599", "id": "fff59757f5d547f5b289622cb9cf2127", "updated_at": "2016-09-07T01:23:02.318998"}, {"status": "active", "person_id": "bdd8c25bfe044c6c8f8c2917458ceab5", "created_at": "2015-04-24T01:52:58.781612", "representative_id": "ece996ab939a4d2b926a93f5ade011e2", "id": "fff2afd23d7f41749193df662f3aa229", "updated_at": "2016-08-27T00:21:22.927847"}, {"status": "inactive", "person_id": "668cd2d9b8a948e9866055af830a77db", "created_at": "2015-04-24T01:49:40.789471", "representative_id": "6a3eb9d6407845d5804bee4a0f9a025a", "id": "fff29e51576b43d19fc9b2ce8924a0ec", "updated_at": "2015-08-04T22:36:58.049322"}, {"status": "active", "person_id": "d7b4c3fbf05a48fca6f2441ea57547ee", "created_at": "2016-04-23T01:05:52.295257", "representative_id": "bd926a6fca154450bd2b60a73872b9a1", "id": "ffdeaf683d75427086d472ffaea3e32b", "updated_at": "2016-04-23T01:05:52.274536"}, {"status": "inactive", "person_id": "7250314b415d4fa79510c21293de451d", "created_at": "2016-03-03T01:06:14.224390", "representative_id": "2ce3eb46ffb14f8f95bf2bb0666b73b8", "id": "ffdc72a920464f998b6fb1c798ed6a3e", "updated_at": "2016-08-05T00:20:12.744738"}, {"status": "inactive", "person_id": "a633626481a247b0afa2c59a08e004a0", "created_at": "2016-02-04T02:42:50.214936", "representative_id": "b2021c69fa63418ba904d5dc6da74ed1", "id": "ffdc3bdd26354d24b097499c8fe8f51b", "updated_at": "2016-09-18T20:00:07.962349"}, {"status": "inactive", "person_id": "20a3c28ef5ff466dab5654d913feb999", "created_at": "2015-05-07T21:15:41.759517", "representative_id": "e3f1aa49fd804c4ca02273558aa5553b", "id": "ffda0f30217f45fa892ce11d7b0cc683", "updated_at": "2015-08-04T23:30:54.475902"}, {"status": "inactive", "person_id": "5b8b08553d5d42dfb44f8207b4ff6447", "created_at": "2015-05-07T21:15:06.899231", "representative_id": "a44693edf34a4bdc95e8758e8e8f676e", "id": "ffd9663edf5e46c3bc3a2e9ab43acb24", "updated_at": "2015-05-19T23:46:55.316287"}, {"status": "active", "person_id": "172b024232ad42418bc0b801cf325678", "created_at": "2015-08-04T23:02:44.432514", "representative_id": "1db3d7632d83461f909315ea4c47c2f4", "id": "ffcf456306574488bcb5576228364419", "updated_at": "2016-06-05T00:39:41.608409"}, {"status": "inactive", "person_id": "d8da409b5ffc417e8c32fcf91e7c2487", "created_at": "2015-04-24T02:22:08.859843", "representative_id": "a3fa721f180c4c98af94abaaa4841f87", "id": "ffb91d2df99143adb320f9e92fc71d6b", "updated_at": "2015-08-04T23:11:15.951183"}, {"status": "active", "person_id": "992704bdfd5549dfb6f3aee09a915aba", "created_at": "2016-03-31T00:03:32.722750", "representative_id": "0953ee0069084fd8977032f8d0a769fe", "id": "ffb6372e995344858b01f065063572ae", "updated_at": "2016-03-31T00:03:32.706198"}, {"status": "inactive", "person_id": "00cf53ebdca242309028342928a7fe3a", "created_at": "2015-05-07T21:17:54.144160", "representative_id": "a6c703d41db0454a8e6842d7710be777", "id": "ffb138f2284246f89f8f3a4d01369453", "updated_at": "2016-02-13T02:09:14.190687"}, {"status": "inactive", "person_id": "3cfda55e1c01400faa170a5d2e137162", "created_at": "2015-04-24T02:06:41.033430", "representative_id": "3b461914a9d4442faafd03823131a2bc", "id": "ffacc6c2fb7d465da475e03bf545b2de", "updated_at": "2015-08-04T22:58:00.958720"}, {"status": "inactive", "person_id": "2dd4019418ef45d8a4d90325f7d039d8", "created_at": "2015-06-03T01:43:50.021074", "representative_id": "4d8194505ec34efea308c7d0a15237d3", "id": "ffa7844c8a504975b7dc4e472ef7b504", "updated_at": "2015-08-04T23:39:38.356939"}, {"status": "active", "person_id": "e94129fbf52a44b6b0b4a626a7581767", "created_at": "2015-09-30T00:48:37.682464", "representative_id": "c9161ae39e9c4f21ae0f2a9cf6171d5e", "id": "ffa41e130e124be2aaf37b2a6d515169", "updated_at": "2016-08-24T01:40:52.074743"}, {"status": "inactive", "person_id": "c9b027619c2a4b3482aaf04e81cce6bb", "created_at": "2015-05-07T21:16:45.204954", "representative_id": "c299640936ce4ef9abad49a9f113e6bd", "id": "ff980c453b7f46c7b0835864ed9d6464", "updated_at": "2015-08-04T23:31:23.565766"}, {"status": "active", "person_id": "bd1cd2120e49484a84c9dfdf3d8821d6", "created_at": "2015-10-23T23:36:44.109227", "representative_id": "eb42f038196e445db274d8868c5587e6", "id": "ff90c43b32754a729d37228644f804ac", "updated_at": "2016-03-27T23:59:17.123770"}, {"status": "inactive", "person_id": "bc372931e61e4c9db7622d5a750f5be5", "created_at": "2015-08-04T23:04:14.166763", "representative_id": "f3a3532d175a4c619d94b9c6c89cf2d8", "id": "ff9056998de54d878c997e608287c6e4", "updated_at": "2015-09-10T00:41:09.228783"}, {"status": "active", "person_id": "a486959583c644b7bba237d7500b876c", "created_at": "2016-04-07T00:11:19.512676", "representative_id": "3a8141ddc6514331a4791f928380ccd3", "id": "ff8ed55da0bc4882ae1ceaa14b09e0d1", "updated_at": "2016-04-07T00:11:19.505200"}, {"status": "inactive", "person_id": "37e10ed58aea470abbe61f359e1da73e", "created_at": "2015-08-04T23:36:53.012926", "representative_id": "364a8033a2cb485392a0e3be0f2570cf", "id": "ff850f1e1e234e4c8ac924a041ba0465", "updated_at": "2015-12-18T02:19:31.339634"}, {"status": "inactive", "person_id": "a9a84653dfb2463fa795e5b4505d8ac9", "created_at": "2015-05-07T18:23:48.938685", "representative_id": "8ad8a14a56094e8290e1f162bd7b7241", "id": "ff833f13613546b7a6717b1b5dbf98b9", "updated_at": "2015-08-04T23:03:19.058201"}, {"status": "active", "person_id": "6f4f47f424a44bfe941020d571ab893c", "created_at": "2015-08-04T22:51:19.970533", "representative_id": "8db2ae5f710c433b93edb066632734c2", "id": "ff80a192583146a8bb0b2db7c8bfd657", "updated_at": "2016-08-27T00:32:05.189953"}, {"status": "inactive", "person_id": "9287793c6bd74e708f8a0c2854fca399", "created_at": "2015-04-24T01:47:58.308618", "representative_id": "7a446a1b6c8e441395292dba83690a8b", "id": "ff7f4d7ecdd7496f968b479d22828241", "updated_at": "2015-08-04T22:34:09.108244"}, {"status": "inactive", "person_id": "9de7820c037743fba0b607e840e0f90d", "created_at": "2015-04-24T02:26:08.533369", "representative_id": "6ca65f0cfbdd489d8ef6dc9c25c52a04", "id": "ff7d624371894083a80f36e731062883", "updated_at": "2015-08-04T23:17:04.226802"}, {"status": "active", "person_id": "5d9b94ff3b7343649a3c192d3482977f", "created_at": "2015-08-04T22:53:27.483803", "representative_id": "8adeff0cac0e46ac9f82e863aa3212c4", "id": "ff7bab387ae64fe4bde1917201a2a642", "updated_at": "2016-09-07T00:37:25.636352"}, {"status": "active", "person_id": "b56029018ff6427e8f49d6864053187c", "created_at": "2015-08-04T23:01:19.794250", "representative_id": "18c8ed1798f842a28824293a8448a49a", "id": "ff7a3b896552418ba47b8f3b46945f28", "updated_at": "2016-03-28T00:25:02.864214"}, {"status": "inactive", "person_id": "2b845c8f547149559020fbda21e5f520", "created_at": "2015-04-24T02:31:52.179802", "representative_id": "962529ab26a74715adf1b10857964dc3", "id": "ff76ba1e944b417ea4df8040badd510b", "updated_at": "2015-08-04T23:25:26.787610"}, {"status": "inactive", "person_id": "0a6c3b9b501042d58b04be227e391c8f", "created_at": "2015-08-04T23:00:25.349985", "representative_id": "a38d7453bc2d40a1af18a983de949d20", "id": "ff76649dbcd14a458728f5fa5ef2cbfd", "updated_at": "2016-06-17T00:42:47.603804"}, {"status": "active", "person_id": "10da25ac784a44769b2d43c165b70096", "created_at": "2015-08-04T22:34:33.060161", "representative_id": "9ea9f5cdb07e420f87601244f15240d3", "id": "ff6f9bc84d694f98be0e20972fd976ae", "updated_at": "2016-07-01T00:11:37.386746"}, {"status": "active", "person_id": "9e5f2d0b73cd4d5097d1aa1d834624c7", "created_at": "2016-03-06T01:49:51.557186", "representative_id": "d34ce3b349604f54b1ac1cdfc94f31d9", "id": "ff6d771928aa45c5a7453f9321809b00", "updated_at": "2016-03-28T00:55:55.934625"}, {"status": "inactive", "person_id": "b14e9b5c26c845b5b691bee99c8ee61d", "created_at": "2015-08-04T23:29:39.944035", "representative_id": "2dad0e4813e247c09655c5f10da434dc", "id": "ff6471a35f4e4cbfbf1e9569f1ffebcd", "updated_at": "2015-10-04T00:24:15.475958"}, {"status": "inactive", "person_id": "c4b584540ef34ab2b380a096fdce8f15", "created_at": "2015-05-07T21:27:14.296076", "representative_id": "1a02eb0b409c40a682db0a5af823911e", "id": "ff5c8780b862421b9687fdff4f55350e", "updated_at": "2016-02-06T02:22:34.666734"}, {"status": "inactive", "person_id": "74103ffcfb544ef7a93d2ae948e70f9b", "created_at": "2015-08-04T22:42:23.105191", "representative_id": "388d31d917304c4f859b029541786e9d", "id": "ff5b6884d0a846caa4c11c7ffddb42f1", "updated_at": "2016-03-12T01:02:08.934469"}, {"status": "inactive", "person_id": "97e993956cb94687bc2849e83882c7d3", "created_at": "2015-04-24T02:04:02.997570", "representative_id": "4f4ed6bbd59147e4adf673b4028d04d0", "id": "ff5537175d934f8ca84550027db8ee4d", "updated_at": "2015-08-04T22:55:55.366183"}, {"status": "inactive", "person_id": "cb81918f83a24854b894d2ad6bcff4ef", "created_at": "2015-04-24T02:24:26.593122", "representative_id": "b752c5e7def04707bcb75a1a71616a01", "id": "ff4cc9a4884548ebb93d08cef7b81517", "updated_at": "2015-08-04T23:14:29.484124"}, {"status": "inactive", "person_id": "12215cbb9029433c91ce61e16e04e446", "created_at": "2015-04-24T01:47:34.416412", "representative_id": "c718c5411cf64c7faa2aa58482f6c49a", "id": "ff48539540224abe8cee2cdbd013ea07", "updated_at": "2015-08-04T22:33:22.032048"}, {"status": "active", "person_id": "59e87479365d4c66963b9d8a81db403e", "created_at": "2015-06-05T00:51:43.975489", "representative_id": "03dc171894554424a2223b8e5321ff66", "id": "ff424f8df0b744b5b6363f7c55c0bdeb", "updated_at": "2016-07-21T00:22:27.208260"}, {"status": "inactive", "person_id": "b41e607034094d35ac2633e3a95a038e", "created_at": "2015-08-04T23:01:25.650388", "representative_id": "a5848efd0a424693bd42916a25b5cf9f", "id": "ff3edb08036f461486898c9ff84b95b8", "updated_at": "2015-10-03T23:57:44.666952"}, {"status": "active", "person_id": "308aba8870b94303bf138b7f61906808", "created_at": "2016-07-21T00:12:58.019042", "representative_id": "369f73cbcd63403cbbee3043af38b12b", "id": "ff3802a4570045189f6d7337112d7b80", "updated_at": "2016-07-21T00:12:57.994159"}, {"status": "active", "person_id": "6d181c09bda24a5295b9a98a74e4a856", "created_at": "2016-09-18T19:44:03.839087", "representative_id": "32ff56235e8c4b7ba4dc747c275ecce7", "id": "ff337afcf6684f4fa01fa9bc5e76002e", "updated_at": "2016-09-18T19:44:03.835619"}, {"status": "inactive", "person_id": "bf53d7cd9fdb4476bd9169e216a262c8", "created_at": "2015-08-04T22:48:42.510885", "representative_id": "3a8141ddc6514331a4791f928380ccd3", "id": "ff26d7fe9ff74810ac0a59ee8e102aec", "updated_at": "2016-03-25T01:22:20.658520"}, {"status": "active", "person_id": "94b4adf1d4e04d04bc633c86d34ae0d1", "created_at": "2016-06-30T00:17:32.731789", "representative_id": "fa30ac2918dd4865964af6dd2d16ff6a", "id": "ff257562abe44fe7ace01548a725b0b2", "updated_at": "2016-06-30T00:17:32.718339"}, {"status": "inactive", "person_id": "bfd3e56304c54cff937e6aa182c6a262", "created_at": "2015-08-04T22:34:56.100215", "representative_id": "3c82e55d53e344f59ac5a553197bb4f7", "id": "ff20f7a6c3e54e39b4393fcddff01df5", "updated_at": "2016-04-23T00:01:03.328079"}, {"status": "active", "person_id": "5b97b14d2c1c44c9b553a8d95656ebc9", "created_at": "2016-09-18T18:47:01.411892", "representative_id": "615be2d7e3a843f3a220e9aff7dd2597", "id": "ff1f85cbb11d4c7f8b62fe6cbd931850", "updated_at": "2016-09-18T18:47:01.387259"}, {"status": "inactive", "person_id": "d818c561996948729befdf20b77d8b71", "created_at": "2015-04-24T02:10:57.180397", "representative_id": "90638985bf7d44a3a9a1aaed57c38b01", "id": "ff1d5aabe72246668fab4357caa32a6e", "updated_at": "2015-08-04T23:01:22.447779"}, {"status": "inactive", "person_id": "2ad02b5dab46443aaaf5da305114390b", "created_at": "2015-04-24T02:16:21.623091", "representative_id": "07b61c6a46fa46cf8bb03254c647fb3e", "id": "ff1bd14c8b414da3854f9feaf9bd7b59", "updated_at": "2015-08-04T23:05:47.961176"}, {"status": "active", "person_id": "d05f3dc752f44ae39c7082b5878d6362", "created_at": "2015-08-04T23:32:25.664220", "representative_id": "b1bb5cffee0e4de4b4e872ff0a91b018", "id": "ff15213c2ef74436a68807d9943b5987", "updated_at": "2016-03-28T00:58:55.097367"}, {"status": "inactive", "person_id": "6ea7fb8917fb4b628243479c99263419", "created_at": "2015-04-24T02:04:11.678438", "representative_id": "7ecadf032da7452c83a15ced57c07ac3", "id": "ff13f1287045404584063eca990c6280", "updated_at": "2015-08-04T22:56:02.488908"}, {"status": "inactive", "person_id": "ca6305a88f0a49f1afa03db19080fb4f", "created_at": "2015-08-04T23:40:30.802663", "representative_id": "3d13cb4f61e9450c9b4ea3717a9da256", "id": "ff12bbbf25994a1da3340400d47786ce", "updated_at": "2015-09-18T00:33:33.915808"}], "next": "http://api.lobbyfacts.eu/api/1/accreditation?limit=50&offset=50", "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 15499, + "facets": {}, + "results": [ + { + "status": "inactive", + "person_id": "92887cb8ec924bd98c1f9605f9723d7e", + "created_at": "2015-04-24T01:57:40.146184Z", + "representative_id": "e466f4977a294886b1aeedd3c21eafcd", + "id": "ffff9201e61b4aeeb9270ce86f44c7d3", + "updated_at": "2015-06-06T00:34:33.246147Z" + }, + { + "status": "inactive", + "person_id": "f6ce1642963d4ce5aecdaa7e470c6003", + "created_at": "2015-05-07T21:25:53.095506Z", + "representative_id": "58e4be0261c34a9eaf28559ddc94a599", + "id": "fff59757f5d547f5b289622cb9cf2127", + "updated_at": "2016-09-07T01:23:02.318998Z" + }, + { + "status": "active", + "person_id": "bdd8c25bfe044c6c8f8c2917458ceab5", + "created_at": "2015-04-24T01:52:58.781612Z", + "representative_id": "ece996ab939a4d2b926a93f5ade011e2", + "id": "fff2afd23d7f41749193df662f3aa229", + "updated_at": "2016-08-27T00:21:22.927847Z" + }, + { + "status": "inactive", + "person_id": "668cd2d9b8a948e9866055af830a77db", + "created_at": "2015-04-24T01:49:40.789471Z", + "representative_id": "6a3eb9d6407845d5804bee4a0f9a025a", + "id": "fff29e51576b43d19fc9b2ce8924a0ec", + "updated_at": "2015-08-04T22:36:58.049322Z" + }, + { + "status": "active", + "person_id": "d7b4c3fbf05a48fca6f2441ea57547ee", + "created_at": "2016-04-23T01:05:52.295257Z", + "representative_id": "bd926a6fca154450bd2b60a73872b9a1", + "id": "ffdeaf683d75427086d472ffaea3e32b", + "updated_at": "2016-04-23T01:05:52.274536Z" + }, + { + "status": "inactive", + "person_id": "7250314b415d4fa79510c21293de451d", + "created_at": "2016-03-03T01:06:14.224390Z", + "representative_id": "2ce3eb46ffb14f8f95bf2bb0666b73b8", + "id": "ffdc72a920464f998b6fb1c798ed6a3e", + "updated_at": "2016-08-05T00:20:12.744738Z" + }, + { + "status": "inactive", + "person_id": "a633626481a247b0afa2c59a08e004a0", + "created_at": "2016-02-04T02:42:50.214936Z", + "representative_id": "b2021c69fa63418ba904d5dc6da74ed1", + "id": "ffdc3bdd26354d24b097499c8fe8f51b", + "updated_at": "2016-09-18T20:00:07.962349Z" + }, + { + "status": "inactive", + "person_id": "20a3c28ef5ff466dab5654d913feb999", + "created_at": "2015-05-07T21:15:41.759517Z", + "representative_id": "e3f1aa49fd804c4ca02273558aa5553b", + "id": "ffda0f30217f45fa892ce11d7b0cc683", + "updated_at": "2015-08-04T23:30:54.475902Z" + }, + { + "status": "inactive", + "person_id": "5b8b08553d5d42dfb44f8207b4ff6447", + "created_at": "2015-05-07T21:15:06.899231Z", + "representative_id": "a44693edf34a4bdc95e8758e8e8f676e", + "id": "ffd9663edf5e46c3bc3a2e9ab43acb24", + "updated_at": "2015-05-19T23:46:55.316287Z" + }, + { + "status": "active", + "person_id": "172b024232ad42418bc0b801cf325678", + "created_at": "2015-08-04T23:02:44.432514Z", + "representative_id": "1db3d7632d83461f909315ea4c47c2f4", + "id": "ffcf456306574488bcb5576228364419", + "updated_at": "2016-06-05T00:39:41.608409Z" + }, + { + "status": "inactive", + "person_id": "d8da409b5ffc417e8c32fcf91e7c2487", + "created_at": "2015-04-24T02:22:08.859843Z", + "representative_id": "a3fa721f180c4c98af94abaaa4841f87", + "id": "ffb91d2df99143adb320f9e92fc71d6b", + "updated_at": "2015-08-04T23:11:15.951183Z" + }, + { + "status": "active", + "person_id": "992704bdfd5549dfb6f3aee09a915aba", + "created_at": "2016-03-31T00:03:32.722750Z", + "representative_id": "0953ee0069084fd8977032f8d0a769fe", + "id": "ffb6372e995344858b01f065063572ae", + "updated_at": "2016-03-31T00:03:32.706198Z" + }, + { + "status": "inactive", + "person_id": "00cf53ebdca242309028342928a7fe3a", + "created_at": "2015-05-07T21:17:54.144160Z", + "representative_id": "a6c703d41db0454a8e6842d7710be777", + "id": "ffb138f2284246f89f8f3a4d01369453", + "updated_at": "2016-02-13T02:09:14.190687Z" + }, + { + "status": "inactive", + "person_id": "3cfda55e1c01400faa170a5d2e137162", + "created_at": "2015-04-24T02:06:41.033430Z", + "representative_id": "3b461914a9d4442faafd03823131a2bc", + "id": "ffacc6c2fb7d465da475e03bf545b2de", + "updated_at": "2015-08-04T22:58:00.958720Z" + }, + { + "status": "inactive", + "person_id": "2dd4019418ef45d8a4d90325f7d039d8", + "created_at": "2015-06-03T01:43:50.021074Z", + "representative_id": "4d8194505ec34efea308c7d0a15237d3", + "id": "ffa7844c8a504975b7dc4e472ef7b504", + "updated_at": "2015-08-04T23:39:38.356939Z" + }, + { + "status": "active", + "person_id": "e94129fbf52a44b6b0b4a626a7581767", + "created_at": "2015-09-30T00:48:37.682464Z", + "representative_id": "c9161ae39e9c4f21ae0f2a9cf6171d5e", + "id": "ffa41e130e124be2aaf37b2a6d515169", + "updated_at": "2016-08-24T01:40:52.074743Z" + }, + { + "status": "inactive", + "person_id": "c9b027619c2a4b3482aaf04e81cce6bb", + "created_at": "2015-05-07T21:16:45.204954Z", + "representative_id": "c299640936ce4ef9abad49a9f113e6bd", + "id": "ff980c453b7f46c7b0835864ed9d6464", + "updated_at": "2015-08-04T23:31:23.565766Z" + }, + { + "status": "active", + "person_id": "bd1cd2120e49484a84c9dfdf3d8821d6", + "created_at": "2015-10-23T23:36:44.109227Z", + "representative_id": "eb42f038196e445db274d8868c5587e6", + "id": "ff90c43b32754a729d37228644f804ac", + "updated_at": "2016-03-27T23:59:17.123770Z" + }, + { + "status": "inactive", + "person_id": "bc372931e61e4c9db7622d5a750f5be5", + "created_at": "2015-08-04T23:04:14.166763Z", + "representative_id": "f3a3532d175a4c619d94b9c6c89cf2d8", + "id": "ff9056998de54d878c997e608287c6e4", + "updated_at": "2015-09-10T00:41:09.228783Z" + }, + { + "status": "active", + "person_id": "a486959583c644b7bba237d7500b876c", + "created_at": "2016-04-07T00:11:19.512676Z", + "representative_id": "3a8141ddc6514331a4791f928380ccd3", + "id": "ff8ed55da0bc4882ae1ceaa14b09e0d1", + "updated_at": "2016-04-07T00:11:19.505200Z" + }, + { + "status": "inactive", + "person_id": "37e10ed58aea470abbe61f359e1da73e", + "created_at": "2015-08-04T23:36:53.012926Z", + "representative_id": "364a8033a2cb485392a0e3be0f2570cf", + "id": "ff850f1e1e234e4c8ac924a041ba0465", + "updated_at": "2015-12-18T02:19:31.339634Z" + }, + { + "status": "inactive", + "person_id": "a9a84653dfb2463fa795e5b4505d8ac9", + "created_at": "2015-05-07T18:23:48.938685Z", + "representative_id": "8ad8a14a56094e8290e1f162bd7b7241", + "id": "ff833f13613546b7a6717b1b5dbf98b9", + "updated_at": "2015-08-04T23:03:19.058201Z" + }, + { + "status": "active", + "person_id": "6f4f47f424a44bfe941020d571ab893c", + "created_at": "2015-08-04T22:51:19.970533Z", + "representative_id": "8db2ae5f710c433b93edb066632734c2", + "id": "ff80a192583146a8bb0b2db7c8bfd657", + "updated_at": "2016-08-27T00:32:05.189953Z" + }, + { + "status": "inactive", + "person_id": "9287793c6bd74e708f8a0c2854fca399", + "created_at": "2015-04-24T01:47:58.308618Z", + "representative_id": "7a446a1b6c8e441395292dba83690a8b", + "id": "ff7f4d7ecdd7496f968b479d22828241", + "updated_at": "2015-08-04T22:34:09.108244Z" + }, + { + "status": "inactive", + "person_id": "9de7820c037743fba0b607e840e0f90d", + "created_at": "2015-04-24T02:26:08.533369Z", + "representative_id": "6ca65f0cfbdd489d8ef6dc9c25c52a04", + "id": "ff7d624371894083a80f36e731062883", + "updated_at": "2015-08-04T23:17:04.226802Z" + }, + { + "status": "active", + "person_id": "5d9b94ff3b7343649a3c192d3482977f", + "created_at": "2015-08-04T22:53:27.483803Z", + "representative_id": "8adeff0cac0e46ac9f82e863aa3212c4", + "id": "ff7bab387ae64fe4bde1917201a2a642", + "updated_at": "2016-09-07T00:37:25.636352Z" + }, + { + "status": "active", + "person_id": "b56029018ff6427e8f49d6864053187c", + "created_at": "2015-08-04T23:01:19.794250Z", + "representative_id": "18c8ed1798f842a28824293a8448a49a", + "id": "ff7a3b896552418ba47b8f3b46945f28", + "updated_at": "2016-03-28T00:25:02.864214Z" + }, + { + "status": "inactive", + "person_id": "2b845c8f547149559020fbda21e5f520", + "created_at": "2015-04-24T02:31:52.179802Z", + "representative_id": "962529ab26a74715adf1b10857964dc3", + "id": "ff76ba1e944b417ea4df8040badd510b", + "updated_at": "2015-08-04T23:25:26.787610Z" + }, + { + "status": "inactive", + "person_id": "0a6c3b9b501042d58b04be227e391c8f", + "created_at": "2015-08-04T23:00:25.349985Z", + "representative_id": "a38d7453bc2d40a1af18a983de949d20", + "id": "ff76649dbcd14a458728f5fa5ef2cbfd", + "updated_at": "2016-06-17T00:42:47.603804Z" + }, + { + "status": "active", + "person_id": "10da25ac784a44769b2d43c165b70096", + "created_at": "2015-08-04T22:34:33.060161Z", + "representative_id": "9ea9f5cdb07e420f87601244f15240d3", + "id": "ff6f9bc84d694f98be0e20972fd976ae", + "updated_at": "2016-07-01T00:11:37.386746Z" + }, + { + "status": "active", + "person_id": "9e5f2d0b73cd4d5097d1aa1d834624c7", + "created_at": "2016-03-06T01:49:51.557186Z", + "representative_id": "d34ce3b349604f54b1ac1cdfc94f31d9", + "id": "ff6d771928aa45c5a7453f9321809b00", + "updated_at": "2016-03-28T00:55:55.934625Z" + }, + { + "status": "inactive", + "person_id": "b14e9b5c26c845b5b691bee99c8ee61d", + "created_at": "2015-08-04T23:29:39.944035Z", + "representative_id": "2dad0e4813e247c09655c5f10da434dc", + "id": "ff6471a35f4e4cbfbf1e9569f1ffebcd", + "updated_at": "2015-10-04T00:24:15.475958Z" + }, + { + "status": "inactive", + "person_id": "c4b584540ef34ab2b380a096fdce8f15", + "created_at": "2015-05-07T21:27:14.296076Z", + "representative_id": "1a02eb0b409c40a682db0a5af823911e", + "id": "ff5c8780b862421b9687fdff4f55350e", + "updated_at": "2016-02-06T02:22:34.666734Z" + }, + { + "status": "inactive", + "person_id": "74103ffcfb544ef7a93d2ae948e70f9b", + "created_at": "2015-08-04T22:42:23.105191Z", + "representative_id": "388d31d917304c4f859b029541786e9d", + "id": "ff5b6884d0a846caa4c11c7ffddb42f1", + "updated_at": "2016-03-12T01:02:08.934469Z" + }, + { + "status": "inactive", + "person_id": "97e993956cb94687bc2849e83882c7d3", + "created_at": "2015-04-24T02:04:02.997570Z", + "representative_id": "4f4ed6bbd59147e4adf673b4028d04d0", + "id": "ff5537175d934f8ca84550027db8ee4d", + "updated_at": "2015-08-04T22:55:55.366183Z" + }, + { + "status": "inactive", + "person_id": "cb81918f83a24854b894d2ad6bcff4ef", + "created_at": "2015-04-24T02:24:26.593122Z", + "representative_id": "b752c5e7def04707bcb75a1a71616a01", + "id": "ff4cc9a4884548ebb93d08cef7b81517", + "updated_at": "2015-08-04T23:14:29.484124Z" + }, + { + "status": "inactive", + "person_id": "12215cbb9029433c91ce61e16e04e446", + "created_at": "2015-04-24T01:47:34.416412Z", + "representative_id": "c718c5411cf64c7faa2aa58482f6c49a", + "id": "ff48539540224abe8cee2cdbd013ea07", + "updated_at": "2015-08-04T22:33:22.032048Z" + }, + { + "status": "active", + "person_id": "59e87479365d4c66963b9d8a81db403e", + "created_at": "2015-06-05T00:51:43.975489Z", + "representative_id": "03dc171894554424a2223b8e5321ff66", + "id": "ff424f8df0b744b5b6363f7c55c0bdeb", + "updated_at": "2016-07-21T00:22:27.208260Z" + }, + { + "status": "inactive", + "person_id": "b41e607034094d35ac2633e3a95a038e", + "created_at": "2015-08-04T23:01:25.650388Z", + "representative_id": "a5848efd0a424693bd42916a25b5cf9f", + "id": "ff3edb08036f461486898c9ff84b95b8", + "updated_at": "2015-10-03T23:57:44.666952Z" + }, + { + "status": "active", + "person_id": "308aba8870b94303bf138b7f61906808", + "created_at": "2016-07-21T00:12:58.019042Z", + "representative_id": "369f73cbcd63403cbbee3043af38b12b", + "id": "ff3802a4570045189f6d7337112d7b80", + "updated_at": "2016-07-21T00:12:57.994159Z" + }, + { + "status": "active", + "person_id": "6d181c09bda24a5295b9a98a74e4a856", + "created_at": "2016-09-18T19:44:03.839087Z", + "representative_id": "32ff56235e8c4b7ba4dc747c275ecce7", + "id": "ff337afcf6684f4fa01fa9bc5e76002e", + "updated_at": "2016-09-18T19:44:03.835619Z" + }, + { + "status": "inactive", + "person_id": "bf53d7cd9fdb4476bd9169e216a262c8", + "created_at": "2015-08-04T22:48:42.510885Z", + "representative_id": "3a8141ddc6514331a4791f928380ccd3", + "id": "ff26d7fe9ff74810ac0a59ee8e102aec", + "updated_at": "2016-03-25T01:22:20.658520Z" + }, + { + "status": "active", + "person_id": "94b4adf1d4e04d04bc633c86d34ae0d1", + "created_at": "2016-06-30T00:17:32.731789Z", + "representative_id": "fa30ac2918dd4865964af6dd2d16ff6a", + "id": "ff257562abe44fe7ace01548a725b0b2", + "updated_at": "2016-06-30T00:17:32.718339Z" + }, + { + "status": "inactive", + "person_id": "bfd3e56304c54cff937e6aa182c6a262", + "created_at": "2015-08-04T22:34:56.100215Z", + "representative_id": "3c82e55d53e344f59ac5a553197bb4f7", + "id": "ff20f7a6c3e54e39b4393fcddff01df5", + "updated_at": "2016-04-23T00:01:03.328079Z" + }, + { + "status": "active", + "person_id": "5b97b14d2c1c44c9b553a8d95656ebc9", + "created_at": "2016-09-18T18:47:01.411892Z", + "representative_id": "615be2d7e3a843f3a220e9aff7dd2597", + "id": "ff1f85cbb11d4c7f8b62fe6cbd931850", + "updated_at": "2016-09-18T18:47:01.387259Z" + }, + { + "status": "inactive", + "person_id": "d818c561996948729befdf20b77d8b71", + "created_at": "2015-04-24T02:10:57.180397Z", + "representative_id": "90638985bf7d44a3a9a1aaed57c38b01", + "id": "ff1d5aabe72246668fab4357caa32a6e", + "updated_at": "2015-08-04T23:01:22.447779Z" + }, + { + "status": "inactive", + "person_id": "2ad02b5dab46443aaaf5da305114390b", + "created_at": "2015-04-24T02:16:21.623091Z", + "representative_id": "07b61c6a46fa46cf8bb03254c647fb3e", + "id": "ff1bd14c8b414da3854f9feaf9bd7b59", + "updated_at": "2015-08-04T23:05:47.961176Z" + }, + { + "status": "active", + "person_id": "d05f3dc752f44ae39c7082b5878d6362", + "created_at": "2015-08-04T23:32:25.664220Z", + "representative_id": "b1bb5cffee0e4de4b4e872ff0a91b018", + "id": "ff15213c2ef74436a68807d9943b5987", + "updated_at": "2016-03-28T00:58:55.097367Z" + }, + { + "status": "inactive", + "person_id": "6ea7fb8917fb4b628243479c99263419", + "created_at": "2015-04-24T02:04:11.678438Z", + "representative_id": "7ecadf032da7452c83a15ced57c07ac3", + "id": "ff13f1287045404584063eca990c6280", + "updated_at": "2015-08-04T22:56:02.488908Z" + }, + { + "status": "inactive", + "person_id": "ca6305a88f0a49f1afa03db19080fb4f", + "created_at": "2015-08-04T23:40:30.802663Z", + "representative_id": "3d13cb4f61e9450c9b4ea3717a9da256", + "id": "ff12bbbf25994a1da3340400d47786ce", + "updated_at": "2015-09-18T00:33:33.915808Z" + } + ], + "next": "http://api.lobbyfacts.eu/api/1/accreditation?limit=50&offset=50", + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/misc/5eae5.json b/test/inputs/json/misc/5eae5.json index a51e53b05..c665de9b9 100644 --- a/test/inputs/json/misc/5eae5.json +++ b/test/inputs/json/misc/5eae5.json @@ -1 +1,1324 @@ -[{"ID":1,"Date":"2015-09-01T00:00:00","Title":"European North Sea Energy Alliance","Sponsor":"Christina McKelvie MSP"},{"ID":2,"Date":"2015-09-01T00:00:00","Title":"AS it is","Sponsor":"Margaret McCulloch MSP"},{"ID":3,"Date":"2015-09-01T00:00:00","Title":"Building Capacity, Investing in Stroke Research","Sponsor":"Dennis Robertson MSP"},{"ID":4,"Date":"2015-09-02T00:00:00","Title":"Celebrating Scotland's Small and Rural Towns","Sponsor":"Margaret McCulloch MSP"},{"ID":5,"Date":"2015-09-02T00:00:00","Title":"50 years of supporting carers","Sponsor":"Graeme Dey MSP"},{"ID":6,"Date":"2015-09-02T00:00:00","Title":"Sole Searching - A Hootenanny","Sponsor":"Alex Rowley MSP"},{"ID":7,"Date":"2015-09-02T00:00:00","Title":"Exploring European Approaches to Development","Sponsor":"Sarah Boyack MSP"},{"ID":8,"Date":"2015-09-03T00:00:00","Title":"Saltire Fletcher Lecture 2015","Sponsor":"Linda Fabiani MSP"},{"ID":9,"Date":"2015-09-07T00:00:00","Title":"Your Say","Sponsor":"Welfare Reform Committee"},{"ID":10,"Date":"2015-09-08T00:00:00","Title":"Celebrating Scotland's Walking Champions","Sponsor":"Patricia Ferguson MSP"},{"ID":11,"Date":"2015-09-08T00:00:00","Title":"Columba 1400 Impact Study","Sponsor":"Dave Thompson MSP"},{"ID":12,"Date":"2015-09-08T00:00:00","Title":"Women in Business ","Sponsor":"Margaret McCulloch MSP"},{"ID":13,"Date":"2015-09-09T00:00:00","Title":"Scottish Older People's Assembly","Sponsor":"Christine Grahame MSP"},{"ID":14,"Date":"2015-09-09T00:00:00","Title":"How we can prevent homelessness and reduce re-offending?","Sponsor":"Mary Fee MSP"},{"ID":15,"Date":"2015-09-09T00:00:00","Title":"Street Law: bringing practical law to classrooms","Sponsor":"Paul Martin MSP"},{"ID":16,"Date":"2015-09-09T00:00:00","Title":"FAST Forward ","Sponsor":"Stewart Maxwell MSP"},{"ID":17,"Date":"2015-09-09T00:00:00","Title":"Preventing Accidents, Scotland's National Outcomes","Sponsor":"Clare Adamson MSP"},{"ID":18,"Date":"2015-09-10T00:00:00","Title":"Nature of Scotland Awards 2015 Shortlist ","Sponsor":"Claudia Beamish MSP"},{"ID":19,"Date":"2015-09-15T00:00:00","Title":"Children Get Arthritis Too","Sponsor":"Margaret McCulloch MSP"},{"ID":20,"Date":"2015-09-15T00:00:00","Title":"Transport Focus Stakeholders ","Sponsor":"Patrick Harvie MSP"},{"ID":21,"Date":"2015-09-15T00:00:00","Title":"Growing Your Small Business","Sponsor":"Hugh Henry MSP"},{"ID":22,"Date":"2015-09-16T00:00:00","Title":"SCIAF 50th Anniversary ","Sponsor":"Presiding Officer "},{"ID":23,"Date":"2015-09-16T00:00:00","Title":"Luxembourg Presidency of the EU ","Sponsor":"Christina McKelvie MSP"},{"ID":24,"Date":"2015-09-16T00:00:00","Title":"Camphill Scotland - Worldwide Weave","Sponsor":"Alison McInnes MSP"},{"ID":25,"Date":"2015-09-16T00:00:00","Title":"Association of Chief Officers of Scottish Voluntary Organisations","Sponsor":"Alex Neil MSP"},{"ID":26,"Date":"2015-09-16T00:00:00","Title":"IPSA Conference 2015: Roundtable and Reception","Sponsor":"Bruce Crawford MSP"},{"ID":27,"Date":"2015-09-17T00:00:00","Title":"Wear it Pink photocall","Sponsor":"Christina McKelvie MSP"},{"ID":28,"Date":"2015-09-17T00:00:00","Title":"Holyrood Apple Day 2015","Sponsor":"John Wilson MSP"},{"ID":29,"Date":"2015-09-17T00:00:00","Title":"Youth Volunteering - The Lived Experience","Sponsor":"Fiona McLeod MSP"},{"ID":30,"Date":"2015-09-17T00:00:00","Title":"See Me: In Health","Sponsor":"Jenny Marra MSP"},{"ID":31,"Date":"2015-09-18T00:00:00","Title":"Future Directions for Well-Being Policy","Sponsor":"Scotland's Future Forum"},{"ID":32,"Date":"2015-09-21T00:00:00","Title":"Breast Cancer Care Scotland - B-Aware Mobile Roadshow","Sponsor":"Bob Doris MSP"},{"ID":33,"Date":"2015-09-22T00:00:00","Title":"Scottish Craft Distillers Association ","Sponsor":"Jean Urquhart MSP "},{"ID":34,"Date":"2015-09-22T00:00:00","Title":"Connect2Renewables","Sponsor":"Christina McKelvie MSP"},{"ID":35,"Date":"2015-09-22T00:00:00","Title":"25 Years of Parkhead CAB","Sponsor":"John Mason MSP"},{"ID":36,"Date":"2015-09-23T00:00:00","Title":"250th Anniversary of Thomas Muir, Father of Scottish Democracy","Sponsor":"Fiona McLeod MSP"},{"ID":37,"Date":"2016-09-23T00:00:00","Title":"Scottish Sport Alliance Manifesto for Scottish Sport","Sponsor":"Alison Johnstone MSP and Liz Smith MSP"},{"ID":38,"Date":"2019-09-23T00:00:00","Title":"SCOTLAND: Towards a Global Nuclear Weapons Ban","Sponsor":"Bill Kidd MSP"},{"ID":39,"Date":"2015-09-24T00:00:00","Title":"Our Environment Competition: Meet the Winners","Sponsor":"Alex Fergusson MSP"},{"ID":40,"Date":"2015-09-24T00:00:00","Title":"National Review of Primary Care Out of Hours Services","Sponsor":"Duncan McNeill MSP"},{"ID":41,"Date":"2015-09-24T00:00:00","Title":"1+2: Language Learning for All","Sponsor":"Michael Russell MSP"},{"ID":42,"Date":"2015-09-29T00:00:00","Title":"Working to End Breast Cancer Now","Sponsor":"Jenny Marra MSP"},{"ID":43,"Date":"2015-09-29T00:00:00","Title":"Colleges Scotland ","Sponsor":"Iain Gray MSP"},{"ID":44,"Date":"2015-09-29T00:00:00","Title":"Safeguarding Diabetes Service ","Sponsor":"Nanette Milne MSP"},{"ID":45,"Date":"2015-09-30T00:00:00","Title":"STV Breakfast Briefing","Sponsor":"Linda Fabiani MSP"},{"ID":46,"Date":"2015-09-30T00:00:00","Title":"Self Management Awards 2015","Sponsor":"Jackie Baillie MSP"},{"ID":47,"Date":"2015-09-30T00:00:00","Title":"Livestock Keepers","Sponsor":"John Scott MSP"},{"ID":48,"Date":"2015-09-30T00:00:00","Title":"High Quality Haemophilia Care in Scotland","Sponsor":"Richard Lyle MSP"},{"ID":49,"Date":"2015-09-30T00:00:00","Title":"Special Olympics World Games 2015","Sponsor":"Presiding Officer and Minister for Sport, Health Improvement and Mental Health"},{"ID":50,"Date":"2015-10-01T00:00:00","Title":"Breaking the Mould Celebrating Women's Role Over the Past 100 Years","Sponsor":"Joan McAlpine MSP"},{"ID":51,"Date":"2015-10-01T00:00:00","Title":"Play/Talk/Read","Sponsor":"Fiona McLeod MSP"},{"ID":52,"Date":"2015-10-01T00:00:00","Title":"Manufacturing our Future: Driving Value for Scotland","Sponsor":"Gordon MacDonald MSP"},{"ID":53,"Date":"2015-10-05T00:00:00","Title":"Scottish Older People's Assembly","Sponsor":"Christian Allard MSP"},{"ID":54,"Date":"2015-10-06T00:00:00","Title":"Federation of City Farms and Community Gardens (FCFCG) 10th Anniversary in Scotland","Sponsor":"Anne McTaggart MSP"},{"ID":55,"Date":"2015-10-06T00:00:00","Title":"SSAFA: The Armed Forces Charity","Sponsor":"Margaret Mitchell MSP"},{"ID":56,"Date":"2015-10-06T00:00:00","Title":"From dots to digital: National Braille Week 2015","Sponsor":"Dennis Robertson MSP"},{"ID":57,"Date":"2015-10-06T00:00:00","Title":"Roundtable: Women & Justice","Sponsor":"Jean Urquhart MSP"},{"ID":58,"Date":"2015-10-07T00:00:00","Title":"Unveiling and presentation of the Army painting Service ","Sponsor":"Presiding Officer"},{"ID":59,"Date":"2015-10-07T00:00:00","Title":"UK Music Event","Sponsor":"Anne McTaggart MSP"},{"ID":60,"Date":"2015-10-07T00:00:00","Title":"UN 70 Years of Service to Humanity","Sponsor":"Christina McKelvie MSP"},{"ID":61,"Date":"2015-10-07T00:00:00","Title":"Alcoholics Anonymous Awareness","Sponsor":"Rhoda Grant MSP"},{"ID":62,"Date":"2015-10-07T00:00:00","Title":"Human Rights and The Peace Process in Colombia","Sponsor":"Sarah Boyack MSP"},{"ID":63,"Date":"2015-10-08T00:00:00","Title":"Glasgow Gurdwara - Kultar's Mime","Sponsor":"Sandra White MSP"},{"ID":64,"Date":"2015-10-08T00:00:00","Title":"International Credit Union Day 2015","Sponsor":"John Wilson MSP"},{"ID":65,"Date":"2015-10-26T00:00:00","Title":"Scottish Futures Forum/Knowledge Exchange - Parliament/Universities","Sponsor":"Scottish Futures Forum"},{"ID":66,"Date":"2015-10-27T00:00:00","Title":"Scottish Tree of the Year Prize giving Reception","Sponsor":"Jim Hume MSP"},{"ID":67,"Date":"2015-10-27T00:00:00","Title":"Citizens Advice Scotland","Sponsor":"Dave Thompson MSP"},{"ID":68,"Date":"2015-10-27T00:00:00","Title":"Aberdeen City Region Deal","Sponsor":"Mark McDonald MSP"},{"ID":69,"Date":"2015-10-28T00:00:00","Title":"Scottish Parliament Launch of the 2015 Scottish Poppy Appeal","Sponsor":"The Presiding Officer"},{"ID":70,"Date":"2015-10-28T00:00:00","Title":"Scottish Sports Futures Reception","Sponsor":"Colin Keir MSP"},{"ID":71,"Date":"2015-10-28T00:00:00","Title":"Recognising the Contribution of William Hill","Sponsor":"John Scott MSP"},{"ID":72,"Date":"2015-10-28T00:00:00","Title":"Creating a 21st Century Learning Environment","Sponsor":"George Adam MSP"},{"ID":73,"Date":"2015-10-28T00:00:00","Title":"Care and Repair Edinburgh 30th Birthday Party","Sponsor":"Gordon MacDonald MSP"},{"ID":74,"Date":"2015-10-29T00:00:00","Title":"Ownership and Management Options for Scotland's Community Land Assets","Sponsor":"Chic Brodie MSP"},{"ID":75,"Date":"2015-10-29T00:00:00","Title":"Business in the Parliament 2015 Reception and Dinner","Sponsor":"Presiding Officer"},{"ID":76,"Date":"2015-10-30T00:00:00","Title":"Business in the Parliament 2015 ","Sponsor":"Presiding Officer"},{"ID":77,"Date":"2015-10-31T00:00:00","Title":"Holyrood Rocks Final 2015","Sponsor":"SPCB"},{"ID":78,"Date":"2015-11-03T00:00:00","Title":"Celebrating Social Enterprise","Sponsor":"Tavish Scott MSP"},{"ID":79,"Date":"2015-11-03T00:00:00","Title":"Holocaust Educational Trust","Sponsor":"Ken McIntosh MSP"},{"ID":80,"Date":"2015-11-03T00:00:00","Title":"10 Years of ScottishPower Energy People Trust","Sponsor":"James Dornan MSP"},{"ID":81,"Date":"2015-11-03T00:00:00","Title":"New lamp post mounted wind turbine technology","Sponsor":"Richard Lyle MSP"},{"ID":82,"Date":"2015-11-04T00:00:00","Title":"BHF Scotland: Fighting for Every Heart Beat","Sponsor":"Dennis Robertson MSP"},{"ID":83,"Date":"2015-11-04T00:00:00","Title":"Edinburgh Tenants Federation","Sponsor":"Sarah Boyack MSP"},{"ID":84,"Date":"2015-11-04T00:00:00","Title":"Psoriatic Arthritis Awareness in Scotland","Sponsor":"Dave Thompson MSP"},{"ID":85,"Date":"2015-11-04T00:00:00","Title":"Knitting a Nation: Social Fabric ","Sponsor":"Roderick Campbell MSP"},{"ID":86,"Date":"2015-11-04T00:00:00","Title":"Blacklisted","Sponsor":"Neil Findlay MSP"},{"ID":87,"Date":"2015-11-06T00:00:00","Title":"Community Resources Network Scotland (CRNS) Conference 2015 - Choose to Reuse","Sponsor":"Patrick Harvie MSP"},{"ID":88,"Date":"2015-11-10T00:00:00","Title":"Lung Ha Theatre Company 30th Anniversary","Sponsor":"Joan McAlpine MSP"},{"ID":89,"Date":"2015-11-10T00:00:00","Title":"Making it Happen: Encouraging Enterprise & Entrepreneurship","Sponsor":"Liz Smith MSP"},{"ID":90,"Date":"2015-11-10T00:00:00","Title":"Celebrating World Diabetes Day","Sponsor":"Nanette Milne MSP"},{"ID":91,"Date":"2015-11-10T00:00:00","Title":"Prostitution Law Reform Bill","Sponsor":"Jean Urquhart MSP"},{"ID":92,"Date":"2015-11-10T00:00:00","Title":"Supporting Families Affected by Someone's Drinking","Sponsor":"Christian Allard MSP"},{"ID":93,"Date":"2015-11-11T00:00:00","Title":"Remembrance Day Commemorations","Sponsor":"SPCB"},{"ID":94,"Date":"2015-11-11T00:00:00","Title":"RAMH 25th Anniversary of Service Provision","Sponsor":"George Adam MSP"},{"ID":95,"Date":"2015-11-12T00:00:00","Title":"Get Ready for Winter","Sponsor":"Stuart McMillan MSP"},{"ID":96,"Date":"2015-11-12T00:00:00","Title":"Scotland's Outdoors - Our natural health service","Sponsor":"Malcolm Chisholm MSP"},{"ID":97,"Date":"2015-11-12T00:00:00","Title":"Anxiety & Depression in Families Affected by Substance Abuse","Sponsor":"John Mason MSP"},{"ID":98,"Date":"2015-11-16T00:00:00","Title":"SFF - Participative Budgeting","Sponsor":"Scottish Futures Forum"},{"ID":99,"Date":"2015-11-17T00:00:00","Title":"SCVO Annual Parliamentary Reception","Sponsor":"James Dornan MSP"},{"ID":100,"Date":"2015-11-17T00:00:00","Title":"Pancreatic Cancer UK","Sponsor":"Clare Adamson MSP"},{"ID":101,"Date":"2015-11-17T00:00:00","Title":"Scotland United in prayer for Parliament","Sponsor":"Nigel Don MSP"},{"ID":102,"Date":"2015-11-17T00:00:00","Title":"Women in Property - Annual Review of the Scottish Planning System","Sponsor":"Jayne Baxter MSP"},{"ID":103,"Date":"2015-11-17T00:00:00","Title":"The Refugee Crisis: framing the Scottish Response","Sponsor":"John Mason MSP"},{"ID":104,"Date":"2015-11-18T00:00:00","Title":"Celebrate. Remember, Continue Celebrating 60 Years of Action for Children","Sponsor":"Anne McTaggart MSP"},{"ID":105,"Date":"2015-11-18T00:00:00","Title":"Scottish Parliamentary Maritime Reception","Sponsor":"Liam McArthur MSP"},{"ID":106,"Date":"2015-11-18T00:00:00","Title":"My Lungs My Life","Sponsor":"Nanette Milne MSP"},{"ID":107,"Date":"2015-11-19T00:00:00","Title":"Experiences of Psychosis Film Showing","Sponsor":"Malcolm Chisholm MSP"},{"ID":108,"Date":"2015-11-19T00:00:00","Title":"Road to Recovery?","Sponsor":"Cara Hilton MSP"},{"ID":109,"Date":"2015-11-19T00:00:00","Title":"Carers Rights Day","Sponsor":"Rhoda Grant MSP"},{"ID":110,"Date":"2015-11-19T00:00:00","Title":"National Third Sector GIRFEC project: Getting children's services right for every child - how the third sector can help","Sponsor":"George Adam MSP"},{"ID":111,"Date":"2015-11-20T00:00:00","Title":"Marine Tourism Conference","Sponsor":"Stuart McMillan MSP"},{"ID":112,"Date":"2015-11-24T00:00:00","Title":"10 Years of Architecture & Design Scotland (A&DS)","Sponsor":"Patricia Ferguson MSP"},{"ID":113,"Date":"2015-11-24T00:00:00","Title":"Scottish Literature International lecture","Sponsor":"Jean Urquhart MSP"},{"ID":114,"Date":"2015-11-24T00:00:00","Title":"European HIV-Hepatitis Testing Week - HIV Scotland Reception","Sponsor":"Kevin Stewart MSP"},{"ID":115,"Date":"2015-11-24T00:00:00","Title":"Shaw Trust Scotland","Sponsor":"Michael McMahon MSP"},{"ID":116,"Date":"2015-11-24T00:00:00","Title":"Delivering biodiversity through grouse moor management","Sponsor":"Graeme Dey MSP"},{"ID":117,"Date":"2015-11-25T00:00:00","Title":"National Gaelic Schools Debate and Cross Party Group on Gaelic's Annual Reception","Sponsor":"Angus MacDonald MSP"},{"ID":118,"Date":"2015-11-25T00:00:00","Title":"HIE's 50th Anniversary","Sponsor":"Dave Thompson MSP"},{"ID":119,"Date":"2015-11-25T00:00:00","Title":"Scotland's Nuclear Sector & The Economy","Sponsor":"Iain Gray MSP"},{"ID":120,"Date":"2015-11-26T00:00:00","Title":"Implementing the 'Discards Ban' in Scotland","Sponsor":"Angus MacDonald MSP"},{"ID":121,"Date":"2015-11-26T00:00:00","Title":"PAS Parliamentary Reception","Sponsor":"Stuart McMillan MSP"},{"ID":122,"Date":"2015-11-26T00:00:00","Title":"Centenary Memorials Restoration Fund Reception","Sponsor":"Alex Salmond MSP"},{"ID":123,"Date":"2015-11-30T00:00:00","Title":"St Andrews Day Schools Debating Competition 2015","Sponsor":"SPCB"},{"ID":124,"Date":"2015-12-01T00:00:00","Title":"Penumbra 30 Years of Making a Positive Difference","Sponsor":"Mary Scanlon MSP"},{"ID":125,"Date":"2015-12-01T00:00:00","Title":"Promoting General Practice: RCGP Scotland's Manifesto for 2016","Sponsor":"Bob Doris MSP"},{"ID":126,"Date":"2015-12-01T00:00:00","Title":"Land Ecology: The Norwegian Experience","Sponsor":"Rob Gibson MSP"},{"ID":127,"Date":"2015-12-01T00:00:00","Title":"Moonwalk Supporting Vital Cancer Services","Sponsor":"Drew Smith MSP"},{"ID":128,"Date":"2015-12-02T00:00:00","Title":"Design in Action Business Showcase ","Sponsor":"Michael Russell MSP"},{"ID":129,"Date":"2015-12-02T00:00:00","Title":"Money Advice Scotland","Sponsor":"Deputy Presiding Officer John Scott MSP and Minister for Business, Energy and Tourism"},{"ID":130,"Date":"2015-12-02T00:00:00","Title":"Physiotherapy Works in Scotland","Sponsor":"Dennis Robertson MSP"},{"ID":131,"Date":"2015-12-02T00:00:00","Title":"In the pink? In the red? Or in between?","Sponsor":"Mark McDonald MSP"},{"ID":132,"Date":"2015-12-03T00:00:00","Title":"Care Opinion: Supporting the Citizen Voice","Sponsor":"Roderick Campbell MSP"},{"ID":133,"Date":"2015-12-03T00:00:00","Title":"HiFest Showcase","Sponsor":"Mike MacKenzie MSP "},{"ID":134,"Date":"2015-12-03T00:00:00","Title":"Clydeside Action on Asbestos","Sponsor":"Stuart McMillan MSP"},{"ID":135,"Date":"2015-12-04T00:00:00","Title":"Young Voices on Preventing Sexual Violence","Sponsor":"Malcolm Chisholm MSP"},{"ID":136,"Date":"2015-12-07T00:00:00","Title":"Scottish Public Service Awards","Sponsor":"Presiding Officer and Cabinet Secretary for Fair Work, Skills and Training"},{"ID":137,"Date":"2015-12-08T00:00:00","Title":"Fields in Trust's 90th Anniversary","Sponsor":"Alison Johnstone MSP"},{"ID":138,"Date":"2015-12-08T00:00:00","Title":"The Vascular Health and Stroke Training Programme","Sponsor":"Duncan McNeil MSP"},{"ID":139,"Date":"2015-12-08T00:00:00","Title":"CBI Scotland","Sponsor":"Ruth Davidson MSP"},{"ID":140,"Date":"2015-12-09T00:00:00","Title":"International Human Rights Day","Sponsor":"John Finnie MSP"},{"ID":141,"Date":"2015-12-09T00:00:00","Title":"SBATC Apprentice of the Year Awards 2015","Sponsor":"Nigel Don MSP"},{"ID":142,"Date":"2015-12-09T00:00:00","Title":"PRS for Music Creators Reception","Sponsor":"Deputy Presiding Officer and Cabinet Secretary for Culture, Europe and External Affairs"},{"ID":143,"Date":"2015-12-10T00:00:00","Title":"Scarf School Calendar Awards","Sponsor":"Mark McDonald MSP"},{"ID":144,"Date":"2015-12-10T00:00:00","Title":"Write to End Violence Against Women Awards","Sponsor":"Kezia Dugdale MSP"},{"ID":145,"Date":"2015-12-14T00:00:00","Title":"Roots of Empathy","Sponsor":"Dennis Robertson MSP"},{"ID":146,"Date":"2015-12-15T00:00:00","Title":"Selfhelp4stroke","Sponsor":"Dennis Robertson MSP"},{"ID":147,"Date":"2015-12-15T00:00:00","Title":"Cystic Fibrosis Trust","Sponsor":"Bob Doris MSP"},{"ID":148,"Date":"2015-12-15T00:00:00","Title":"Scottish Health Action on Alcohol Problems-LGBT","Sponsor":"Jim Eadie MSP"},{"ID":149,"Date":"2015-12-16T00:00:00","Title":"Scottish Parliament Christmas Carol Service","Sponsor":"Presiding Officer"},{"ID":150,"Date":"2015-12-17T00:00:00","Title":"Scotland Welcomes Refugees","Sponsor":"Sandra White MSP"},{"ID":151,"Date":"2015-12-17T00:00:00","Title":"MG ALBA - Vision Document LΓ¨irsinn 2021 ","Sponsor":"Angus MacDonald MSP"},{"ID":152,"Date":"2015-12-17T00:00:00","Title":"Humanist Yuletide Lunch","Sponsor":"Patrick Harvie MSP"},{"ID":153,"Date":"2015-12-17T00:00:00","Title":"BBC Charter Renewal - Advanced preview of the Doctor Who Christmas Special","Sponsor":"Claire Baker MSP / George Adam MSP"},{"ID":154,"Date":"2016-01-07T00:00:00","Title":"A Football Manifesto - Scottish Football Supporters Association","Sponsor":"Alison Johnstone MSP"},{"ID":155,"Date":"2016-01-12T00:00:00","Title":"Scottish Renewables 2016","Sponsor":"Patrick Harvie MSP"},{"ID":156,"Date":"2016-01-12T00:00:00","Title":"No one living in a hard-to-heat, draughty home by 2025","Sponsor":"Jim Eadie MSP"},{"ID":157,"Date":"2016-01-13T00:00:00","Title":"VisitScotland","Sponsor":"Deputy Presiding Officer Elaine Smith MSP and Minister for Business, Energy and Tourism Fergus Ewing MSP"},{"ID":158,"Date":"2016-01-13T00:00:00","Title":"Celebrating the Success of Supporting Young People","Sponsor":"Tavish Scott MSP"},{"ID":159,"Date":"2016-01-13T00:00:00","Title":"IoF Scotland / OSCR Reception","Sponsor":"Bill Kidd MSP"},{"ID":160,"Date":"2016-01-14T00:00:00","Title":"Scottish Local Shop Report","Sponsor":"Gordon MacDonald MSP"},{"ID":161,"Date":"2016-01-14T00:00:00","Title":"Parliamentary Cancer Pledge ","Sponsor":"Jackson Carlaw MSP"},{"ID":162,"Date":"2016-01-14T00:00:00","Title":"The Financial Capability Strategy for Scotland","Sponsor":"John Wilson MSP"},{"ID":163,"Date":"2016-01-15T00:00:00","Title":"NUS: Women Lead the Way","Sponsor":"Alison Johnstone MSP"},{"ID":164,"Date":"2016-01-19T00:00:00","Title":"John Bellany and Scottish Women's Hospitals exhibition Preview Reception","Sponsor":"Presiding Officer "},{"ID":165,"Date":"2016-01-19T00:00:00","Title":"Celebrating James Watt 2015-19","Sponsor":"Angus MacDonald MSP"},{"ID":166,"Date":"2016-01-19T00:00:00","Title":"SAMH","Sponsor":"Bob Doris MSP"},{"ID":167,"Date":"2016-01-19T00:00:00","Title":"Scotland's Trusts - A New Pill for Health","Sponsor":"Bruce Crawford MSP"},{"ID":168,"Date":"2016-01-19T00:00:00","Title":"Engineering trends, potential and challenges in Scotland","Sponsor":"Elaine Murray MSP"},{"ID":169,"Date":"2016-01-20T00:00:00","Title":"Consular Corps' Burns Supper","Sponsor":"Presiding Officer "},{"ID":170,"Date":"2016-01-21T00:00:00","Title":"A Deposit Return System for Scotland","Sponsor":"Angus MacDonald MSP"},{"ID":171,"Date":"2016-01-21T00:00:00","Title":"First Ministers Portrait Exhibition - Art Talk","Sponsor":"Angus MacDonald MSP"},{"ID":172,"Date":"2016-01-26T00:00:00","Title":"Quality Scotland Celebrating 25 Years of Excellence","Sponsor":"Richard Lyle MSP"},{"ID":173,"Date":"2016-01-26T00:00:00","Title":"Scottish Parliament Burns Club Supper","Sponsor":"Rob Gibson MSP"},{"ID":174,"Date":"2016-01-26T00:00:00","Title":"Gathering the Voices ","Sponsor":"Stewart Maxwell MSP"},{"ID":175,"Date":"2016-01-26T00:00:00","Title":"Immigration: What’s the Story? – Show Racism the Red Card","Sponsor":"Alex Neil MSP"},{"ID":176,"Date":"2016-01-27T00:00:00","Title":"Active Kids: Briefing with Paralympics Gold Medallist Ellie Simmonds","Sponsor":"Linda Fabiani MSP"},{"ID":177,"Date":"2016-01-27T00:00:00","Title":"Forestry in Scotland","Sponsor":"Angus MacDonald MSP"},{"ID":178,"Date":"2016-01-27T00:00:00","Title":"Essential Facts Regarding A&E Services in Scotland","Sponsor":"Fiona McLeod MSP"},{"ID":179,"Date":"2016-01-27T00:00:00","Title":"A campaign group for a Safe and Accountable Peoples NHS in Scotland (ASAP)","Sponsor":"Neil Findlay MSP"},{"ID":180,"Date":"2016-01-28T00:00:00","Title":"Calling Time on Nuisance Calls","Sponsor":"Graeme Dey MSP"},{"ID":181,"Date":"2016-01-28T00:00:00","Title":"Celebrate Organic Ambitions: Scotland's Organic Action Plan 2016-2020","Sponsor":"Angus McDonald MSP"},{"ID":182,"Date":"2016-01-28T00:00:00","Title":"100 years of the right to Contentiously Object","Sponsor":"Patrick Harvie MSP"},{"ID":183,"Date":"2016-02-02T00:00:00","Title":"Fraser of Allander Institute at the University of Strathclyde ","Sponsor":"Jackie Baillie MSP, Jackson Carlaw MSP, Patrick Harvie MSP, Willie Rennie MSP, John Swinney MSP "},{"ID":184,"Date":"2016-02-02T00:00:00","Title":"Scotland's Futures Forum and GGIS Annual Seminar","Sponsor":"Scotland's Future Forum"},{"ID":185,"Date":"2016-02-02T00:00:00","Title":"Zero Tolerance to Female Genital Mutilation ","Sponsor":"Margaret McCulloch MSP "},{"ID":186,"Date":"2016-02-02T00:00:00","Title":"Citizen and Consumer Interests in Communications ","Sponsor":"Bruce Crawford MSP"},{"ID":187,"Date":"2016-02-02T00:00:00","Title":"PCS Parliamentary Reception","Sponsor":"Neil Findlay MSP"},{"ID":188,"Date":"2016-02-03T00:00:00","Title":"Lloyds TSB Foundation for Scotland 30 Years of Supporting Scotland","Sponsor":"Presiding Officer & Deputy First Minister"},{"ID":189,"Date":"2016-02-03T00:00:00","Title":"Mobility as a Service: A New Reality","Sponsor":"Graeme Dey MSP"},{"ID":190,"Date":"2016-02-03T00:00:00","Title":"Music Therapy and Dementia: Enriching Life When It is Needed","Sponsor":"Tavish Scott MSP "},{"ID":191,"Date":"2016-02-03T00:00:00","Title":"Federation of Entertainment Unions Manifesto","Sponsor":"Claire Baker MSP"},{"ID":192,"Date":"2016-02-03T00:00:00","Title":"ACTSA Reception: Anti-Apartheid Movement","Sponsor":"Drew Smith MSP"},{"ID":193,"Date":"2016-02-04T00:00:00","Title":"Vattenfall – investing in Scottish onshore and offshore wind","Sponsor":"Dennis Robertson MSP"},{"ID":194,"Date":"2016-02-09T00:00:00","Title":"A Fairer and Healthier Scotland: the Housing Association Offer","Sponsor":"Jim Eadie MSP"},{"ID":195,"Date":"2016-02-09T00:00:00","Title":"Starting Again – a new life in Scotland","Sponsor":"Sandra White MSP"},{"ID":196,"Date":"2016-02-09T00:00:00","Title":"More Than Just Money","Sponsor":"Jenny Marra MSP"},{"ID":197,"Date":"2016-02-09T00:00:00","Title":"Digital Scotland Superfast Broadband (DSSB) Briefing","Sponsor":"Stewart Stevenson MSP"},{"ID":198,"Date":"2016-02-09T00:00:00","Title":"Laudato Si’ and delivering climate change action in Scotland","Sponsor":"Siobhan McMahon MSP & Sarah Boyack MSP"},{"ID":199,"Date":"2016-02-10T00:00:00","Title":"Parkinson's UK - Get it on Time","Sponsor":"Dennis Robertson MSP"},{"ID":200,"Date":"2016-02-10T00:00:00","Title":"Celebrating diversities in Scotland - Polish Culture and Language","Sponsor":"Jean Urquhart MSP"},{"ID":201,"Date":"2016-02-10T00:00:00","Title":"Blacklist","Sponsor":"Elaine Smith MSP"},{"ID":202,"Date":"2016-02-10T00:00:00","Title":"Hepatitis C – Scoping Exercise and Film Screening","Sponsor":"Malcolm Chisholm MSP"},{"ID":203,"Date":"2016-02-10T00:00:00","Title":"POVERTY: See It Change It- East Lothian","Sponsor":"Iain Gray MSP"},{"ID":204,"Date":"2016-02-11T00:00:00","Title":"#ScotSpirit Photocall","Sponsor":"Bruce Crawford MSP"},{"ID":205,"Date":"2016-02-11T00:00:00","Title":"Edinburgh Festival Fringe Society","Sponsor":"Colin Keir MSP"},{"ID":206,"Date":"2016-02-11T00:00:00","Title":"Scotland’s UNESCO Global Geoparks ","Sponsor":"Jean Urquhart MSP"},{"ID":207,"Date":"2016-02-12T00:00:00","Title":"Making Scotland a Credit Union Nation","Sponsor":"SPCB"},{"ID":208,"Date":"2016-02-23T00:00:00","Title":"No Young Person Left Behind","Sponsor":"George Adam MSP & Iain Gray MSP"},{"ID":209,"Date":"2016-02-23T00:00:00","Title":"Scottish Newspaper Society: The Effectiveness of Local Newspapers","Sponsor":"Alex Neil MSP"},{"ID":210,"Date":"2016-02-23T00:00:00","Title":"University of the Highlands and Islands","Sponsor":"Jean Urquhart MSP"},{"ID":211,"Date":"2016-02-23T00:00:00","Title":"Huts for Scotland: Introducing the new guidance","Sponsor":"Angus MacDonald MSP"},{"ID":212,"Date":"2016-02-24T00:00:00","Title":"Scottish Environment Link","Sponsor":"Rob Gibson MSP"},{"ID":213,"Date":"2016-02-24T00:00:00","Title":"Podiatry and Prevention- Keeping Scotland on its Feet.","Sponsor":"Jim Hume MSP"},{"ID":214,"Date":"2016-02-24T00:00:00","Title":"What Would Keir Hardie say? ","Sponsor":"Neil Findlay MSP"},{"ID":215,"Date":"2016-02-25T00:00:00","Title":"Shaping Landscapes","Sponsor":"Liam McArthur MSP"},{"ID":216,"Date":"2016-02-25T00:00:00","Title":"CrossReach Drop-in","Sponsor":"Jim Eadie MSP"},{"ID":217,"Date":"2016-02-25T00:00:00","Title":"Ocean Youth Trust Scotland","Sponsor":"Stuart McMillan MSP"},{"ID":218,"Date":"2016-02-25T00:00:00","Title":"An Impact event on a public protection project","Sponsor":"Alex Johnstone MSP"},{"ID":219,"Date":"2016-02-25T00:00:00","Title":"Royal Highland Education Trust","Sponsor":"John Scott MSP"},{"ID":220,"Date":"2016-02-26T00:00:00","Title":"Scotland's Journey: Quality Eating Disorder Services","Sponsor":"Dennis Robertson MSP"},{"ID":221,"Date":"2016-02-29T00:00:00","Title":"Learning for Democracy","Sponsor":"Jean Urquhart MSP"},{"ID":222,"Date":"2016-03-01T00:00:00","Title":"Rare Disease Day 2016","Sponsor":"Malcolm Chisholm MSP "},{"ID":223,"Date":"2016-03-01T00:00:00","Title":"Moving beyond neonicotinoids ","Sponsor":"Graeme Dey MSP"},{"ID":224,"Date":"2016-03-01T00:00:00","Title":"Scotland United in Prayer","Sponsor":"Murdo Fraser MSP"},{"ID":225,"Date":"2016-03-01T00:00:00","Title":"Child Health and Wellbeing","Sponsor":"Cara Hilton MSP"},{"ID":226,"Date":"2016-03-02T00:00:00","Title":"EU Integration from a Scottish Shia Perspective","Sponsor":"Bill Kidd MSP "},{"ID":227,"Date":"2016-03-02T00:00:00","Title":"Borders Forest Trust 20th Anniversary ","Sponsor":"Jim Hume MSP "},{"ID":228,"Date":"2016-03-02T00:00:00","Title":"Sue Ryder ","Sponsor":"Christian Allard MSP"},{"ID":229,"Date":"2016-03-02T00:00:00","Title":"The Brain Tumour Charity","Sponsor":"Cameron Buchanan MSP"},{"ID":230,"Date":"2016-03-03T00:00:00","Title":"Scotland’s outdoors for health & wellbeing","Sponsor":"Alison Johnstone MSP"},{"ID":231,"Date":"2016-03-03T00:00:00","Title":"Improving Safety Standards in the Scottish Prison Sector","Sponsor":"Graeme Pearson MSP"},{"ID":232,"Date":"2016-03-09T00:00:00","Title":"Marie Curie Great Daffadil Appeal 2016","Sponsor":"Linda Fabiani MSP "},{"ID":233,"Date":"2016-03-09T00:00:00","Title":"Epilepsy Services in Scotland: A Blue Print for Success","Sponsor":"Kenneth Gibson MSP"},{"ID":234,"Date":"2016-03-09T00:00:00","Title":"Supporting Scotland’s Heritage","Sponsor":"Jamie McGrigor MSP "},{"ID":235,"Date":"2016-03-09T00:00:00","Title":"The contribution of e-cigarettes to individual and public health","Sponsor":"Mike MacKenzie MSP"},{"ID":236,"Date":"2016-03-10T00:00:00","Title":"In-Work Poverty and Enterprise: Self-employment and Business Ownership as Contexts of Poverty","Sponsor":"Joan McAlpine MSP "},{"ID":237,"Date":"2016-03-10T00:00:00","Title":"40 Years of Scottish Women’s Aid Choir Performance","Sponsor":"Malcolm Chisholm MSP/Christina McKelvie MSP"},{"ID":238,"Date":"2016-03-10T00:00:00","Title":"Banking for the Common Good","Sponsor":"Lesley Brennan MSP"},{"ID":239,"Date":"2016-03-10T00:00:00","Title":"StepChange Debt Charity Scotland: Scotland in the Red","Sponsor":"James Dornan MSP"},{"ID":240,"Date":"2016-03-10T00:00:00","Title":"The UK wide report on Depression and Employment","Sponsor":"Malcolm Chisholm MSP"},{"ID":241,"Date":"2016-03-15T00:00:00","Title":"Cancer Research UK","Sponsor":"Malcolm Chisholm MSP"},{"ID":242,"Date":"2016-03-15T00:00:00","Title":"Celebrating Food for Thought ","Sponsor":"Rob Gibson MSP"},{"ID":243,"Date":"2016-03-15T00:00:00","Title":"Lions Clubs International UN Day","Sponsor":"Alex Fergusson MSP"},{"ID":244,"Date":"2016-03-15T00:00:00","Title":"Tackling homelessness in Scotland","Sponsor":"Gordon MacDonald MSP "},{"ID":245,"Date":"2016-03-16T00:00:00","Title":"A Charter for Trees, Woods and People","Sponsor":"Claudia Beamish MSP "},{"ID":246,"Date":"2016-03-16T00:00:00","Title":"Hibs Community Foundation","Sponsor":"Kezia Dugdale MSP"},{"ID":247,"Date":"2016-03-17T00:00:00","Title":"Green/Blue infrastructure ","Sponsor":"Chic Brodie MSP"},{"ID":248,"Date":"2016-03-17T00:00:00","Title":"Skills & Training in Scotch Whisky Industry","Sponsor":"Gordon MacDonald MSP "},{"ID":249,"Date":"2016-03-17T00:00:00","Title":"Industrial Evolution Report ","Sponsor":"Kenneth Gibson MSP"},{"ID":250,"Date":"2016-03-17T00:00:00","Title":"UN Global Goals: Bangladesh & Scotland Cooperation","Sponsor":"Sarah Boyack MSP"},{"ID":251,"Date":"2016-03-17T00:00:00","Title":"Intersex Equality & Human Rights ","Sponsor":"Margaret McCulloch MSP"},{"ID":252,"Date":"2016-03-21T00:00:00","Title":"Our Films: Our Europe Premiere and Awards Ceremony","Sponsor":"Christina McKelvie MSP"},{"ID":253,"Date":"2016-03-22T00:00:00","Title":"Spark 50th Anniversary ","Sponsor":"Fiona McLeod MSP "},{"ID":254,"Date":"2016-03-22T00:00:00","Title":"Scottish Young Consumer of the Year Final 2016","Sponsor":"Dave Thompson MSP"},{"ID":255,"Date":"2016-03-22T00:00:00","Title":"Family Group Conferencing -The Child At The Centre","Sponsor":"Mark MacDonald MSP"},{"ID":256,"Date":"2016-03-22T00:00:00","Title":"Diabetes in Scotland ","Sponsor":"Dennis Robertson MSP"},{"ID":257,"Date":"2016-03-23T00:00:00","Title":"Patient Charter on Access to Medicines in Scotland","Sponsor":"Malcolm Chisholm MSP"},{"ID":258,"Date":"2016-03-23T00:00:00","Title":"Every Picture Tells a Story","Sponsor":"Jim Eadie MSP"},{"ID":259,"Date":"2016-03-23T00:00:00","Title":"Celebrating 10 Years of Smoke-Free Indoor Public Places","Sponsor":"Stewart Maxwell MSP"},{"ID":260,"Date":"2016-05-25T00:00:00","Title":"European Heart Network Annual Conference 2016","Sponsor":"Andy Wightman MSP "},{"ID":261,"Date":"2016-06-02T00:00:00","Title":"Photocall - Volunteers' Week ","Sponsor":"Bruce Crawford MSP"},{"ID":262,"Date":"2016-06-07T00:00:00","Title":"The Headmasters' Conference","Sponsor":"Liz Smith MSP"},{"ID":263,"Date":"2016-06-07T00:00:00","Title":"Should GM be on the table?","Sponsor":"Iain Gray MSP"},{"ID":264,"Date":"2016-06-08T00:00:00","Title":"Social security in Scotland: A manifesto for change","Sponsor":"Patrick Harvie MSP"},{"ID":265,"Date":"2016-06-16T00:00:00","Title":"Neurological care","Sponsor":"Mark McDonald MSP"},{"ID":266,"Date":"2016-06-16T00:00:00","Title":"Looking Forward Not Back National Symposium","Sponsor":"Christina McKelvie MSP / Alison Harris MSP"},{"ID":267,"Date":"2016-06-28T00:00:00","Title":"International Cricket Council Annual Conference 2016","Sponsor":"Deputy Presiding Officer Linda Fabiani MSP and Minister for Public Health and Sport Aileen Campbell MSP"},{"ID":268,"Date":"2016-06-28T00:00:00","Title":"Scottish IBD Delivery Plan","Sponsor":"Clare Adamson MSP"},{"ID":269,"Date":"2016-06-28T00:00:00","Title":"BBC Scotland Charter","Sponsor":"George Adam MSP "},{"ID":270,"Date":"2016-06-28T00:00:00","Title":"CAMRA","Sponsor":"Patrick Harvie MSP"},{"ID":271,"Date":"2016-06-28T00:00:00","Title":"Inverness Airport to Heathrow Airport Service","Sponsor":"Maree Todd MSP"},{"ID":272,"Date":"2016-06-29T00:00:00","Title":"Holyrood Magazine and Coca-Cola Summer Drinks","Sponsor":"Linda Fabiani MSP"},{"ID":273,"Date":"2016-06-29T00:00:00","Title":"Scottish Introduction to The Parliament Project","Sponsor":"Willie Rennie MSP"},{"ID":274,"Date":"2016-06-29T00:00:00","Title":"Addition Workers Graduation","Sponsor":"John Finnie MSP"},{"ID":275,"Date":"2016-06-30T00:00:00","Title":"No Patient Left Behind","Sponsor":"Gillian Martin MSP"},{"ID":276,"Date":"2016-06-30T00:00:00","Title":"Snare-free Scotland information and photocall drop-in event","Sponsor":"Mark Ruskell MSP"},{"ID":277,"Date":"2016-06-30T00:00:00","Title":"Scottish PEN event for Raid Badawi","Sponsor":"Michael Russell MSP"}] \ No newline at end of file +[ + { + "ID": 1, + "Date": "2015-09-01T00:00:00Z", + "Title": "European North Sea Energy Alliance", + "Sponsor": "Christina McKelvie MSP" + }, + { "ID": 2, "Date": "2015-09-01T00:00:00Z", "Title": "AS it is", "Sponsor": "Margaret McCulloch MSP" }, + { + "ID": 3, + "Date": "2015-09-01T00:00:00Z", + "Title": "Building Capacity, Investing in Stroke Research", + "Sponsor": "Dennis Robertson MSP" + }, + { + "ID": 4, + "Date": "2015-09-02T00:00:00Z", + "Title": "Celebrating Scotland's Small and Rural Towns", + "Sponsor": "Margaret McCulloch MSP" + }, + { "ID": 5, "Date": "2015-09-02T00:00:00Z", "Title": "50 years of supporting carers", "Sponsor": "Graeme Dey MSP" }, + { "ID": 6, "Date": "2015-09-02T00:00:00Z", "Title": "Sole Searching - A Hootenanny", "Sponsor": "Alex Rowley MSP" }, + { + "ID": 7, + "Date": "2015-09-02T00:00:00Z", + "Title": "Exploring European Approaches to Development", + "Sponsor": "Sarah Boyack MSP" + }, + { + "ID": 8, + "Date": "2015-09-03T00:00:00Z", + "Title": "Saltire Fletcher Lecture 2015", + "Sponsor": "Linda Fabiani MSP" + }, + { "ID": 9, "Date": "2015-09-07T00:00:00Z", "Title": "Your Say", "Sponsor": "Welfare Reform Committee" }, + { + "ID": 10, + "Date": "2015-09-08T00:00:00Z", + "Title": "Celebrating Scotland's Walking Champions", + "Sponsor": "Patricia Ferguson MSP" + }, + { "ID": 11, "Date": "2015-09-08T00:00:00Z", "Title": "Columba 1400 Impact Study", "Sponsor": "Dave Thompson MSP" }, + { "ID": 12, "Date": "2015-09-08T00:00:00Z", "Title": "Women in Business ", "Sponsor": "Margaret McCulloch MSP" }, + { + "ID": 13, + "Date": "2015-09-09T00:00:00Z", + "Title": "Scottish Older People's Assembly", + "Sponsor": "Christine Grahame MSP" + }, + { + "ID": 14, + "Date": "2015-09-09T00:00:00Z", + "Title": "How we can prevent homelessness and reduce re-offending?", + "Sponsor": "Mary Fee MSP" + }, + { + "ID": 15, + "Date": "2015-09-09T00:00:00Z", + "Title": "Street Law: bringing practical law to classrooms", + "Sponsor": "Paul Martin MSP" + }, + { "ID": 16, "Date": "2015-09-09T00:00:00Z", "Title": "FAST Forward ", "Sponsor": "Stewart Maxwell MSP" }, + { + "ID": 17, + "Date": "2015-09-09T00:00:00Z", + "Title": "Preventing Accidents, Scotland's National Outcomes", + "Sponsor": "Clare Adamson MSP" + }, + { + "ID": 18, + "Date": "2015-09-10T00:00:00Z", + "Title": "Nature of Scotland Awards 2015 Shortlist ", + "Sponsor": "Claudia Beamish MSP" + }, + { + "ID": 19, + "Date": "2015-09-15T00:00:00Z", + "Title": "Children Get Arthritis Too", + "Sponsor": "Margaret McCulloch MSP" + }, + { + "ID": 20, + "Date": "2015-09-15T00:00:00Z", + "Title": "Transport Focus Stakeholders ", + "Sponsor": "Patrick Harvie MSP" + }, + { "ID": 21, "Date": "2015-09-15T00:00:00Z", "Title": "Growing Your Small Business", "Sponsor": "Hugh Henry MSP" }, + { "ID": 22, "Date": "2015-09-16T00:00:00Z", "Title": "SCIAF 50th Anniversary ", "Sponsor": "Presiding Officer " }, + { + "ID": 23, + "Date": "2015-09-16T00:00:00Z", + "Title": "Luxembourg Presidency of the EU ", + "Sponsor": "Christina McKelvie MSP" + }, + { + "ID": 24, + "Date": "2015-09-16T00:00:00Z", + "Title": "Camphill Scotland - Worldwide Weave", + "Sponsor": "Alison McInnes MSP" + }, + { + "ID": 25, + "Date": "2015-09-16T00:00:00Z", + "Title": "Association of Chief Officers of Scottish Voluntary Organisations", + "Sponsor": "Alex Neil MSP" + }, + { + "ID": 26, + "Date": "2015-09-16T00:00:00Z", + "Title": "IPSA Conference 2015: Roundtable and Reception", + "Sponsor": "Bruce Crawford MSP" + }, + { + "ID": 27, + "Date": "2015-09-17T00:00:00Z", + "Title": "Wear it Pink photocall", + "Sponsor": "Christina McKelvie MSP" + }, + { "ID": 28, "Date": "2015-09-17T00:00:00Z", "Title": "Holyrood Apple Day 2015", "Sponsor": "John Wilson MSP" }, + { + "ID": 29, + "Date": "2015-09-17T00:00:00Z", + "Title": "Youth Volunteering - The Lived Experience", + "Sponsor": "Fiona McLeod MSP" + }, + { "ID": 30, "Date": "2015-09-17T00:00:00Z", "Title": "See Me: In Health", "Sponsor": "Jenny Marra MSP" }, + { + "ID": 31, + "Date": "2015-09-18T00:00:00Z", + "Title": "Future Directions for Well-Being Policy", + "Sponsor": "Scotland's Future Forum" + }, + { + "ID": 32, + "Date": "2015-09-21T00:00:00Z", + "Title": "Breast Cancer Care Scotland - B-Aware Mobile Roadshow", + "Sponsor": "Bob Doris MSP" + }, + { + "ID": 33, + "Date": "2015-09-22T00:00:00Z", + "Title": "Scottish Craft Distillers Association ", + "Sponsor": "Jean Urquhart MSP " + }, + { "ID": 34, "Date": "2015-09-22T00:00:00Z", "Title": "Connect2Renewables", "Sponsor": "Christina McKelvie MSP" }, + { "ID": 35, "Date": "2015-09-22T00:00:00Z", "Title": "25 Years of Parkhead CAB", "Sponsor": "John Mason MSP" }, + { + "ID": 36, + "Date": "2015-09-23T00:00:00Z", + "Title": "250th Anniversary of Thomas Muir, Father of Scottish Democracy", + "Sponsor": "Fiona McLeod MSP" + }, + { + "ID": 37, + "Date": "2016-09-23T00:00:00Z", + "Title": "Scottish Sport Alliance Manifesto for Scottish Sport", + "Sponsor": "Alison Johnstone MSP and Liz Smith MSP" + }, + { + "ID": 38, + "Date": "2019-09-23T00:00:00Z", + "Title": "SCOTLAND: Towards a Global Nuclear Weapons Ban", + "Sponsor": "Bill Kidd MSP" + }, + { + "ID": 39, + "Date": "2015-09-24T00:00:00Z", + "Title": "Our Environment Competition: Meet the Winners", + "Sponsor": "Alex Fergusson MSP" + }, + { + "ID": 40, + "Date": "2015-09-24T00:00:00Z", + "Title": "National Review of Primary Care Out of Hours Services", + "Sponsor": "Duncan McNeill MSP" + }, + { + "ID": 41, + "Date": "2015-09-24T00:00:00Z", + "Title": "1+2: Language Learning for All", + "Sponsor": "Michael Russell MSP" + }, + { + "ID": 42, + "Date": "2015-09-29T00:00:00Z", + "Title": "Working to End Breast Cancer Now", + "Sponsor": "Jenny Marra MSP" + }, + { "ID": 43, "Date": "2015-09-29T00:00:00Z", "Title": "Colleges Scotland ", "Sponsor": "Iain Gray MSP" }, + { + "ID": 44, + "Date": "2015-09-29T00:00:00Z", + "Title": "Safeguarding Diabetes Service ", + "Sponsor": "Nanette Milne MSP" + }, + { "ID": 45, "Date": "2015-09-30T00:00:00Z", "Title": "STV Breakfast Briefing", "Sponsor": "Linda Fabiani MSP" }, + { + "ID": 46, + "Date": "2015-09-30T00:00:00Z", + "Title": "Self Management Awards 2015", + "Sponsor": "Jackie Baillie MSP" + }, + { "ID": 47, "Date": "2015-09-30T00:00:00Z", "Title": "Livestock Keepers", "Sponsor": "John Scott MSP" }, + { + "ID": 48, + "Date": "2015-09-30T00:00:00Z", + "Title": "High Quality Haemophilia Care in Scotland", + "Sponsor": "Richard Lyle MSP" + }, + { + "ID": 49, + "Date": "2015-09-30T00:00:00Z", + "Title": "Special Olympics World Games 2015", + "Sponsor": "Presiding Officer and Minister for Sport, Health Improvement and Mental Health" + }, + { + "ID": 50, + "Date": "2015-10-01T00:00:00Z", + "Title": "Breaking the Mould Celebrating Women's Role Over the Past 100 Years", + "Sponsor": "Joan McAlpine MSP" + }, + { "ID": 51, "Date": "2015-10-01T00:00:00Z", "Title": "Play/Talk/Read", "Sponsor": "Fiona McLeod MSP" }, + { + "ID": 52, + "Date": "2015-10-01T00:00:00Z", + "Title": "Manufacturing our Future: Driving Value for Scotland", + "Sponsor": "Gordon MacDonald MSP" + }, + { + "ID": 53, + "Date": "2015-10-05T00:00:00Z", + "Title": "Scottish Older People's Assembly", + "Sponsor": "Christian Allard MSP" + }, + { + "ID": 54, + "Date": "2015-10-06T00:00:00Z", + "Title": "Federation of City Farms and Community Gardens (FCFCG) 10th Anniversary in Scotland", + "Sponsor": "Anne McTaggart MSP" + }, + { + "ID": 55, + "Date": "2015-10-06T00:00:00Z", + "Title": "SSAFA: The Armed Forces Charity", + "Sponsor": "Margaret Mitchell MSP" + }, + { + "ID": 56, + "Date": "2015-10-06T00:00:00Z", + "Title": "From dots to digital: National Braille Week 2015", + "Sponsor": "Dennis Robertson MSP" + }, + { + "ID": 57, + "Date": "2015-10-06T00:00:00Z", + "Title": "Roundtable: Women & Justice", + "Sponsor": "Jean Urquhart MSP" + }, + { + "ID": 58, + "Date": "2015-10-07T00:00:00Z", + "Title": "Unveiling and presentation of the Army painting Service ", + "Sponsor": "Presiding Officer" + }, + { "ID": 59, "Date": "2015-10-07T00:00:00Z", "Title": "UK Music Event", "Sponsor": "Anne McTaggart MSP" }, + { + "ID": 60, + "Date": "2015-10-07T00:00:00Z", + "Title": "UN 70 Years of Service to Humanity", + "Sponsor": "Christina McKelvie MSP" + }, + { + "ID": 61, + "Date": "2015-10-07T00:00:00Z", + "Title": "Alcoholics Anonymous Awareness", + "Sponsor": "Rhoda Grant MSP" + }, + { + "ID": 62, + "Date": "2015-10-07T00:00:00Z", + "Title": "Human Rights and The Peace Process in Colombia", + "Sponsor": "Sarah Boyack MSP" + }, + { + "ID": 63, + "Date": "2015-10-08T00:00:00Z", + "Title": "Glasgow Gurdwara - Kultar's Mime", + "Sponsor": "Sandra White MSP" + }, + { + "ID": 64, + "Date": "2015-10-08T00:00:00Z", + "Title": "International Credit Union Day 2015", + "Sponsor": "John Wilson MSP" + }, + { + "ID": 65, + "Date": "2015-10-26T00:00:00Z", + "Title": "Scottish Futures Forum/Knowledge Exchange - Parliament/Universities", + "Sponsor": "Scottish Futures Forum" + }, + { + "ID": 66, + "Date": "2015-10-27T00:00:00Z", + "Title": "Scottish Tree of the Year Prize giving Reception", + "Sponsor": "Jim Hume MSP" + }, + { "ID": 67, "Date": "2015-10-27T00:00:00Z", "Title": "Citizens Advice Scotland", "Sponsor": "Dave Thompson MSP" }, + { "ID": 68, "Date": "2015-10-27T00:00:00Z", "Title": "Aberdeen City Region Deal", "Sponsor": "Mark McDonald MSP" }, + { + "ID": 69, + "Date": "2015-10-28T00:00:00Z", + "Title": "Scottish Parliament Launch of the 2015 Scottish Poppy Appeal", + "Sponsor": "The Presiding Officer" + }, + { + "ID": 70, + "Date": "2015-10-28T00:00:00Z", + "Title": "Scottish Sports Futures Reception", + "Sponsor": "Colin Keir MSP" + }, + { + "ID": 71, + "Date": "2015-10-28T00:00:00Z", + "Title": "Recognising the Contribution of William Hill", + "Sponsor": "John Scott MSP" + }, + { + "ID": 72, + "Date": "2015-10-28T00:00:00Z", + "Title": "Creating a 21st Century Learning Environment", + "Sponsor": "George Adam MSP" + }, + { + "ID": 73, + "Date": "2015-10-28T00:00:00Z", + "Title": "Care and Repair Edinburgh 30th Birthday Party", + "Sponsor": "Gordon MacDonald MSP" + }, + { + "ID": 74, + "Date": "2015-10-29T00:00:00Z", + "Title": "Ownership and Management Options for Scotland's Community Land Assets", + "Sponsor": "Chic Brodie MSP" + }, + { + "ID": 75, + "Date": "2015-10-29T00:00:00Z", + "Title": "Business in the Parliament 2015 Reception and Dinner", + "Sponsor": "Presiding Officer" + }, + { + "ID": 76, + "Date": "2015-10-30T00:00:00Z", + "Title": "Business in the Parliament 2015 ", + "Sponsor": "Presiding Officer" + }, + { "ID": 77, "Date": "2015-10-31T00:00:00Z", "Title": "Holyrood Rocks Final 2015", "Sponsor": "SPCB" }, + { + "ID": 78, + "Date": "2015-11-03T00:00:00Z", + "Title": "Celebrating Social Enterprise", + "Sponsor": "Tavish Scott MSP" + }, + { "ID": 79, "Date": "2015-11-03T00:00:00Z", "Title": "Holocaust Educational Trust", "Sponsor": "Ken McIntosh MSP" }, + { + "ID": 80, + "Date": "2015-11-03T00:00:00Z", + "Title": "10 Years of ScottishPower Energy People Trust", + "Sponsor": "James Dornan MSP" + }, + { + "ID": 81, + "Date": "2015-11-03T00:00:00Z", + "Title": "New lamp post mounted wind turbine technology", + "Sponsor": "Richard Lyle MSP" + }, + { + "ID": 82, + "Date": "2015-11-04T00:00:00Z", + "Title": "BHF Scotland: Fighting for Every Heart Beat", + "Sponsor": "Dennis Robertson MSP" + }, + { + "ID": 83, + "Date": "2015-11-04T00:00:00Z", + "Title": "Edinburgh Tenants Federation", + "Sponsor": "Sarah Boyack MSP" + }, + { + "ID": 84, + "Date": "2015-11-04T00:00:00Z", + "Title": "Psoriatic Arthritis Awareness in Scotland", + "Sponsor": "Dave Thompson MSP" + }, + { + "ID": 85, + "Date": "2015-11-04T00:00:00Z", + "Title": "Knitting a Nation: Social Fabric ", + "Sponsor": "Roderick Campbell MSP" + }, + { "ID": 86, "Date": "2015-11-04T00:00:00Z", "Title": "Blacklisted", "Sponsor": "Neil Findlay MSP" }, + { + "ID": 87, + "Date": "2015-11-06T00:00:00Z", + "Title": "Community Resources Network Scotland (CRNS) Conference 2015 - Choose to Reuse", + "Sponsor": "Patrick Harvie MSP" + }, + { + "ID": 88, + "Date": "2015-11-10T00:00:00Z", + "Title": "Lung Ha Theatre Company 30th Anniversary", + "Sponsor": "Joan McAlpine MSP" + }, + { + "ID": 89, + "Date": "2015-11-10T00:00:00Z", + "Title": "Making it Happen: Encouraging Enterprise & Entrepreneurship", + "Sponsor": "Liz Smith MSP" + }, + { + "ID": 90, + "Date": "2015-11-10T00:00:00Z", + "Title": "Celebrating World Diabetes Day", + "Sponsor": "Nanette Milne MSP" + }, + { + "ID": 91, + "Date": "2015-11-10T00:00:00Z", + "Title": "Prostitution Law Reform Bill", + "Sponsor": "Jean Urquhart MSP" + }, + { + "ID": 92, + "Date": "2015-11-10T00:00:00Z", + "Title": "Supporting Families Affected by Someone's Drinking", + "Sponsor": "Christian Allard MSP" + }, + { "ID": 93, "Date": "2015-11-11T00:00:00Z", "Title": "Remembrance Day Commemorations", "Sponsor": "SPCB" }, + { + "ID": 94, + "Date": "2015-11-11T00:00:00Z", + "Title": "RAMH 25th Anniversary of Service Provision", + "Sponsor": "George Adam MSP" + }, + { "ID": 95, "Date": "2015-11-12T00:00:00Z", "Title": "Get Ready for Winter", "Sponsor": "Stuart McMillan MSP" }, + { + "ID": 96, + "Date": "2015-11-12T00:00:00Z", + "Title": "Scotland's Outdoors - Our natural health service", + "Sponsor": "Malcolm Chisholm MSP" + }, + { + "ID": 97, + "Date": "2015-11-12T00:00:00Z", + "Title": "Anxiety & Depression in Families Affected by Substance Abuse", + "Sponsor": "John Mason MSP" + }, + { + "ID": 98, + "Date": "2015-11-16T00:00:00Z", + "Title": "SFF - Participative Budgeting", + "Sponsor": "Scottish Futures Forum" + }, + { + "ID": 99, + "Date": "2015-11-17T00:00:00Z", + "Title": "SCVO Annual Parliamentary Reception", + "Sponsor": "James Dornan MSP" + }, + { "ID": 100, "Date": "2015-11-17T00:00:00Z", "Title": "Pancreatic Cancer UK", "Sponsor": "Clare Adamson MSP" }, + { + "ID": 101, + "Date": "2015-11-17T00:00:00Z", + "Title": "Scotland United in prayer for Parliament", + "Sponsor": "Nigel Don MSP" + }, + { + "ID": 102, + "Date": "2015-11-17T00:00:00Z", + "Title": "Women in Property - Annual Review of the Scottish Planning System", + "Sponsor": "Jayne Baxter MSP" + }, + { + "ID": 103, + "Date": "2015-11-17T00:00:00Z", + "Title": "The Refugee Crisis: framing the Scottish Response", + "Sponsor": "John Mason MSP" + }, + { + "ID": 104, + "Date": "2015-11-18T00:00:00Z", + "Title": "Celebrate. Remember, Continue Celebrating 60 Years of Action for Children", + "Sponsor": "Anne McTaggart MSP" + }, + { + "ID": 105, + "Date": "2015-11-18T00:00:00Z", + "Title": "Scottish Parliamentary Maritime Reception", + "Sponsor": "Liam McArthur MSP" + }, + { "ID": 106, "Date": "2015-11-18T00:00:00Z", "Title": "My Lungs My Life", "Sponsor": "Nanette Milne MSP" }, + { + "ID": 107, + "Date": "2015-11-19T00:00:00Z", + "Title": "Experiences of Psychosis Film Showing", + "Sponsor": "Malcolm Chisholm MSP" + }, + { "ID": 108, "Date": "2015-11-19T00:00:00Z", "Title": "Road to Recovery?", "Sponsor": "Cara Hilton MSP" }, + { "ID": 109, "Date": "2015-11-19T00:00:00Z", "Title": "Carers Rights Day", "Sponsor": "Rhoda Grant MSP" }, + { + "ID": 110, + "Date": "2015-11-19T00:00:00Z", + "Title": "National Third Sector GIRFEC project: Getting children's services right for every child - how the third sector can help", + "Sponsor": "George Adam MSP" + }, + { + "ID": 111, + "Date": "2015-11-20T00:00:00Z", + "Title": "Marine Tourism Conference", + "Sponsor": "Stuart McMillan MSP" + }, + { + "ID": 112, + "Date": "2015-11-24T00:00:00Z", + "Title": "10 Years of Architecture & Design Scotland (A&DS)", + "Sponsor": "Patricia Ferguson MSP" + }, + { + "ID": 113, + "Date": "2015-11-24T00:00:00Z", + "Title": "Scottish Literature International lecture", + "Sponsor": "Jean Urquhart MSP" + }, + { + "ID": 114, + "Date": "2015-11-24T00:00:00Z", + "Title": "European HIV-Hepatitis Testing Week - HIV Scotland Reception", + "Sponsor": "Kevin Stewart MSP" + }, + { "ID": 115, "Date": "2015-11-24T00:00:00Z", "Title": "Shaw Trust Scotland", "Sponsor": "Michael McMahon MSP" }, + { + "ID": 116, + "Date": "2015-11-24T00:00:00Z", + "Title": "Delivering biodiversity through grouse moor management", + "Sponsor": "Graeme Dey MSP" + }, + { + "ID": 117, + "Date": "2015-11-25T00:00:00Z", + "Title": "National Gaelic Schools Debate and Cross Party Group on Gaelic's Annual Reception", + "Sponsor": "Angus MacDonald MSP" + }, + { "ID": 118, "Date": "2015-11-25T00:00:00Z", "Title": "HIE's 50th Anniversary", "Sponsor": "Dave Thompson MSP" }, + { + "ID": 119, + "Date": "2015-11-25T00:00:00Z", + "Title": "Scotland's Nuclear Sector & The Economy", + "Sponsor": "Iain Gray MSP" + }, + { + "ID": 120, + "Date": "2015-11-26T00:00:00Z", + "Title": "Implementing the 'Discards Ban' in Scotland", + "Sponsor": "Angus MacDonald MSP" + }, + { + "ID": 121, + "Date": "2015-11-26T00:00:00Z", + "Title": "PAS Parliamentary Reception", + "Sponsor": "Stuart McMillan MSP" + }, + { + "ID": 122, + "Date": "2015-11-26T00:00:00Z", + "Title": "Centenary Memorials Restoration Fund Reception", + "Sponsor": "Alex Salmond MSP" + }, + { + "ID": 123, + "Date": "2015-11-30T00:00:00Z", + "Title": "St Andrews Day Schools Debating Competition 2015", + "Sponsor": "SPCB" + }, + { + "ID": 124, + "Date": "2015-12-01T00:00:00Z", + "Title": "Penumbra 30 Years of Making a Positive Difference", + "Sponsor": "Mary Scanlon MSP" + }, + { + "ID": 125, + "Date": "2015-12-01T00:00:00Z", + "Title": "Promoting General Practice: RCGP Scotland's Manifesto for 2016", + "Sponsor": "Bob Doris MSP" + }, + { + "ID": 126, + "Date": "2015-12-01T00:00:00Z", + "Title": "Land Ecology: The Norwegian Experience", + "Sponsor": "Rob Gibson MSP" + }, + { + "ID": 127, + "Date": "2015-12-01T00:00:00Z", + "Title": "Moonwalk Supporting Vital Cancer Services", + "Sponsor": "Drew Smith MSP" + }, + { + "ID": 128, + "Date": "2015-12-02T00:00:00Z", + "Title": "Design in Action Business Showcase ", + "Sponsor": "Michael Russell MSP" + }, + { + "ID": 129, + "Date": "2015-12-02T00:00:00Z", + "Title": "Money Advice Scotland", + "Sponsor": "Deputy Presiding Officer John Scott MSP and Minister for Business, Energy and Tourism" + }, + { + "ID": 130, + "Date": "2015-12-02T00:00:00Z", + "Title": "Physiotherapy Works in Scotland", + "Sponsor": "Dennis Robertson MSP" + }, + { + "ID": 131, + "Date": "2015-12-02T00:00:00Z", + "Title": "In the pink? In the red? Or in between?", + "Sponsor": "Mark McDonald MSP" + }, + { + "ID": 132, + "Date": "2015-12-03T00:00:00Z", + "Title": "Care Opinion: Supporting the Citizen Voice", + "Sponsor": "Roderick Campbell MSP" + }, + { "ID": 133, "Date": "2015-12-03T00:00:00Z", "Title": "HiFest Showcase", "Sponsor": "Mike MacKenzie MSP " }, + { + "ID": 134, + "Date": "2015-12-03T00:00:00Z", + "Title": "Clydeside Action on Asbestos", + "Sponsor": "Stuart McMillan MSP" + }, + { + "ID": 135, + "Date": "2015-12-04T00:00:00Z", + "Title": "Young Voices on Preventing Sexual Violence", + "Sponsor": "Malcolm Chisholm MSP" + }, + { + "ID": 136, + "Date": "2015-12-07T00:00:00Z", + "Title": "Scottish Public Service Awards", + "Sponsor": "Presiding Officer and Cabinet Secretary for Fair Work, Skills and Training" + }, + { + "ID": 137, + "Date": "2015-12-08T00:00:00Z", + "Title": "Fields in Trust's 90th Anniversary", + "Sponsor": "Alison Johnstone MSP" + }, + { + "ID": 138, + "Date": "2015-12-08T00:00:00Z", + "Title": "The Vascular Health and Stroke Training Programme", + "Sponsor": "Duncan McNeil MSP" + }, + { "ID": 139, "Date": "2015-12-08T00:00:00Z", "Title": "CBI Scotland", "Sponsor": "Ruth Davidson MSP" }, + { + "ID": 140, + "Date": "2015-12-09T00:00:00Z", + "Title": "International Human Rights Day", + "Sponsor": "John Finnie MSP" + }, + { + "ID": 141, + "Date": "2015-12-09T00:00:00Z", + "Title": "SBATC Apprentice of the Year Awards 2015", + "Sponsor": "Nigel Don MSP" + }, + { + "ID": 142, + "Date": "2015-12-09T00:00:00Z", + "Title": "PRS for Music Creators Reception", + "Sponsor": "Deputy Presiding Officer and Cabinet Secretary for Culture, Europe and External Affairs" + }, + { + "ID": 143, + "Date": "2015-12-10T00:00:00Z", + "Title": "Scarf School Calendar Awards", + "Sponsor": "Mark McDonald MSP" + }, + { + "ID": 144, + "Date": "2015-12-10T00:00:00Z", + "Title": "Write to End Violence Against Women Awards", + "Sponsor": "Kezia Dugdale MSP" + }, + { "ID": 145, "Date": "2015-12-14T00:00:00Z", "Title": "Roots of Empathy", "Sponsor": "Dennis Robertson MSP" }, + { "ID": 146, "Date": "2015-12-15T00:00:00Z", "Title": "Selfhelp4stroke", "Sponsor": "Dennis Robertson MSP" }, + { "ID": 147, "Date": "2015-12-15T00:00:00Z", "Title": "Cystic Fibrosis Trust", "Sponsor": "Bob Doris MSP" }, + { + "ID": 148, + "Date": "2015-12-15T00:00:00Z", + "Title": "Scottish Health Action on Alcohol Problems-LGBT", + "Sponsor": "Jim Eadie MSP" + }, + { + "ID": 149, + "Date": "2015-12-16T00:00:00Z", + "Title": "Scottish Parliament Christmas Carol Service", + "Sponsor": "Presiding Officer" + }, + { "ID": 150, "Date": "2015-12-17T00:00:00Z", "Title": "Scotland Welcomes Refugees", "Sponsor": "Sandra White MSP" }, + { + "ID": 151, + "Date": "2015-12-17T00:00:00Z", + "Title": "MG ALBA - Vision Document LΓ¨irsinn 2021 ", + "Sponsor": "Angus MacDonald MSP" + }, + { "ID": 152, "Date": "2015-12-17T00:00:00Z", "Title": "Humanist Yuletide Lunch", "Sponsor": "Patrick Harvie MSP" }, + { + "ID": 153, + "Date": "2015-12-17T00:00:00Z", + "Title": "BBC Charter Renewal - Advanced preview of the Doctor Who Christmas Special", + "Sponsor": "Claire Baker MSP / George Adam MSP" + }, + { + "ID": 154, + "Date": "2016-01-07T00:00:00Z", + "Title": "A Football Manifesto - Scottish Football Supporters Association", + "Sponsor": "Alison Johnstone MSP" + }, + { "ID": 155, "Date": "2016-01-12T00:00:00Z", "Title": "Scottish Renewables 2016", "Sponsor": "Patrick Harvie MSP" }, + { + "ID": 156, + "Date": "2016-01-12T00:00:00Z", + "Title": "No one living in a hard-to-heat, draughty home by 2025", + "Sponsor": "Jim Eadie MSP" + }, + { + "ID": 157, + "Date": "2016-01-13T00:00:00Z", + "Title": "VisitScotland", + "Sponsor": "Deputy Presiding Officer Elaine Smith MSP and Minister for Business, Energy and Tourism Fergus Ewing MSP" + }, + { + "ID": 158, + "Date": "2016-01-13T00:00:00Z", + "Title": "Celebrating the Success of Supporting Young People", + "Sponsor": "Tavish Scott MSP" + }, + { "ID": 159, "Date": "2016-01-13T00:00:00Z", "Title": "IoF Scotland / OSCR Reception", "Sponsor": "Bill Kidd MSP" }, + { + "ID": 160, + "Date": "2016-01-14T00:00:00Z", + "Title": "Scottish Local Shop Report", + "Sponsor": "Gordon MacDonald MSP" + }, + { + "ID": 161, + "Date": "2016-01-14T00:00:00Z", + "Title": "Parliamentary Cancer Pledge ", + "Sponsor": "Jackson Carlaw MSP" + }, + { + "ID": 162, + "Date": "2016-01-14T00:00:00Z", + "Title": "The Financial Capability Strategy for Scotland", + "Sponsor": "John Wilson MSP" + }, + { + "ID": 163, + "Date": "2016-01-15T00:00:00Z", + "Title": "NUS: Women Lead the Way", + "Sponsor": "Alison Johnstone MSP" + }, + { + "ID": 164, + "Date": "2016-01-19T00:00:00Z", + "Title": "John Bellany and Scottish Women's Hospitals exhibition Preview Reception", + "Sponsor": "Presiding Officer " + }, + { + "ID": 165, + "Date": "2016-01-19T00:00:00Z", + "Title": "Celebrating James Watt 2015-19", + "Sponsor": "Angus MacDonald MSP" + }, + { "ID": 166, "Date": "2016-01-19T00:00:00Z", "Title": "SAMH", "Sponsor": "Bob Doris MSP" }, + { + "ID": 167, + "Date": "2016-01-19T00:00:00Z", + "Title": "Scotland's Trusts - A New Pill for Health", + "Sponsor": "Bruce Crawford MSP" + }, + { + "ID": 168, + "Date": "2016-01-19T00:00:00Z", + "Title": "Engineering trends, potential and challenges in Scotland", + "Sponsor": "Elaine Murray MSP" + }, + { + "ID": 169, + "Date": "2016-01-20T00:00:00Z", + "Title": "Consular Corps' Burns Supper", + "Sponsor": "Presiding Officer " + }, + { + "ID": 170, + "Date": "2016-01-21T00:00:00Z", + "Title": "A Deposit Return System for Scotland", + "Sponsor": "Angus MacDonald MSP" + }, + { + "ID": 171, + "Date": "2016-01-21T00:00:00Z", + "Title": "First Ministers Portrait Exhibition - Art Talk", + "Sponsor": "Angus MacDonald MSP" + }, + { + "ID": 172, + "Date": "2016-01-26T00:00:00Z", + "Title": "Quality Scotland Celebrating 25 Years of Excellence", + "Sponsor": "Richard Lyle MSP" + }, + { + "ID": 173, + "Date": "2016-01-26T00:00:00Z", + "Title": "Scottish Parliament Burns Club Supper", + "Sponsor": "Rob Gibson MSP" + }, + { "ID": 174, "Date": "2016-01-26T00:00:00Z", "Title": "Gathering the Voices ", "Sponsor": "Stewart Maxwell MSP" }, + { + "ID": 175, + "Date": "2016-01-26T00:00:00Z", + "Title": "Immigration: What’s the Story? – Show Racism the Red Card", + "Sponsor": "Alex Neil MSP" + }, + { + "ID": 176, + "Date": "2016-01-27T00:00:00Z", + "Title": "Active Kids: Briefing with Paralympics Gold Medallist Ellie Simmonds", + "Sponsor": "Linda Fabiani MSP" + }, + { "ID": 177, "Date": "2016-01-27T00:00:00Z", "Title": "Forestry in Scotland", "Sponsor": "Angus MacDonald MSP" }, + { + "ID": 178, + "Date": "2016-01-27T00:00:00Z", + "Title": "Essential Facts Regarding A&E Services in Scotland", + "Sponsor": "Fiona McLeod MSP" + }, + { + "ID": 179, + "Date": "2016-01-27T00:00:00Z", + "Title": "A campaign group for a Safe and Accountable Peoples NHS in Scotland (ASAP)", + "Sponsor": "Neil Findlay MSP" + }, + { + "ID": 180, + "Date": "2016-01-28T00:00:00Z", + "Title": "Calling Time on Nuisance Calls", + "Sponsor": "Graeme Dey MSP" + }, + { + "ID": 181, + "Date": "2016-01-28T00:00:00Z", + "Title": "Celebrate Organic Ambitions: Scotland's Organic Action Plan 2016-2020", + "Sponsor": "Angus McDonald MSP" + }, + { + "ID": 182, + "Date": "2016-01-28T00:00:00Z", + "Title": "100 years of the right to Contentiously Object", + "Sponsor": "Patrick Harvie MSP" + }, + { + "ID": 183, + "Date": "2016-02-02T00:00:00Z", + "Title": "Fraser of Allander Institute at the University of Strathclyde ", + "Sponsor": "Jackie Baillie MSP, Jackson Carlaw MSP, Patrick Harvie MSP, Willie Rennie MSP, John Swinney MSP " + }, + { + "ID": 184, + "Date": "2016-02-02T00:00:00Z", + "Title": "Scotland's Futures Forum and GGIS Annual Seminar", + "Sponsor": "Scotland's Future Forum" + }, + { + "ID": 185, + "Date": "2016-02-02T00:00:00Z", + "Title": "Zero Tolerance to Female Genital Mutilation ", + "Sponsor": "Margaret McCulloch MSP " + }, + { + "ID": 186, + "Date": "2016-02-02T00:00:00Z", + "Title": "Citizen and Consumer Interests in Communications ", + "Sponsor": "Bruce Crawford MSP" + }, + { + "ID": 187, + "Date": "2016-02-02T00:00:00Z", + "Title": "PCS Parliamentary Reception", + "Sponsor": "Neil Findlay MSP" + }, + { + "ID": 188, + "Date": "2016-02-03T00:00:00Z", + "Title": "Lloyds TSB Foundation for Scotland 30 Years of Supporting Scotland", + "Sponsor": "Presiding Officer & Deputy First Minister" + }, + { + "ID": 189, + "Date": "2016-02-03T00:00:00Z", + "Title": "Mobility as a Service: A New Reality", + "Sponsor": "Graeme Dey MSP" + }, + { + "ID": 190, + "Date": "2016-02-03T00:00:00Z", + "Title": "Music Therapy and Dementia: Enriching Life When It is Needed", + "Sponsor": "Tavish Scott MSP " + }, + { + "ID": 191, + "Date": "2016-02-03T00:00:00Z", + "Title": "Federation of Entertainment Unions Manifesto", + "Sponsor": "Claire Baker MSP" + }, + { + "ID": 192, + "Date": "2016-02-03T00:00:00Z", + "Title": "ACTSA Reception: Anti-Apartheid Movement", + "Sponsor": "Drew Smith MSP" + }, + { + "ID": 193, + "Date": "2016-02-04T00:00:00Z", + "Title": "Vattenfall – investing in Scottish onshore and offshore wind", + "Sponsor": "Dennis Robertson MSP" + }, + { + "ID": 194, + "Date": "2016-02-09T00:00:00Z", + "Title": "A Fairer and Healthier Scotland: the Housing Association Offer", + "Sponsor": "Jim Eadie MSP" + }, + { + "ID": 195, + "Date": "2016-02-09T00:00:00Z", + "Title": "Starting Again – a new life in Scotland", + "Sponsor": "Sandra White MSP" + }, + { "ID": 196, "Date": "2016-02-09T00:00:00Z", "Title": "More Than Just Money", "Sponsor": "Jenny Marra MSP" }, + { + "ID": 197, + "Date": "2016-02-09T00:00:00Z", + "Title": "Digital Scotland Superfast Broadband (DSSB) Briefing", + "Sponsor": "Stewart Stevenson MSP" + }, + { + "ID": 198, + "Date": "2016-02-09T00:00:00Z", + "Title": "Laudato Si’ and delivering climate change action in Scotland", + "Sponsor": "Siobhan McMahon MSP & Sarah Boyack MSP" + }, + { + "ID": 199, + "Date": "2016-02-10T00:00:00Z", + "Title": "Parkinson's UK - Get it on Time", + "Sponsor": "Dennis Robertson MSP" + }, + { + "ID": 200, + "Date": "2016-02-10T00:00:00Z", + "Title": "Celebrating diversities in Scotland - Polish Culture and Language", + "Sponsor": "Jean Urquhart MSP" + }, + { "ID": 201, "Date": "2016-02-10T00:00:00Z", "Title": "Blacklist", "Sponsor": "Elaine Smith MSP" }, + { + "ID": 202, + "Date": "2016-02-10T00:00:00Z", + "Title": "Hepatitis C – Scoping Exercise and Film Screening", + "Sponsor": "Malcolm Chisholm MSP" + }, + { + "ID": 203, + "Date": "2016-02-10T00:00:00Z", + "Title": "POVERTY: See It Change It- East Lothian", + "Sponsor": "Iain Gray MSP" + }, + { "ID": 204, "Date": "2016-02-11T00:00:00Z", "Title": "#ScotSpirit Photocall", "Sponsor": "Bruce Crawford MSP" }, + { + "ID": 205, + "Date": "2016-02-11T00:00:00Z", + "Title": "Edinburgh Festival Fringe Society", + "Sponsor": "Colin Keir MSP" + }, + { + "ID": 206, + "Date": "2016-02-11T00:00:00Z", + "Title": "Scotland’s UNESCO Global Geoparks ", + "Sponsor": "Jean Urquhart MSP" + }, + { "ID": 207, "Date": "2016-02-12T00:00:00Z", "Title": "Making Scotland a Credit Union Nation", "Sponsor": "SPCB" }, + { + "ID": 208, + "Date": "2016-02-23T00:00:00Z", + "Title": "No Young Person Left Behind", + "Sponsor": "George Adam MSP & Iain Gray MSP" + }, + { + "ID": 209, + "Date": "2016-02-23T00:00:00Z", + "Title": "Scottish Newspaper Society: The Effectiveness of Local Newspapers", + "Sponsor": "Alex Neil MSP" + }, + { + "ID": 210, + "Date": "2016-02-23T00:00:00Z", + "Title": "University of the Highlands and Islands", + "Sponsor": "Jean Urquhart MSP" + }, + { + "ID": 211, + "Date": "2016-02-23T00:00:00Z", + "Title": "Huts for Scotland: Introducing the new guidance", + "Sponsor": "Angus MacDonald MSP" + }, + { "ID": 212, "Date": "2016-02-24T00:00:00Z", "Title": "Scottish Environment Link", "Sponsor": "Rob Gibson MSP" }, + { + "ID": 213, + "Date": "2016-02-24T00:00:00Z", + "Title": "Podiatry and Prevention- Keeping Scotland on its Feet.", + "Sponsor": "Jim Hume MSP" + }, + { + "ID": 214, + "Date": "2016-02-24T00:00:00Z", + "Title": "What Would Keir Hardie say? ", + "Sponsor": "Neil Findlay MSP" + }, + { "ID": 215, "Date": "2016-02-25T00:00:00Z", "Title": "Shaping Landscapes", "Sponsor": "Liam McArthur MSP" }, + { "ID": 216, "Date": "2016-02-25T00:00:00Z", "Title": "CrossReach Drop-in", "Sponsor": "Jim Eadie MSP" }, + { + "ID": 217, + "Date": "2016-02-25T00:00:00Z", + "Title": "Ocean Youth Trust Scotland", + "Sponsor": "Stuart McMillan MSP" + }, + { + "ID": 218, + "Date": "2016-02-25T00:00:00Z", + "Title": "An Impact event on a public protection project", + "Sponsor": "Alex Johnstone MSP" + }, + { + "ID": 219, + "Date": "2016-02-25T00:00:00Z", + "Title": "Royal Highland Education Trust", + "Sponsor": "John Scott MSP" + }, + { + "ID": 220, + "Date": "2016-02-26T00:00:00Z", + "Title": "Scotland's Journey: Quality Eating Disorder Services", + "Sponsor": "Dennis Robertson MSP" + }, + { "ID": 221, "Date": "2016-02-29T00:00:00Z", "Title": "Learning for Democracy", "Sponsor": "Jean Urquhart MSP" }, + { "ID": 222, "Date": "2016-03-01T00:00:00Z", "Title": "Rare Disease Day 2016", "Sponsor": "Malcolm Chisholm MSP " }, + { + "ID": 223, + "Date": "2016-03-01T00:00:00Z", + "Title": "Moving beyond neonicotinoids ", + "Sponsor": "Graeme Dey MSP" + }, + { "ID": 224, "Date": "2016-03-01T00:00:00Z", "Title": "Scotland United in Prayer", "Sponsor": "Murdo Fraser MSP" }, + { "ID": 225, "Date": "2016-03-01T00:00:00Z", "Title": "Child Health and Wellbeing", "Sponsor": "Cara Hilton MSP" }, + { + "ID": 226, + "Date": "2016-03-02T00:00:00Z", + "Title": "EU Integration from a Scottish Shia Perspective", + "Sponsor": "Bill Kidd MSP " + }, + { + "ID": 227, + "Date": "2016-03-02T00:00:00Z", + "Title": "Borders Forest Trust 20th Anniversary ", + "Sponsor": "Jim Hume MSP " + }, + { "ID": 228, "Date": "2016-03-02T00:00:00Z", "Title": "Sue Ryder ", "Sponsor": "Christian Allard MSP" }, + { + "ID": 229, + "Date": "2016-03-02T00:00:00Z", + "Title": "The Brain Tumour Charity", + "Sponsor": "Cameron Buchanan MSP" + }, + { + "ID": 230, + "Date": "2016-03-03T00:00:00Z", + "Title": "Scotland’s outdoors for health & wellbeing", + "Sponsor": "Alison Johnstone MSP" + }, + { + "ID": 231, + "Date": "2016-03-03T00:00:00Z", + "Title": "Improving Safety Standards in the Scottish Prison Sector", + "Sponsor": "Graeme Pearson MSP" + }, + { + "ID": 232, + "Date": "2016-03-09T00:00:00Z", + "Title": "Marie Curie Great Daffadil Appeal 2016", + "Sponsor": "Linda Fabiani MSP " + }, + { + "ID": 233, + "Date": "2016-03-09T00:00:00Z", + "Title": "Epilepsy Services in Scotland: A Blue Print for Success", + "Sponsor": "Kenneth Gibson MSP" + }, + { + "ID": 234, + "Date": "2016-03-09T00:00:00Z", + "Title": "Supporting Scotland’s Heritage", + "Sponsor": "Jamie McGrigor MSP " + }, + { + "ID": 235, + "Date": "2016-03-09T00:00:00Z", + "Title": "The contribution of e-cigarettes to individual and public health", + "Sponsor": "Mike MacKenzie MSP" + }, + { + "ID": 236, + "Date": "2016-03-10T00:00:00Z", + "Title": "In-Work Poverty and Enterprise: Self-employment and Business Ownership as Contexts of Poverty", + "Sponsor": "Joan McAlpine MSP " + }, + { + "ID": 237, + "Date": "2016-03-10T00:00:00Z", + "Title": "40 Years of Scottish Women’s Aid Choir Performance", + "Sponsor": "Malcolm Chisholm MSP/Christina McKelvie MSP" + }, + { + "ID": 238, + "Date": "2016-03-10T00:00:00Z", + "Title": "Banking for the Common Good", + "Sponsor": "Lesley Brennan MSP" + }, + { + "ID": 239, + "Date": "2016-03-10T00:00:00Z", + "Title": "StepChange Debt Charity Scotland: Scotland in the Red", + "Sponsor": "James Dornan MSP" + }, + { + "ID": 240, + "Date": "2016-03-10T00:00:00Z", + "Title": "The UK wide report on Depression and Employment", + "Sponsor": "Malcolm Chisholm MSP" + }, + { "ID": 241, "Date": "2016-03-15T00:00:00Z", "Title": "Cancer Research UK", "Sponsor": "Malcolm Chisholm MSP" }, + { + "ID": 242, + "Date": "2016-03-15T00:00:00Z", + "Title": "Celebrating Food for Thought ", + "Sponsor": "Rob Gibson MSP" + }, + { + "ID": 243, + "Date": "2016-03-15T00:00:00Z", + "Title": "Lions Clubs International UN Day", + "Sponsor": "Alex Fergusson MSP" + }, + { + "ID": 244, + "Date": "2016-03-15T00:00:00Z", + "Title": "Tackling homelessness in Scotland", + "Sponsor": "Gordon MacDonald MSP " + }, + { + "ID": 245, + "Date": "2016-03-16T00:00:00Z", + "Title": "A Charter for Trees, Woods and People", + "Sponsor": "Claudia Beamish MSP " + }, + { "ID": 246, "Date": "2016-03-16T00:00:00Z", "Title": "Hibs Community Foundation", "Sponsor": "Kezia Dugdale MSP" }, + { "ID": 247, "Date": "2016-03-17T00:00:00Z", "Title": "Green/Blue infrastructure ", "Sponsor": "Chic Brodie MSP" }, + { + "ID": 248, + "Date": "2016-03-17T00:00:00Z", + "Title": "Skills & Training in Scotch Whisky Industry", + "Sponsor": "Gordon MacDonald MSP " + }, + { + "ID": 249, + "Date": "2016-03-17T00:00:00Z", + "Title": "Industrial Evolution Report ", + "Sponsor": "Kenneth Gibson MSP" + }, + { + "ID": 250, + "Date": "2016-03-17T00:00:00Z", + "Title": "UN Global Goals: Bangladesh & Scotland Cooperation", + "Sponsor": "Sarah Boyack MSP" + }, + { + "ID": 251, + "Date": "2016-03-17T00:00:00Z", + "Title": "Intersex Equality & Human Rights ", + "Sponsor": "Margaret McCulloch MSP" + }, + { + "ID": 252, + "Date": "2016-03-21T00:00:00Z", + "Title": "Our Films: Our Europe Premiere and Awards Ceremony", + "Sponsor": "Christina McKelvie MSP" + }, + { "ID": 253, "Date": "2016-03-22T00:00:00Z", "Title": "Spark 50th Anniversary ", "Sponsor": "Fiona McLeod MSP " }, + { + "ID": 254, + "Date": "2016-03-22T00:00:00Z", + "Title": "Scottish Young Consumer of the Year Final 2016", + "Sponsor": "Dave Thompson MSP" + }, + { + "ID": 255, + "Date": "2016-03-22T00:00:00Z", + "Title": "Family Group Conferencing -The Child At The Centre", + "Sponsor": "Mark MacDonald MSP" + }, + { "ID": 256, "Date": "2016-03-22T00:00:00Z", "Title": "Diabetes in Scotland ", "Sponsor": "Dennis Robertson MSP" }, + { + "ID": 257, + "Date": "2016-03-23T00:00:00Z", + "Title": "Patient Charter on Access to Medicines in Scotland", + "Sponsor": "Malcolm Chisholm MSP" + }, + { "ID": 258, "Date": "2016-03-23T00:00:00Z", "Title": "Every Picture Tells a Story", "Sponsor": "Jim Eadie MSP" }, + { + "ID": 259, + "Date": "2016-03-23T00:00:00Z", + "Title": "Celebrating 10 Years of Smoke-Free Indoor Public Places", + "Sponsor": "Stewart Maxwell MSP" + }, + { + "ID": 260, + "Date": "2016-05-25T00:00:00Z", + "Title": "European Heart Network Annual Conference 2016", + "Sponsor": "Andy Wightman MSP " + }, + { + "ID": 261, + "Date": "2016-06-02T00:00:00Z", + "Title": "Photocall - Volunteers' Week ", + "Sponsor": "Bruce Crawford MSP" + }, + { "ID": 262, "Date": "2016-06-07T00:00:00Z", "Title": "The Headmasters' Conference", "Sponsor": "Liz Smith MSP" }, + { "ID": 263, "Date": "2016-06-07T00:00:00Z", "Title": "Should GM be on the table?", "Sponsor": "Iain Gray MSP" }, + { + "ID": 264, + "Date": "2016-06-08T00:00:00Z", + "Title": "Social security in Scotland: A manifesto for change", + "Sponsor": "Patrick Harvie MSP" + }, + { "ID": 265, "Date": "2016-06-16T00:00:00Z", "Title": "Neurological care", "Sponsor": "Mark McDonald MSP" }, + { + "ID": 266, + "Date": "2016-06-16T00:00:00Z", + "Title": "Looking Forward Not Back National Symposium", + "Sponsor": "Christina McKelvie MSP / Alison Harris MSP" + }, + { + "ID": 267, + "Date": "2016-06-28T00:00:00Z", + "Title": "International Cricket Council Annual Conference 2016", + "Sponsor": "Deputy Presiding Officer Linda Fabiani MSP and Minister for Public Health and Sport Aileen Campbell MSP" + }, + { + "ID": 268, + "Date": "2016-06-28T00:00:00Z", + "Title": "Scottish IBD Delivery Plan", + "Sponsor": "Clare Adamson MSP" + }, + { "ID": 269, "Date": "2016-06-28T00:00:00Z", "Title": "BBC Scotland Charter", "Sponsor": "George Adam MSP " }, + { "ID": 270, "Date": "2016-06-28T00:00:00Z", "Title": "CAMRA", "Sponsor": "Patrick Harvie MSP" }, + { + "ID": 271, + "Date": "2016-06-28T00:00:00Z", + "Title": "Inverness Airport to Heathrow Airport Service", + "Sponsor": "Maree Todd MSP" + }, + { + "ID": 272, + "Date": "2016-06-29T00:00:00Z", + "Title": "Holyrood Magazine and Coca-Cola Summer Drinks", + "Sponsor": "Linda Fabiani MSP" + }, + { + "ID": 273, + "Date": "2016-06-29T00:00:00Z", + "Title": "Scottish Introduction to The Parliament Project", + "Sponsor": "Willie Rennie MSP" + }, + { "ID": 274, "Date": "2016-06-29T00:00:00Z", "Title": "Addition Workers Graduation", "Sponsor": "John Finnie MSP" }, + { "ID": 275, "Date": "2016-06-30T00:00:00Z", "Title": "No Patient Left Behind", "Sponsor": "Gillian Martin MSP" }, + { + "ID": 276, + "Date": "2016-06-30T00:00:00Z", + "Title": "Snare-free Scotland information and photocall drop-in event", + "Sponsor": "Mark Ruskell MSP" + }, + { + "ID": 277, + "Date": "2016-06-30T00:00:00Z", + "Title": "Scottish PEN event for Raid Badawi", + "Sponsor": "Michael Russell MSP" + } +] diff --git a/test/inputs/json/misc/5f7fe.json b/test/inputs/json/misc/5f7fe.json index 852506b47..fe39712d6 100644 --- a/test/inputs/json/misc/5f7fe.json +++ b/test/inputs/json/misc/5f7fe.json @@ -1,2053 +1,22780 @@ { - "meta" : { - "view" : { - "id" : "5xaw-6ayf", - "name" : "Lottery Mega Millions Winning Numbers: Beginning 2002", - "attribution" : "New York State Gaming Commission", - "attributionLink" : "http://nylottery.ny.gov/wps/portal/Home/Lottery/home/your+lottery/drawing+results/drawingresultsmega", - "averageRating" : 0, - "category" : "Government & Finance", - "createdAt" : 1362492565, - "description" : "Go to http://on.ny.gov/1J8tPSN on the New York Lottery website for past Mega Millions results and payouts.", - "displayType" : "table", - "downloadCount" : 44849, - "hideFromCatalog" : false, - "hideFromDataJson" : false, - "indexUpdatedAt" : 1501322618, - "locale" : "", - "newBackend" : false, - "numberOfComments" : 0, - "oid" : 26482418, - "provenance" : "official", - "publicationAppendEnabled" : false, - "publicationDate" : 1501322465, - "publicationGroup" : 714877, - "publicationStage" : "published", - "rowsUpdatedAt" : 1501322464, - "rowsUpdatedBy" : "xzik-pf59", - "tableId" : 14361925, - "totalTimesRated" : 0, - "viewCount" : 337494, - "viewLastModified" : 1501322465, - "viewType" : "tabular", - "columns" : [ { - "id" : -1, - "name" : "sid", - "dataTypeName" : "meta_data", - "fieldName" : ":sid", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "id", - "dataTypeName" : "meta_data", - "fieldName" : ":id", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "position", - "dataTypeName" : "meta_data", - "fieldName" : ":position", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "created_at", - "dataTypeName" : "meta_data", - "fieldName" : ":created_at", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "created_meta", - "dataTypeName" : "meta_data", - "fieldName" : ":created_meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "updated_at", - "dataTypeName" : "meta_data", - "fieldName" : ":updated_at", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "updated_meta", - "dataTypeName" : "meta_data", - "fieldName" : ":updated_meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "meta", - "dataTypeName" : "meta_data", - "fieldName" : ":meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : 313393711, - "name" : "Draw Date", - "dataTypeName" : "calendar_date", - "fieldName" : "draw_date", - "position" : 1, - "renderTypeName" : "calendar_date", - "tableColumnId" : 8368515, - "width" : 140, - "cachedContents" : { - "largest" : "2017-07-28T00:00:00", - "non_null" : 1584, - "null" : 0, - "top" : [ { - "item" : "2017-05-02T00:00:00", - "count" : 20 - }, { - "item" : "2017-05-05T00:00:00", - "count" : 19 - }, { - "item" : "2017-05-09T00:00:00", - "count" : 18 - }, { - "item" : "2017-05-12T00:00:00", - "count" : 17 - }, { - "item" : "2017-05-16T00:00:00", - "count" : 16 - }, { - "item" : "2017-05-19T00:00:00", - "count" : 15 - }, { - "item" : "2017-05-23T00:00:00", - "count" : 14 - }, { - "item" : "2017-05-26T00:00:00", - "count" : 13 - }, { - "item" : "2017-05-30T00:00:00", - "count" : 12 - }, { - "item" : "2017-06-02T00:00:00", - "count" : 11 - }, { - "item" : "2017-06-06T00:00:00", - "count" : 10 - }, { - "item" : "2017-06-09T00:00:00", - "count" : 9 - }, { - "item" : "2017-06-13T00:00:00", - "count" : 8 - }, { - "item" : "2017-06-16T00:00:00", - "count" : 7 - }, { - "item" : "2017-06-20T00:00:00", - "count" : 6 - }, { - "item" : "2017-06-23T00:00:00", - "count" : 5 - }, { - "item" : "2017-06-27T00:00:00", - "count" : 4 - }, { - "item" : "2017-06-30T00:00:00", - "count" : 3 - }, { - "item" : "2017-07-04T00:00:00", - "count" : 2 - }, { - "item" : "2017-07-07T00:00:00", - "count" : 1 - } ], - "smallest" : "2002-05-17T00:00:00" - }, - "format" : { - "view" : "date", - "align" : "center" + "meta": { + "view": { + "id": "5xaw-6ayf", + "name": "Lottery Mega Millions Winning Numbers: Beginning 2002", + "attribution": "New York State Gaming Commission", + "attributionLink": "http://nylottery.ny.gov/wps/portal/Home/Lottery/home/your+lottery/drawing+results/drawingresultsmega", + "averageRating": 0, + "category": "Government & Finance", + "createdAt": 1362492565, + "description": "Go to http://on.ny.gov/1J8tPSN on the New York Lottery website for past Mega Millions results and payouts.", + "displayType": "table", + "downloadCount": 44849, + "hideFromCatalog": false, + "hideFromDataJson": false, + "indexUpdatedAt": 1501322618, + "locale": "", + "newBackend": false, + "numberOfComments": 0, + "oid": 26482418, + "provenance": "official", + "publicationAppendEnabled": false, + "publicationDate": 1501322465, + "publicationGroup": 714877, + "publicationStage": "published", + "rowsUpdatedAt": 1501322464, + "rowsUpdatedBy": "xzik-pf59", + "tableId": 14361925, + "totalTimesRated": 0, + "viewCount": 337494, + "viewLastModified": 1501322465, + "viewType": "tabular", + "columns": [ + { + "id": -1, + "name": "sid", + "dataTypeName": "meta_data", + "fieldName": ":sid", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "id", + "dataTypeName": "meta_data", + "fieldName": ":id", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "position", + "dataTypeName": "meta_data", + "fieldName": ":position", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "created_at", + "dataTypeName": "meta_data", + "fieldName": ":created_at", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "created_meta", + "dataTypeName": "meta_data", + "fieldName": ":created_meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "updated_at", + "dataTypeName": "meta_data", + "fieldName": ":updated_at", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "updated_meta", + "dataTypeName": "meta_data", + "fieldName": ":updated_meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "meta", + "dataTypeName": "meta_data", + "fieldName": ":meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": 313393711, + "name": "Draw Date", + "dataTypeName": "calendar_date", + "fieldName": "draw_date", + "position": 1, + "renderTypeName": "calendar_date", + "tableColumnId": 8368515, + "width": 140, + "cachedContents": { + "largest": "2017-07-28T00:00:00Z", + "non_null": 1584, + "null": 0, + "top": [ + { + "item": "2017-05-02T00:00:00Z", + "count": 20 + }, + { + "item": "2017-05-05T00:00:00Z", + "count": 19 + }, + { + "item": "2017-05-09T00:00:00Z", + "count": 18 + }, + { + "item": "2017-05-12T00:00:00Z", + "count": 17 + }, + { + "item": "2017-05-16T00:00:00Z", + "count": 16 + }, + { + "item": "2017-05-19T00:00:00Z", + "count": 15 + }, + { + "item": "2017-05-23T00:00:00Z", + "count": 14 + }, + { + "item": "2017-05-26T00:00:00Z", + "count": 13 + }, + { + "item": "2017-05-30T00:00:00Z", + "count": 12 + }, + { + "item": "2017-06-02T00:00:00Z", + "count": 11 + }, + { + "item": "2017-06-06T00:00:00Z", + "count": 10 + }, + { + "item": "2017-06-09T00:00:00Z", + "count": 9 + }, + { + "item": "2017-06-13T00:00:00Z", + "count": 8 + }, + { + "item": "2017-06-16T00:00:00Z", + "count": 7 + }, + { + "item": "2017-06-20T00:00:00Z", + "count": 6 + }, + { + "item": "2017-06-23T00:00:00Z", + "count": 5 + }, + { + "item": "2017-06-27T00:00:00Z", + "count": 4 + }, + { + "item": "2017-06-30T00:00:00Z", + "count": 3 + }, + { + "item": "2017-07-04T00:00:00Z", + "count": 2 + }, + { + "item": "2017-07-07T00:00:00Z", + "count": 1 + } + ], + "smallest": "2002-05-17T00:00:00Z" + }, + "format": { + "view": "date", + "align": "center" + } + }, + { + "id": 313393712, + "name": "Winning Numbers", + "dataTypeName": "text", + "fieldName": "winning_numbers", + "position": 2, + "renderTypeName": "text", + "tableColumnId": 8368516, + "width": 182, + "cachedContents": { + "largest": "46 48 53 61 74", + "non_null": 1584, + "null": 0, + "top": [ + { + "item": "05 14 42 43 58", + "count": 20 + }, + { + "item": "04 23 33 47 53", + "count": 19 + }, + { + "item": "06 29 45 69 73", + "count": 18 + }, + { + "item": "28 34 41 42 47", + "count": 17 + }, + { + "item": "04 35 39 56 72", + "count": 16 + }, + { + "item": "01 04 05 24 30", + "count": 15 + }, + { + "item": "06 13 17 33 60", + "count": 14 + }, + { + "item": "25 26 28 37 56", + "count": 13 + }, + { + "item": "05 20 32 37 67", + "count": 12 + }, + { + "item": "07 42 57 69 72", + "count": 11 + }, + { + "item": "03 05 16 49 75", + "count": 10 + }, + { + "item": "03 16 28 33 37", + "count": 9 + }, + { + "item": "27 51 62 68 75", + "count": 8 + }, + { + "item": "18 22 26 30 44", + "count": 7 + }, + { + "item": "02 15 41 49 63", + "count": 6 + }, + { + "item": "12 20 53 66 74", + "count": 5 + }, + { + "item": "04 21 45 52 57", + "count": 4 + }, + { + "item": "10 38 51 55 64", + "count": 3 + }, + { + "item": "16 39 47 53 71", + "count": 2 + }, + { + "item": "02 09 11 28 60", + "count": 1 + } + ], + "smallest": "01 02 03 12 37" + }, + "format": { + "align": "center" + } + }, + { + "id": 313393713, + "name": "Mega Ball", + "dataTypeName": "text", + "fieldName": "mega_ball", + "position": 3, + "renderTypeName": "text", + "tableColumnId": 8368517, + "width": 138, + "cachedContents": { + "largest": "52", + "non_null": 1584, + "null": 0, + "top": [ + { + "item": "21", + "count": 20 + }, + { + "item": "34", + "count": 19 + }, + { + "item": "03", + "count": 18 + }, + { + "item": "10", + "count": 17 + }, + { + "item": "13", + "count": 16 + }, + { + "item": "36", + "count": 15 + }, + { + "item": "07", + "count": 14 + }, + { + "item": "42", + "count": 13 + }, + { + "item": "09", + "count": 12 + }, + { + "item": "35", + "count": 11 + }, + { + "item": "06", + "count": 10 + }, + { + "item": "25", + "count": 9 + }, + { + "item": "38", + "count": 8 + }, + { + "item": "02", + "count": 7 + }, + { + "item": "44", + "count": 6 + }, + { + "item": "26", + "count": 5 + }, + { + "item": "29", + "count": 4 + }, + { + "item": "19", + "count": 3 + }, + { + "item": "24", + "count": 2 + }, + { + "item": "08", + "count": 1 + } + ], + "smallest": "01" + }, + "format": { + "align": "center" + } + }, + { + "id": 313393714, + "name": "Multiplier", + "dataTypeName": "text", + "fieldName": "multiplier", + "position": 4, + "renderTypeName": "text", + "tableColumnId": 8368518, + "width": 131, + "cachedContents": { + "largest": "05", + "non_null": 681, + "null": 903, + "top": [ + { + "item": "04", + "count": 20 + }, + { + "item": "02", + "count": 19 + }, + { + "item": "03", + "count": 18 + }, + { + "item": "05", + "count": 17 + } + ], + "smallest": "02" + }, + "format": { + "align": "center" + } + } + ], + "grants": [ + { + "inherited": false, + "type": "viewer", + "flags": ["public"] + } + ], + "metadata": { + "custom_fields": { + "Notes": { + "Notes": "The information contained on these pages is believed to be accurate. In the event of a discrepancy between the information displayed on this Web site concerning winning numbers and payouts and the information contained in the official and certified files maintained by the New York Lottery's Drawing Unit, those maintained by the Drawing Unit shall prevail." + }, + "Common Core": { + "Contact Email": "opendata@its.ny.gov", + "Publisher": "State of New York", + "Contact Name": "Open Data NY" + }, + "Dataset Summary": { + "Granularity": "Draw Date", + "Coverage": "Statewide", + "Posting Frequency": "Twice weekly", + "Data Frequency": "Twice weekly", + "Units": "Drawings Unit", + "Dataset Owner": "Lottery", + "Organization": "The New York Lottery", + "Time Period": "05/17/2002 to present", + "Contact Information": "Info@gaming.ny.gov" + }, + "Additional Resources": { + "See Also ": "http://www.megamillions.com/", + "See Also": "http://www.gaming.ny.gov/" + }, + "Dataset Information": { + "Agency": "Gaming Commission, New York State" + } + }, + "renderTypeConfig": { + "visible": { + "table": true + } + }, + "availableDisplayTypes": ["table", "fatrow", "page"], + "jsonQuery": { + "order": [ + { + "ascending": false, + "columnFieldName": "draw_date" + } + ] + }, + "rdfSubject": "0", + "attachments": [ + { + "blobId": "43B923D1-44E4-4220-96F1-D87BCE113E07", + "assetId": "", + "name": "NYSGAM_Mega_Overview.pdf", + "filename": "NYSGAM_Mega_Overview.pdf" + }, + { + "blobId": "BDC2731B-4B54-447D-B1AB-1091E5E5B24E", + "assetId": "", + "name": "NYSGAM_Mega_Winning_Numbers_DataDictionary.pdf", + "filename": "NYSGAM_Mega_Winning_Numbers_DataDictionary.pdf" + } + ] + }, + "owner": { + "id": "xzik-pf59", + "displayName": "NY Open Data", + "profileImageUrlLarge": "/api/users/xzik-pf59/profile_images/LARGE", + "profileImageUrlMedium": "/api/users/xzik-pf59/profile_images/THUMB", + "profileImageUrlSmall": "/api/users/xzik-pf59/profile_images/TINY", + "roleName": "publisher", + "screenName": "NY Open Data", + "rights": [ + "create_datasets", + "edit_others_datasets", + "edit_nominations", + "approve_nominations", + "moderate_comments", + "manage_stories", + "feature_items", + "change_configurations", + "view_domain", + "view_others_datasets", + "create_pages", + "edit_pages", + "view_goals", + "view_dashboards", + "edit_goals", + "edit_dashboards", + "manage_provenance", + "view_story", + "view_unpublished_story", + "view_all_dataset_status_logs", + "use_data_connectors" + ] + }, + "query": { + "orderBys": [ + { + "ascending": false, + "expression": { + "columnId": 313393711, + "type": "column" + } + } + ] + }, + "rights": ["read"], + "tableAuthor": { + "id": "xzik-pf59", + "displayName": "NY Open Data", + "profileImageUrlLarge": "/api/users/xzik-pf59/profile_images/LARGE", + "profileImageUrlMedium": "/api/users/xzik-pf59/profile_images/THUMB", + "profileImageUrlSmall": "/api/users/xzik-pf59/profile_images/TINY", + "roleName": "publisher", + "screenName": "NY Open Data", + "rights": [ + "create_datasets", + "edit_others_datasets", + "edit_nominations", + "approve_nominations", + "moderate_comments", + "manage_stories", + "feature_items", + "change_configurations", + "view_domain", + "view_others_datasets", + "create_pages", + "edit_pages", + "view_goals", + "view_dashboards", + "edit_goals", + "edit_dashboards", + "manage_provenance", + "view_story", + "view_unpublished_story", + "view_all_dataset_status_logs", + "use_data_connectors" + ] + }, + "tags": ["mega millions", "new york lottery", "winning", "results"], + "flags": ["default", "restorable", "restorePossibleForType"] } - }, { - "id" : 313393712, - "name" : "Winning Numbers", - "dataTypeName" : "text", - "fieldName" : "winning_numbers", - "position" : 2, - "renderTypeName" : "text", - "tableColumnId" : 8368516, - "width" : 182, - "cachedContents" : { - "largest" : "46 48 53 61 74", - "non_null" : 1584, - "null" : 0, - "top" : [ { - "item" : "05 14 42 43 58", - "count" : 20 - }, { - "item" : "04 23 33 47 53", - "count" : 19 - }, { - "item" : "06 29 45 69 73", - "count" : 18 - }, { - "item" : "28 34 41 42 47", - "count" : 17 - }, { - "item" : "04 35 39 56 72", - "count" : 16 - }, { - "item" : "01 04 05 24 30", - "count" : 15 - }, { - "item" : "06 13 17 33 60", - "count" : 14 - }, { - "item" : "25 26 28 37 56", - "count" : 13 - }, { - "item" : "05 20 32 37 67", - "count" : 12 - }, { - "item" : "07 42 57 69 72", - "count" : 11 - }, { - "item" : "03 05 16 49 75", - "count" : 10 - }, { - "item" : "03 16 28 33 37", - "count" : 9 - }, { - "item" : "27 51 62 68 75", - "count" : 8 - }, { - "item" : "18 22 26 30 44", - "count" : 7 - }, { - "item" : "02 15 41 49 63", - "count" : 6 - }, { - "item" : "12 20 53 66 74", - "count" : 5 - }, { - "item" : "04 21 45 52 57", - "count" : 4 - }, { - "item" : "10 38 51 55 64", - "count" : 3 - }, { - "item" : "16 39 47 53 71", - "count" : 2 - }, { - "item" : "02 09 11 28 60", - "count" : 1 - } ], - "smallest" : "01 02 03 12 37" - }, - "format" : { - "align" : "center" - } - }, { - "id" : 313393713, - "name" : "Mega Ball", - "dataTypeName" : "text", - "fieldName" : "mega_ball", - "position" : 3, - "renderTypeName" : "text", - "tableColumnId" : 8368517, - "width" : 138, - "cachedContents" : { - "largest" : "52", - "non_null" : 1584, - "null" : 0, - "top" : [ { - "item" : "21", - "count" : 20 - }, { - "item" : "34", - "count" : 19 - }, { - "item" : "03", - "count" : 18 - }, { - "item" : "10", - "count" : 17 - }, { - "item" : "13", - "count" : 16 - }, { - "item" : "36", - "count" : 15 - }, { - "item" : "07", - "count" : 14 - }, { - "item" : "42", - "count" : 13 - }, { - "item" : "09", - "count" : 12 - }, { - "item" : "35", - "count" : 11 - }, { - "item" : "06", - "count" : 10 - }, { - "item" : "25", - "count" : 9 - }, { - "item" : "38", - "count" : 8 - }, { - "item" : "02", - "count" : 7 - }, { - "item" : "44", - "count" : 6 - }, { - "item" : "26", - "count" : 5 - }, { - "item" : "29", - "count" : 4 - }, { - "item" : "19", - "count" : 3 - }, { - "item" : "24", - "count" : 2 - }, { - "item" : "08", - "count" : 1 - } ], - "smallest" : "01" - }, - "format" : { - "align" : "center" - } - }, { - "id" : 313393714, - "name" : "Multiplier", - "dataTypeName" : "text", - "fieldName" : "multiplier", - "position" : 4, - "renderTypeName" : "text", - "tableColumnId" : 8368518, - "width" : 131, - "cachedContents" : { - "largest" : "05", - "non_null" : 681, - "null" : 903, - "top" : [ { - "item" : "04", - "count" : 20 - }, { - "item" : "02", - "count" : 19 - }, { - "item" : "03", - "count" : 18 - }, { - "item" : "05", - "count" : 17 - } ], - "smallest" : "02" - }, - "format" : { - "align" : "center" - } - } ], - "grants" : [ { - "inherited" : false, - "type" : "viewer", - "flags" : [ "public" ] - } ], - "metadata" : { - "custom_fields" : { - "Notes" : { - "Notes" : "The information contained on these pages is believed to be accurate. In the event of a discrepancy between the information displayed on this Web site concerning winning numbers and payouts and the information contained in the official and certified files maintained by the New York Lottery's Drawing Unit, those maintained by the Drawing Unit shall prevail." - }, - "Common Core" : { - "Contact Email" : "opendata@its.ny.gov", - "Publisher" : "State of New York", - "Contact Name" : "Open Data NY" - }, - "Dataset Summary" : { - "Granularity" : "Draw Date", - "Coverage" : "Statewide", - "Posting Frequency" : "Twice weekly", - "Data Frequency" : "Twice weekly", - "Units" : "Drawings Unit", - "Dataset Owner" : "Lottery", - "Organization" : "The New York Lottery", - "Time Period" : "05/17/2002 to present", - "Contact Information" : "Info@gaming.ny.gov" - }, - "Additional Resources" : { - "See Also " : "http://www.megamillions.com/", - "See Also" : "http://www.gaming.ny.gov/" - }, - "Dataset Information" : { - "Agency" : "Gaming Commission, New York State" - } - }, - "renderTypeConfig" : { - "visible" : { - "table" : true - } - }, - "availableDisplayTypes" : [ "table", "fatrow", "page" ], - "jsonQuery" : { - "order" : [ { - "ascending" : false, - "columnFieldName" : "draw_date" - } ] - }, - "rdfSubject" : "0", - "attachments" : [ { - "blobId" : "43B923D1-44E4-4220-96F1-D87BCE113E07", - "assetId" : "", - "name" : "NYSGAM_Mega_Overview.pdf", - "filename" : "NYSGAM_Mega_Overview.pdf" - }, { - "blobId" : "BDC2731B-4B54-447D-B1AB-1091E5E5B24E", - "assetId" : "", - "name" : "NYSGAM_Mega_Winning_Numbers_DataDictionary.pdf", - "filename" : "NYSGAM_Mega_Winning_Numbers_DataDictionary.pdf" - } ] - }, - "owner" : { - "id" : "xzik-pf59", - "displayName" : "NY Open Data", - "profileImageUrlLarge" : "/api/users/xzik-pf59/profile_images/LARGE", - "profileImageUrlMedium" : "/api/users/xzik-pf59/profile_images/THUMB", - "profileImageUrlSmall" : "/api/users/xzik-pf59/profile_images/TINY", - "roleName" : "publisher", - "screenName" : "NY Open Data", - "rights" : [ "create_datasets", "edit_others_datasets", "edit_nominations", "approve_nominations", "moderate_comments", "manage_stories", "feature_items", "change_configurations", "view_domain", "view_others_datasets", "create_pages", "edit_pages", "view_goals", "view_dashboards", "edit_goals", "edit_dashboards", "manage_provenance", "view_story", "view_unpublished_story", "view_all_dataset_status_logs", "use_data_connectors" ] - }, - "query" : { - "orderBys" : [ { - "ascending" : false, - "expression" : { - "columnId" : 313393711, - "type" : "column" - } - } ] - }, - "rights" : [ "read" ], - "tableAuthor" : { - "id" : "xzik-pf59", - "displayName" : "NY Open Data", - "profileImageUrlLarge" : "/api/users/xzik-pf59/profile_images/LARGE", - "profileImageUrlMedium" : "/api/users/xzik-pf59/profile_images/THUMB", - "profileImageUrlSmall" : "/api/users/xzik-pf59/profile_images/TINY", - "roleName" : "publisher", - "screenName" : "NY Open Data", - "rights" : [ "create_datasets", "edit_others_datasets", "edit_nominations", "approve_nominations", "moderate_comments", "manage_stories", "feature_items", "change_configurations", "view_domain", "view_others_datasets", "create_pages", "edit_pages", "view_goals", "view_dashboards", "edit_goals", "edit_dashboards", "manage_provenance", "view_story", "view_unpublished_story", "view_all_dataset_status_logs", "use_data_connectors" ] - }, - "tags" : [ "mega millions", "new york lottery", "winning", "results" ], - "flags" : [ "default", "restorable", "restorePossibleForType" ] - } - }, - "data" : [ [ 1, "DD63E09E-4222-4E85-B209-4ECB6FEB8B9D", 1, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-05-17T00:00:00", "15 18 25 33 47", "30", null ] -, [ 2, "CDB0B5A7-F4E1-4D26-97E2-C0643DF22F9C", 2, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-05-21T00:00:00", "04 28 39 41 44", "09", null ] -, [ 3, "2E7BD2A6-7685-4C03-9DA2-F23490539D0A", 3, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-05-24T00:00:00", "02 04 32 44 52", "36", null ] -, [ 4, "5A8BEB43-7731-4019-87CA-5674C82123F7", 4, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-05-28T00:00:00", "06 21 22 29 32", "24", null ] -, [ 5, "AA15F9F3-C9B9-413D-84AA-915039E534D4", 5, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-05-31T00:00:00", "12 28 45 46 52", "47", null ] -, [ 6, "E322CD76-D127-4524-97D7-073B62D1E2CE", 6, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-04T00:00:00", "03 25 29 30 48", "48", null ] -, [ 7, "6D9D2AF9-D5C9-486A-B522-0F00B9DE27F4", 7, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-07T00:00:00", "14 22 27 28 42", "13", null ] -, [ 8, "D5C31C03-3C01-4089-83ED-D286EC8EB4E0", 8, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-11T00:00:00", "05 06 09 33 44", "52", null ] -, [ 9, "D195047D-520E-43B4-AB07-62468B5F0D7D", 9, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-14T00:00:00", "04 08 32 37 43", "02", null ] -, [ 10, "B70FC384-3AB2-4374-BE6B-19FE0B1B5E60", 10, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-18T00:00:00", "06 13 18 27 45", "18", null ] -, [ 11, "604A874F-7DA9-4CD2-90EB-E6AC68736016", 11, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-21T00:00:00", "13 18 32 39 49", "06", null ] -, [ 12, "BB41E518-5BAD-4AE3-90C3-2BFCB25FA9AF", 12, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-25T00:00:00", "04 18 21 27 41", "50", null ] -, [ 13, "E927B1DB-EE55-4BD2-AD76-23F93A0151AC", 13, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-06-28T00:00:00", "18 31 49 50 51", "04", null ] -, [ 14, "B676A329-65DC-4084-AABE-6A25C83EFAB3", 14, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-02T00:00:00", "14 22 32 35 44", "06", null ] -, [ 15, "776E4AE3-82C8-48CF-930B-C92A1F571516", 15, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-05T00:00:00", "11 20 26 29 41", "41", null ] -, [ 16, "DD63071A-8491-4ED3-A3AC-18352FA79BED", 16, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-09T00:00:00", "26 29 31 44 48", "40", null ] -, [ 17, "3BD81BA2-8C8F-4A58-AAC2-22D96A0672B7", 17, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-12T00:00:00", "13 19 23 38 47", "15", null ] -, [ 18, "46D285E0-FE04-43C5-A848-B9846D038F5B", 18, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-16T00:00:00", "10 24 35 49 52", "47", null ] -, [ 19, "470FA664-DEB5-49C3-9D6F-A3C187FA6FDF", 19, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-19T00:00:00", "07 15 24 37 46", "09", null ] -, [ 20, "4F3CA620-EA20-4576-B91B-44A4A8C38B1C", 20, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-23T00:00:00", "10 12 29 32 38", "07", null ] -, [ 21, "7326095E-618A-4DD2-8949-BC6BE5358158", 21, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-26T00:00:00", "20 27 28 37 49", "32", null ] -, [ 22, "CFAC1CDB-7D92-4432-97D7-83E5FBDB3D8A", 22, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-07-30T00:00:00", "02 06 22 27 44", "01", null ] -, [ 23, "A2F33330-714C-4D90-93AF-E003BFDE8459", 23, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-02T00:00:00", "10 16 23 28 31", "07", null ] -, [ 24, "69C74D9F-48C8-4A14-9A1D-BF41DE0AFB20", 24, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-06T00:00:00", "02 06 38 40 50", "14", null ] -, [ 25, "0FB58BD0-9EE5-4018-BE99-65A943A57052", 25, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-09T00:00:00", "07 17 23 43 44", "26", null ] -, [ 26, "F90BA0BD-C520-44C5-B511-6A12634A3CE3", 26, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-13T00:00:00", "03 10 15 18 25", "52", null ] -, [ 27, "A22129D4-F083-4E99-97C7-15E807B2053E", 27, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-16T00:00:00", "22 31 33 44 52", "43", null ] -, [ 28, "0B145B86-D93E-4729-B31F-102C9BA6E2F5", 28, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-20T00:00:00", "02 13 20 23 43", "06", null ] -, [ 29, "E813DDA1-E3CA-4B4D-9FE2-290318C777DA", 29, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-23T00:00:00", "05 19 20 45 48", "44", null ] -, [ 30, "6292DFE4-D4A5-484A-9E52-8D2CDD57346E", 30, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-27T00:00:00", "02 05 11 18 45", "22", null ] -, [ 31, "5F8C47D5-94BF-4744-879A-879576D98824", 31, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-08-30T00:00:00", "06 31 32 42 51", "42", null ] -, [ 32, "0B608831-82DE-4A5D-B1B5-175B0386B92C", 32, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-03T00:00:00", "08 23 36 49 51", "10", null ] -, [ 33, "0729E99F-EDF4-4CF8-9C7D-538F359A43D6", 33, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-06T00:00:00", "31 39 42 49 51", "35", null ] -, [ 34, "480239A2-53C4-49F8-9B38-0C50CEA74DAA", 34, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-10T00:00:00", "04 06 10 21 25", "21", null ] -, [ 35, "2A460703-1EE5-4863-AD16-AB89FEE47E3C", 35, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-13T00:00:00", "24 32 37 40 51", "12", null ] -, [ 36, "FE0F5025-940B-4B6A-8748-078CE383248C", 36, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-17T00:00:00", "07 10 19 26 44", "05", null ] -, [ 37, "F8B8EB29-240C-4EDD-8D83-767A7144D889", 37, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-20T00:00:00", "01 02 04 05 46", "08", null ] -, [ 38, "B16F1457-6AE7-4F6E-9CD4-2D2A45FAC9AE", 38, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-24T00:00:00", "08 32 34 42 50", "21", null ] -, [ 39, "5B3358D5-CEC6-40A2-B805-27C3C0CEFC46", 39, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-09-27T00:00:00", "23 27 30 33 36", "05", null ] -, [ 40, "F4B78AC5-E425-4199-8847-378923739E98", 40, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-01T00:00:00", "07 21 30 32 37", "15", null ] -, [ 41, "E38867F4-3486-42B1-BB61-C62BFB44E0DC", 41, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-04T00:00:00", "10 42 43 45 51", "01", null ] -, [ 42, "807547BC-EE1A-4B65-84AD-3CE1E854FC35", 42, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-08T00:00:00", "18 34 43 47 50", "25", null ] -, [ 43, "AC63F7BD-012F-4C12-8661-D4E4117368C1", 43, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-11T00:00:00", "09 11 17 26 41", "29", null ] -, [ 44, "A3E5E55D-900C-494F-9E9F-09406CF28772", 44, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-15T00:00:00", "06 20 27 34 51", "22", null ] -, [ 45, "76FE6E0D-849C-4876-9B35-79B6945D12B9", 45, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-18T00:00:00", "10 31 40 48 51", "38", null ] -, [ 46, "0247E8D6-04A3-4975-BB28-9E5ED39E7013", 46, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-22T00:00:00", "16 20 26 36 48", "32", null ] -, [ 47, "203F46F2-9559-4634-B419-0CF89FC181B5", 47, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-25T00:00:00", "08 15 34 39 47", "04", null ] -, [ 48, "A6901E49-98E3-4C6E-8315-0266D96AEB91", 48, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-10-29T00:00:00", "09 10 14 41 49", "35", null ] -, [ 49, "DE30E918-423E-42EB-BA73-F657ABCFD8FE", 49, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-01T00:00:00", "05 10 22 23 43", "37", null ] -, [ 50, "6A5EF20C-5F46-4DB1-B77E-01E1D55D805F", 50, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-05T00:00:00", "02 07 16 28 36", "47", null ] -, [ 51, "0DDE170F-9285-4B87-B30A-AD3C7F643585", 51, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-08T00:00:00", "17 19 37 47 48", "14", null ] -, [ 52, "DB2E5ECC-86E3-49E6-BE8D-B36C8B860FAE", 52, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-12T00:00:00", "03 28 45 48 50", "24", null ] -, [ 53, "C9E90F12-A9A5-4650-A6F3-D5D7D0A7ED1C", 53, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-15T00:00:00", "06 17 44 49 51", "39", null ] -, [ 54, "E7969201-469E-43CD-9B96-5B4D9B5535A1", 54, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-19T00:00:00", "07 16 20 40 52", "08", null ] -, [ 55, "270528C5-6420-4FE3-AAA1-8D19B8AFB6E2", 55, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-22T00:00:00", "11 16 19 22 46", "05", null ] -, [ 56, "C15AD01F-1345-43D5-B0AB-769467A17A9B", 56, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-26T00:00:00", "03 21 27 31 43", "34", null ] -, [ 57, "32E2EF7A-2D3B-4AB7-883D-78E2E55D037E", 57, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-11-29T00:00:00", "08 25 33 42 49", "40", null ] -, [ 58, "2B065668-6258-414B-92E3-4C992B783DDD", 58, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-03T00:00:00", "01 15 19 40 51", "26", null ] -, [ 59, "3974C6B7-6B78-4503-8DD4-7AF43B9D83C6", 59, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-06T00:00:00", "04 08 30 36 52", "48", null ] -, [ 60, "2B12B387-2C45-4544-B2C5-509EC3EF25EA", 60, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-10T00:00:00", "03 05 09 16 31", "28", null ] -, [ 61, "B82357E8-CA56-4079-9CF8-7D4801ECD65B", 61, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-13T00:00:00", "02 13 14 24 46", "34", null ] -, [ 62, "13CB91BC-2F31-42F1-8107-89B322AFE86F", 62, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-17T00:00:00", "03 07 21 29 49", "46", null ] -, [ 63, "22F91DAE-F451-4527-8222-987F1A38D258", 63, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-20T00:00:00", "10 14 41 46 49", "52", null ] -, [ 64, "BD3EC7D2-2C57-4E83-AF26-17710AD6A208", 64, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-24T00:00:00", "08 24 39 43 52", "43", null ] -, [ 65, "D5CCC43B-959F-44B1-B13D-A7E410E4E761", 65, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-27T00:00:00", "11 14 26 30 39", "03", null ] -, [ 66, "E285D142-DA61-4320-A64B-0460BC9AD06E", 66, 1362743863, "706580", 1362743863, "706580", "{\n}", "2002-12-31T00:00:00", "08 21 29 42 51", "34", null ] -, [ 67, "98E41CD9-7A07-4777-99C4-7A3FF99E1843", 67, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-03T00:00:00", "06 14 28 37 46", "03", null ] -, [ 68, "AEEA3F05-8610-47C6-A1DD-8A179E989AE2", 68, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-07T00:00:00", "15 16 28 34 51", "33", null ] -, [ 69, "4E06CBF1-A178-49DD-8633-0BC1B37DA970", 69, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-10T00:00:00", "07 17 18 34 50", "18", null ] -, [ 70, "C0AA6972-7E61-44F6-AB49-00E2F277C475", 70, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-14T00:00:00", "30 39 41 47 52", "27", null ] -, [ 71, "628A1E63-1D14-49BB-AD14-242855DA8215", 71, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-17T00:00:00", "25 26 38 42 46", "27", null ] -, [ 72, "08C611B7-7BF9-4151-BF2F-7813FD7B1CF8", 72, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-21T00:00:00", "04 41 48 50 51", "23", null ] -, [ 73, "46A0C177-42F3-40FD-A28F-1039BA0F4CEF", 73, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-24T00:00:00", "16 31 37 40 41", "05", null ] -, [ 74, "E45F2A0A-C3CB-4F40-9975-154ACD72FA7F", 74, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-28T00:00:00", "13 24 26 32 47", "34", null ] -, [ 75, "3BC338E9-A5E7-4BE9-BBB8-F2BF9D15CEE4", 75, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-01-31T00:00:00", "01 08 09 19 22", "21", null ] -, [ 76, "A4515DBC-FFBA-409E-8BE8-CF303205D017", 76, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-04T00:00:00", "05 12 16 22 24", "48", null ] -, [ 77, "1522A885-5C53-4246-988D-05F89AA7D40B", 77, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-07T00:00:00", "03 09 20 26 27", "50", null ] -, [ 78, "90677E80-B1E2-4F1F-AA35-AF8916FBBF9F", 78, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-11T00:00:00", "18 20 23 48 49", "10", null ] -, [ 79, "7707C582-F232-41DB-B2AD-482FF443C9E8", 79, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-14T00:00:00", "11 13 19 32 47", "21", null ] -, [ 80, "3F14C37A-54D4-4DCD-B83A-3A7F267441DE", 80, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-18T00:00:00", "12 22 29 42 50", "11", null ] -, [ 81, "5823D1CA-DABD-4A60-980E-83739E6F1CA2", 81, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-21T00:00:00", "21 28 29 40 51", "20", null ] -, [ 82, "FFB2EDFC-6008-43C7-B085-802A10E87EB1", 82, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-25T00:00:00", "02 04 06 37 47", "38", null ] -, [ 83, "0A9ABE29-045E-4F63-9078-BAC824AB6704", 83, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-02-28T00:00:00", "11 16 26 48 49", "13", null ] -, [ 84, "4EE62AB5-8FA2-4D3A-B4B5-69A1C3EA158A", 84, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-04T00:00:00", "02 26 36 37 41", "22", null ] -, [ 85, "C2E50A67-D861-4786-A68D-C6A44BE85409", 85, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-07T00:00:00", "07 10 32 36 41", "33", null ] -, [ 86, "26C6335D-FB4B-45B0-BE37-E1D1C7775527", 86, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-11T00:00:00", "10 15 26 28 39", "10", null ] -, [ 87, "EE125C30-5C1A-4655-A8EB-2B1CC440DB50", 87, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-14T00:00:00", "03 06 14 31 33", "08", null ] -, [ 88, "E14A17CA-D479-4C2C-8128-464926CBD322", 88, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-18T00:00:00", "13 14 16 29 49", "29", null ] -, [ 89, "D137FA48-2A58-4107-911F-D8DB91D708EA", 89, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-21T00:00:00", "06 17 18 40 50", "08", null ] -, [ 90, "ADE703B0-44B8-4EF3-9251-743D5A9EC566", 90, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-25T00:00:00", "15 21 37 40 42", "07", null ] -, [ 91, "AB8E0352-1F85-4DCE-A9F0-D14E4536B079", 91, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-03-28T00:00:00", "08 12 21 27 29", "15", null ] -, [ 92, "09359168-05CA-40CC-A9DA-CDEF43B38B53", 92, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-01T00:00:00", "07 12 26 45 47", "36", null ] -, [ 93, "3BE7FEFD-6E77-4543-AED2-C671DFF538B2", 93, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-04T00:00:00", "06 22 28 31 40", "18", null ] -, [ 94, "31DE14F3-C5F3-4570-95E5-BDD9CF730DCF", 94, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-08T00:00:00", "08 10 24 38 45", "06", null ] -, [ 95, "5D649EB0-C1CA-4816-B26B-2B0167EA660F", 95, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-11T00:00:00", "15 26 27 38 39", "46", null ] -, [ 96, "D3506FF7-DF54-441A-8CE5-83F036B839DA", 96, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-15T00:00:00", "16 29 31 39 52", "21", null ] -, [ 97, "E46D4DDD-F39E-483B-9039-5861A76A47F2", 97, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-18T00:00:00", "05 15 24 50 52", "03", null ] -, [ 98, "7E8146F7-D852-40DE-8C52-43BE45BE562E", 98, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-22T00:00:00", "03 09 15 28 52", "07", null ] -, [ 99, "BA9B9A00-E659-425F-9D67-A92211D08CBE", 99, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-25T00:00:00", "01 12 32 48 51", "29", null ] -, [ 100, "58C1D225-815B-4DB8-B948-35A652949308", 100, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-04-29T00:00:00", "06 08 09 33 35", "32", null ] -, [ 101, "1754387A-A0DF-4168-918F-8168243D07A8", 101, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-02T00:00:00", "02 05 19 32 34", "52", null ] -, [ 102, "9D5762AF-6758-46C0-9171-827486835D08", 102, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-06T00:00:00", "05 14 32 44 52", "24", null ] -, [ 103, "454BC472-EEFE-4ACF-B4F9-168839FD8665", 103, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-09T00:00:00", "01 10 20 22 28", "39", null ] -, [ 104, "A8D661D0-3B6B-440D-B4E0-CD61055A1FD4", 104, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-13T00:00:00", "17 20 47 49 50", "34", null ] -, [ 105, "B7EC9B0F-9AFE-45FD-93B2-7FFCA2ED8EDA", 105, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-16T00:00:00", "05 10 16 26 39", "52", null ] -, [ 106, "1CF96B88-1B48-488A-BD4E-DB23E455812F", 106, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-20T00:00:00", "02 16 36 44 49", "03", null ] -, [ 107, "96DDFF18-6B91-4025-BD0A-8E7BFB8F145C", 107, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-23T00:00:00", "12 20 31 33 50", "17", null ] -, [ 108, "B9DB7AEF-4963-490A-9021-D3F9DF7E44CA", 108, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-27T00:00:00", "10 11 17 20 26", "03", null ] -, [ 109, "FAD4EBFE-8EA9-440F-A64A-6EAA0751142A", 109, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-05-30T00:00:00", "01 21 28 33 51", "03", null ] -, [ 110, "49420CC9-2969-499C-9682-0922078F53C7", 110, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-03T00:00:00", "04 20 25 29 32", "20", null ] -, [ 111, "DE8AF8DE-54CC-47F3-B3BB-05471B80C030", 111, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-06T00:00:00", "10 14 28 39 40", "35", null ] -, [ 112, "7AEC15E5-8753-42DA-8D8B-D44AE2936037", 112, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-10T00:00:00", "14 15 23 32 52", "37", null ] -, [ 113, "3744E2FD-4467-473F-AD08-615DABDF4BF9", 113, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-13T00:00:00", "12 15 16 20 51", "33", null ] -, [ 114, "4204CF2D-6A71-49DB-A1CC-EC65C7F337DF", 114, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-17T00:00:00", "27 31 34 40 52", "01", null ] -, [ 115, "D1D590C1-A5BC-462B-9004-A666D7301BCD", 115, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-20T00:00:00", "01 02 03 12 37", "35", null ] -, [ 116, "4975BB43-7289-4C7B-8A35-FAF5F1B2DCB5", 116, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-24T00:00:00", "02 26 43 44 47", "31", null ] -, [ 117, "C02F25C6-38D1-4DF6-B6A1-FBFFD94BD95F", 117, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-06-27T00:00:00", "01 14 20 31 40", "43", null ] -, [ 118, "B417F0A8-9D77-4C4D-9AAC-CCD1CFBDE184", 118, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-01T00:00:00", "28 32 39 45 48", "31", null ] -, [ 119, "AB2B5C72-8FE3-4793-853E-1AE475BB514D", 119, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-04T00:00:00", "06 07 22 37 46", "08", null ] -, [ 120, "142013F7-D91E-44AC-95CC-8DE4C4FB06FC", 120, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-08T00:00:00", "02 09 27 29 35", "18", null ] -, [ 121, "5EC16F46-F61F-438D-9158-380060242B6E", 121, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-11T00:00:00", "01 04 10 16 18", "10", null ] -, [ 122, "10344C0E-E9A9-4272-A637-331A9CE4C387", 122, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-15T00:00:00", "01 26 33 43 48", "22", null ] -, [ 123, "F56CED15-FCFF-4517-A2C8-7304D1539E69", 123, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-18T00:00:00", "29 30 34 38 44", "39", null ] -, [ 124, "26143402-87D4-49D1-88EF-E33AFDC3508E", 124, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-22T00:00:00", "01 05 31 38 47", "03", null ] -, [ 125, "5B59CCDB-E5F1-4AEE-B128-3E8CF145939D", 125, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-25T00:00:00", "33 46 47 50 51", "30", null ] -, [ 126, "AFC67E7B-C793-46F7-9EF1-1C52AA2E94EE", 126, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-07-29T00:00:00", "01 17 19 32 42", "33", null ] -, [ 127, "E1C1FA86-E45D-4A8E-82F7-9A5BD5C8485C", 127, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-01T00:00:00", "02 11 27 30 33", "46", null ] -, [ 128, "BE4D241F-D6A3-42D5-B82D-C7C5F548BAA7", 128, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-05T00:00:00", "07 32 34 38 44", "49", null ] -, [ 129, "34419EB4-F8CE-4979-BF7A-022B83FE4119", 129, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-08T00:00:00", "06 09 35 40 43", "42", null ] -, [ 130, "D97F5B99-5715-41DB-989F-EE646D0885CE", 130, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-12T00:00:00", "08 11 18 35 51", "26", null ] -, [ 131, "54DD969F-9ADB-409E-8C07-FD104FF3214E", 131, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-15T00:00:00", "01 16 20 41 52", "13", null ] -, [ 132, "C45D583E-DBF7-419A-AC90-92366F3BEC38", 132, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-19T00:00:00", "07 11 24 28 52", "16", null ] -, [ 133, "FB0467F9-610B-4187-B189-A1679E990D91", 133, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-22T00:00:00", "04 19 31 32 51", "31", null ] -, [ 134, "E3BF4E12-0FBC-4324-9FE1-6DA035540AEA", 134, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-26T00:00:00", "09 28 42 44 49", "47", null ] -, [ 135, "4367D263-7EB2-4860-AB00-CEEE46595568", 135, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-08-29T00:00:00", "08 11 17 42 52", "10", null ] -, [ 136, "703C475D-9209-4E84-B245-E167C7CF15CB", 136, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-02T00:00:00", "22 26 27 32 39", "14", null ] -, [ 137, "87F8EC61-3E18-42A4-9DFD-F0C83B86394D", 137, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-05T00:00:00", "07 09 28 41 42", "19", null ] -, [ 138, "2F14383B-8605-4624-8AD2-5A0FBB27AFB8", 138, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-09T00:00:00", "14 15 30 39 46", "30", null ] -, [ 139, "7EE72B00-2CE6-4041-B9C6-D3E5A30B58CD", 139, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-12T00:00:00", "16 22 23 38 46", "45", null ] -, [ 140, "A9512471-39BE-4381-81A2-16D003C63F06", 140, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-16T00:00:00", "15 20 24 30 46", "42", null ] -, [ 141, "C33B630E-4AEF-471A-B115-ACE4C7ABB4C9", 141, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-19T00:00:00", "13 14 24 34 47", "13", null ] -, [ 142, "90AECD1E-D7A1-4C0C-B40A-A6FEE8C89582", 142, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-23T00:00:00", "05 16 24 49 51", "28", null ] -, [ 143, "10BE1B47-B8F8-4C5D-B864-161897D232A4", 143, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-26T00:00:00", "05 29 32 45 52", "29", null ] -, [ 144, "456D7CA6-FEE6-4DA7-81CA-2DCA2E97A114", 144, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-09-30T00:00:00", "02 26 37 40 46", "49", null ] -, [ 145, "58CBE626-2263-4622-83A1-172520060895", 145, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-03T00:00:00", "19 21 30 31 52", "51", null ] -, [ 146, "DEBA65E1-7811-402B-B00F-BA8FF5397918", 146, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-07T00:00:00", "01 02 22 40 41", "43", null ] -, [ 147, "6EBA14B3-3CB0-451D-8E30-F8C1478D229C", 147, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-10T00:00:00", "04 19 36 42 48", "13", null ] -, [ 148, "60C042BD-AA8F-438F-BAC3-DA0659C4AAE5", 148, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-14T00:00:00", "18 19 21 33 40", "29", null ] -, [ 149, "E3056AF1-D254-4FF8-AD9E-B519592CD15C", 149, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-17T00:00:00", "14 20 31 46 48", "18", null ] -, [ 150, "3F10D07A-00CD-4903-B1CF-9AE1CDCE0BE9", 150, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-21T00:00:00", "18 34 46 51 52", "38", null ] -, [ 151, "286A4F08-E3C6-43AA-9218-5DE78829445C", 151, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-24T00:00:00", "08 09 16 30 31", "15", null ] -, [ 152, "96DA12DE-9616-409F-9B97-D0EF9B2361F0", 152, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-28T00:00:00", "06 09 20 40 47", "26", null ] -, [ 153, "CF8AF49F-06AB-467D-9465-ECC72ED4FBEB", 153, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-10-31T00:00:00", "06 12 13 36 46", "03", null ] -, [ 154, "660B8C66-B5F5-43F2-8B48-1D1BD288F397", 154, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-04T00:00:00", "16 24 43 44 45", "22", null ] -, [ 155, "12930383-A5F6-4021-864F-6E6613EFCC02", 155, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-07T00:00:00", "06 18 23 26 30", "31", null ] -, [ 156, "55ACF0F2-4E61-4DD1-9AD0-121B04E8E2D8", 156, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-11T00:00:00", "02 05 17 21 22", "43", null ] -, [ 157, "AFFE3574-5A71-449A-A5A9-89A02CC63B46", 157, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-14T00:00:00", "03 13 31 41 42", "52", null ] -, [ 158, "53838D7A-3459-4B07-A5EA-62D93F98F5A0", 158, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-18T00:00:00", "04 11 25 30 52", "36", null ] -, [ 159, "028A208C-371B-4F58-B771-ADDDE67122A1", 159, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-21T00:00:00", "14 26 28 36 42", "14", null ] -, [ 160, "89F065A8-44C0-4FB4-B16E-A67EE3D12895", 160, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-25T00:00:00", "22 32 37 40 41", "52", null ] -, [ 161, "9328CDE3-5932-40FC-8D93-F4D5F75D4900", 161, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-11-28T00:00:00", "19 26 31 44 50", "19", null ] -, [ 162, "6EC846B7-104F-4C4A-B8E0-8BF46EA0E67F", 162, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-02T00:00:00", "10 13 24 34 49", "04", null ] -, [ 163, "A3AA23AD-8665-4F09-BADB-96C5D5C54D3A", 163, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-05T00:00:00", "01 12 15 18 44", "42", null ] -, [ 164, "181538CE-E898-498C-897E-13CEF30A9A24", 164, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-09T00:00:00", "04 14 15 24 48", "41", null ] -, [ 165, "19102899-F12B-405C-A594-F212042C01CB", 165, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-12T00:00:00", "09 16 32 45 46", "26", null ] -, [ 166, "00A140E6-B878-453E-9C36-31A84EE9EB95", 166, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-16T00:00:00", "16 24 31 46 47", "47", null ] -, [ 167, "736F2B3D-93B7-4DAE-B6AF-C4C9BF2EE8EE", 167, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-19T00:00:00", "05 10 17 35 39", "38", null ] -, [ 168, "8CA935B2-B5C0-419D-87EF-26F64B6EC006", 168, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-23T00:00:00", "02 13 21 22 49", "52", null ] -, [ 169, "F7C96926-4484-494B-A7C9-676DCA6F1729", 169, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-26T00:00:00", "01 10 17 20 29", "36", null ] -, [ 170, "16F8399E-7FE4-401B-B800-FA7BB56A97DD", 170, 1362743863, "706580", 1362743863, "706580", "{\n}", "2003-12-30T00:00:00", "12 18 21 32 46", "49", null ] -, [ 171, "9ED8E78A-62FB-41C1-870E-8CDFC91C74D6", 171, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-02T00:00:00", "07 08 36 44 48", "09", null ] -, [ 172, "3CF133FE-1FA3-47DD-897C-60481ED06E88", 172, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-06T00:00:00", "07 13 15 25 32", "09", null ] -, [ 173, "22948242-9DDD-43CB-BF72-CF93BD75566E", 173, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-09T00:00:00", "24 32 38 47 49", "12", null ] -, [ 174, "35461A28-871A-479F-953A-E06F8CB4384F", 174, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-13T00:00:00", "03 17 18 21 45", "21", null ] -, [ 175, "7DABD050-F49B-41BF-A9BA-656346A9F38C", 175, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-16T00:00:00", "12 26 41 44 49", "44", null ] -, [ 176, "90A89117-6F30-49F5-A23C-8333F74EAA1E", 176, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-20T00:00:00", "05 07 14 21 45", "36", null ] -, [ 177, "80664E0D-B4D2-49F0-9959-C9AB17CF93AE", 177, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-23T00:00:00", "10 18 33 46 51", "13", null ] -, [ 178, "D0CE2C24-B101-4185-B19B-D158FB47ED3E", 178, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-27T00:00:00", "06 10 20 38 50", "27", null ] -, [ 179, "F01C707E-9960-4E43-A81E-1782647082A3", 179, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-01-30T00:00:00", "17 28 30 40 51", "44", null ] -, [ 180, "677A8C08-956F-46C4-B6A3-F651B929C471", 180, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-03T00:00:00", "09 21 26 35 41", "17", null ] -, [ 181, "1AC95439-5800-4931-80E8-F93513E15EFA", 181, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-06T00:00:00", "01 06 16 30 49", "13", null ] -, [ 182, "DDE9D7CC-A931-4103-AB9A-DC3DDF728EB5", 182, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-10T00:00:00", "03 07 10 22 32", "23", null ] -, [ 183, "166A3441-00D2-4FEC-BF3B-631E835EA49C", 183, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-13T00:00:00", "14 30 42 43 45", "30", null ] -, [ 184, "1BDB7F1B-A39A-4115-B172-3303380E1DF3", 184, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-17T00:00:00", "02 08 34 36 52", "21", null ] -, [ 185, "E355CFD8-D090-41B8-8811-028D99AB8DA8", 185, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-20T00:00:00", "01 13 20 21 30", "24", null ] -, [ 186, "B999148E-D11E-440B-81DA-789CB7E68DBB", 186, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-24T00:00:00", "06 11 43 49 52", "21", null ] -, [ 187, "1F1CC98F-6F31-4BF7-9145-56C2FF15E6FD", 187, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-02-27T00:00:00", "02 09 24 36 52", "44", null ] -, [ 188, "A78AF303-06C3-4C18-8CD0-491D985D7A43", 188, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-02T00:00:00", "25 30 35 40 50", "04", null ] -, [ 189, "5D0C62A6-844E-4C80-8981-1EC4862B165A", 189, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-05T00:00:00", "30 40 47 49 52", "03", null ] -, [ 190, "DF590B22-E81F-41A7-9ED0-B792C9CE5249", 190, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-09T00:00:00", "16 23 29 36 51", "49", null ] -, [ 191, "DD89D574-8A08-41C4-A5EE-4E4A5AA07163", 191, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-12T00:00:00", "04 29 32 35 36", "11", null ] -, [ 192, "9F301819-E19D-4D62-8128-AE50FC932F93", 192, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-16T00:00:00", "03 28 45 49 51", "52", null ] -, [ 193, "287B8DFB-0016-4750-86CA-425DB92CA791", 193, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-19T00:00:00", "06 09 14 32 50", "04", null ] -, [ 194, "30AC2580-A52B-4268-A81C-BF18BE48945D", 194, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-23T00:00:00", "12 22 35 39 46", "32", null ] -, [ 195, "151FEC11-E77A-43D6-B5F5-E0B0A884017B", 195, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-26T00:00:00", "08 10 17 37 49", "20", null ] -, [ 196, "F7C95B95-0C63-4A37-AA6B-EA02803C0F1E", 196, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-03-30T00:00:00", "03 27 31 41 45", "33", null ] -, [ 197, "37183BCC-D528-4EFF-8337-4329057BB4E6", 197, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-02T00:00:00", "08 17 25 46 47", "13", null ] -, [ 198, "D0B36FC0-DF03-4360-8B25-4346181571B2", 198, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-06T00:00:00", "08 17 29 32 39", "49", null ] -, [ 199, "4401F17E-E367-440B-99FB-688A755EA807", 199, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-09T00:00:00", "02 08 10 11 23", "40", null ] -, [ 200, "64E8D621-CD53-43AA-A99E-9469BF1CF78D", 200, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-13T00:00:00", "13 36 39 50 51", "34", null ] -, [ 201, "530AD7EA-F834-4223-8EB1-35148E1329A8", 201, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-16T00:00:00", "06 24 29 42 51", "41", null ] -, [ 202, "CE4121AF-B677-4B9B-9061-E3BC4CCE3CF4", 202, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-20T00:00:00", "12 22 37 46 48", "49", null ] -, [ 203, "D89990AD-D822-43B2-9D98-B4DB4D36BD27", 203, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-23T00:00:00", "08 22 25 47 48", "27", null ] -, [ 204, "8F52A470-2731-451C-A0E9-652338AC2AE5", 204, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-27T00:00:00", "01 10 17 23 35", "45", null ] -, [ 205, "EEEDFFAB-7B51-4B47-9167-604CD2BBCEDC", 205, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-04-30T00:00:00", "15 21 32 39 50", "34", null ] -, [ 206, "4281178C-8AE5-4EDB-AE19-FFCE603ED9F8", 206, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-04T00:00:00", "03 15 29 37 39", "40", null ] -, [ 207, "FA75A85C-0A84-44B0-BD03-3F6BB05FDE6D", 207, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-07T00:00:00", "14 17 19 44 50", "17", null ] -, [ 208, "3FAD2848-7B00-4795-AAD7-B595FE15B0F2", 208, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-11T00:00:00", "09 25 30 34 37", "30", null ] -, [ 209, "EDE45563-04A9-452C-950C-F90D50C60B7F", 209, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-14T00:00:00", "10 19 32 36 46", "06", null ] -, [ 210, "2CA731BD-CD0F-4CAA-A73D-952783FB2963", 210, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-18T00:00:00", "02 36 44 46 51", "45", null ] -, [ 211, "AB2A1494-C7CD-406A-869E-E91C3B1F9BDB", 211, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-21T00:00:00", "04 20 27 38 49", "31", null ] -, [ 212, "C1BA08C1-1F30-487B-9E16-4E11970807DA", 212, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-25T00:00:00", "05 18 34 36 39", "43", null ] -, [ 213, "7883E5E8-E510-4E95-B2AE-1B3E6322025A", 213, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-05-28T00:00:00", "13 27 36 39 51", "33", null ] -, [ 214, "BE1D586A-3362-4D15-B51F-52F8B09B3BC7", 214, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-01T00:00:00", "07 16 17 26 48", "15", null ] -, [ 215, "4C803D13-0DF9-4B75-AB36-BFA811A6A44B", 215, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-04T00:00:00", "04 16 18 41 47", "46", null ] -, [ 216, "90CECF2B-081E-46D8-ADF3-DE9AF9FFA85D", 216, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-08T00:00:00", "17 24 29 37 45", "43", null ] -, [ 217, "23D2B616-7C32-44DE-BF92-F965349CD096", 217, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-11T00:00:00", "12 28 36 39 52", "36", null ] -, [ 218, "74430CB6-1A79-4878-963D-E5DFF95B7882", 218, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-15T00:00:00", "18 23 27 29 44", "24", null ] -, [ 219, "3CFF8EC5-D00F-4EBC-8E08-DA91AECA3A61", 219, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-18T00:00:00", "07 10 11 15 51", "23", null ] -, [ 220, "D13D362C-47B9-44A7-948D-2377519ACDAB", 220, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-22T00:00:00", "09 10 17 41 52", "19", null ] -, [ 221, "1B04F369-0AA5-4EC1-9ACE-1B1B1A29949B", 221, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-25T00:00:00", "18 19 29 32 42", "32", null ] -, [ 222, "A4EB48A6-5B93-4F87-937D-3FA8D3D9B13A", 222, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-06-29T00:00:00", "10 13 19 28 38", "01", null ] -, [ 223, "C973AB92-79E2-4F3B-9532-29B1EF730C15", 223, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-02T00:00:00", "10 25 38 39 50", "12", null ] -, [ 224, "2A8B3B87-C571-44C5-8B72-4D5FC07E3C4E", 224, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-06T00:00:00", "06 07 08 31 48", "19", null ] -, [ 225, "0CB0EEF7-3E07-47C2-834A-CCC22BD96076", 225, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-09T00:00:00", "11 23 25 29 45", "16", null ] -, [ 226, "FFB87A81-D21E-4374-AB89-D0E77B35C578", 226, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-13T00:00:00", "13 31 37 39 52", "38", null ] -, [ 227, "11FB4729-5353-4468-8630-1404816AE321", 227, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-16T00:00:00", "03 21 22 35 44", "07", null ] -, [ 228, "9C3F4245-A499-4EBC-BF96-C29B635CA561", 228, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-20T00:00:00", "06 15 21 32 44", "13", null ] -, [ 229, "C09247AD-299E-4A91-A8CF-C3A0179AB270", 229, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-23T00:00:00", "05 12 25 35 37", "12", null ] -, [ 230, "DA4F201D-2A37-4504-9947-14F8542402D5", 230, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-27T00:00:00", "08 10 11 13 24", "46", null ] -, [ 231, "169DA2A4-95D6-4BCC-AEFD-46C5FA9370B2", 231, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-07-30T00:00:00", "16 19 21 34 35", "22", null ] -, [ 232, "025397EA-5654-411F-880E-EB525C9D29B9", 232, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-03T00:00:00", "01 02 13 16 22", "31", null ] -, [ 233, "B45BCE14-9723-436A-B1D2-A98665679467", 233, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-06T00:00:00", "04 23 33 38 49", "07", null ] -, [ 234, "9DA11ECD-BC04-4EE6-890B-3B22B141D912", 234, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-10T00:00:00", "18 25 29 31 44", "33", null ] -, [ 235, "29B3B61A-07FB-45E4-8E2B-42BADD6E2B13", 235, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-13T00:00:00", "14 31 41 45 48", "20", null ] -, [ 236, "4D1C8130-8D61-4BE8-820C-335E37212DDC", 236, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-17T00:00:00", "22 23 26 28 36", "10", null ] -, [ 237, "0E60BFAF-3237-4A2F-9EC4-25458A705F26", 237, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-20T00:00:00", "12 17 34 37 39", "34", null ] -, [ 238, "79D77C70-4484-4795-A6B0-D5F87F1C2E74", 238, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-24T00:00:00", "02 05 21 47 50", "46", null ] -, [ 239, "ABB0385F-D6B3-4ED7-A7BE-75C967EFF5F3", 239, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-27T00:00:00", "05 25 38 46 47", "14", null ] -, [ 240, "825BC9DA-7E28-48DF-B5DC-DB33D1F598E8", 240, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-08-31T00:00:00", "14 15 25 42 44", "03", null ] -, [ 241, "64C6A60E-3E95-495C-BC4A-44C53814E058", 241, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-03T00:00:00", "04 14 34 38 44", "10", null ] -, [ 242, "E6ADBDFD-2F6B-4726-A525-746186368933", 242, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-07T00:00:00", "13 30 36 38 51", "35", null ] -, [ 243, "2F5EDD22-FB98-43CC-811B-9877253B4F8A", 243, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-10T00:00:00", "11 17 27 45 52", "05", null ] -, [ 244, "BCD22E2B-7328-49C3-8CC3-FC63B9A344D7", 244, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-14T00:00:00", "12 35 37 38 50", "49", null ] -, [ 245, "5835A221-CB4A-4785-B15B-84FF74486672", 245, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-17T00:00:00", "03 16 25 38 49", "04", null ] -, [ 246, "1D628B4B-456A-430D-96D3-6F4DE602BCFA", 246, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-21T00:00:00", "01 03 15 19 29", "39", null ] -, [ 247, "22DAACA0-0D4E-4874-A27D-60C726301E87", 247, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-24T00:00:00", "11 26 30 49 50", "52", null ] -, [ 248, "DB3BC6FA-6BD3-48AC-8B65-65B6A9681BE6", 248, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-09-28T00:00:00", "01 18 39 42 50", "35", null ] -, [ 249, "F9C7E41D-9C9B-49D1-A4E3-15FC77F7F86F", 249, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-01T00:00:00", "08 10 17 24 39", "52", null ] -, [ 250, "52BE51BE-708D-4321-8C26-DE6165AFE04E", 250, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-05T00:00:00", "08 34 39 48 49", "47", null ] -, [ 251, "B4000AC5-B2AE-4BA0-94A2-E044745964AC", 251, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-08T00:00:00", "16 17 21 33 41", "06", null ] -, [ 252, "D191CC09-A515-4BF6-B819-1FE3B2CA14B3", 252, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-12T00:00:00", "04 18 19 39 51", "13", null ] -, [ 253, "A162D2E1-642C-49E6-992A-BB972253B641", 253, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-15T00:00:00", "04 08 24 30 36", "25", null ] -, [ 254, "50754DC2-AFD6-4809-ACFD-2853213FE3DC", 254, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-19T00:00:00", "06 13 19 34 50", "33", null ] -, [ 255, "6BBC3098-B05C-482D-934B-6BF8C7930F01", 255, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-22T00:00:00", "03 07 20 24 43", "36", null ] -, [ 256, "F2BC443C-393C-42AC-97CD-03845FA2AF4B", 256, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-26T00:00:00", "14 25 39 43 49", "27", null ] -, [ 257, "FD20CDD7-751B-45E2-A189-6F06336E4662", 257, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-10-29T00:00:00", "10 18 26 31 41", "48", null ] -, [ 258, "78F4866D-7BBE-4981-AF76-82B4B1FF4A2E", 258, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-02T00:00:00", "24 32 42 49 50", "03", null ] -, [ 259, "0F1336CF-A403-4F6D-9FE9-6A54EF4F7707", 259, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-05T00:00:00", "03 29 30 41 43", "01", null ] -, [ 260, "F081994F-6D07-4891-BFAF-1AFF8C14CFD4", 260, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-09T00:00:00", "11 20 26 28 52", "07", null ] -, [ 261, "2BD8589C-58C2-4EB1-9AC2-9D7680A25908", 261, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-12T00:00:00", "05 31 33 35 51", "01", null ] -, [ 262, "CEF71225-C2BF-4B92-B680-278C358B7720", 262, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-16T00:00:00", "09 10 27 28 30", "18", null ] -, [ 263, "66BA5BBF-68B0-4AFA-8271-418B80BC6718", 263, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-19T00:00:00", "01 12 24 36 51", "38", null ] -, [ 264, "8509E8A0-2D85-4259-92F6-29B471E9AC37", 264, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-23T00:00:00", "08 30 32 35 51", "17", null ] -, [ 265, "E28F4368-1712-48D1-91F6-26904326CF2D", 265, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-26T00:00:00", "07 09 18 37 43", "34", null ] -, [ 266, "74CF5561-90C2-45C1-979E-F07822F35FC2", 266, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-11-30T00:00:00", "10 20 22 28 52", "04", null ] -, [ 267, "B41849CC-89C1-483B-949C-6F6A87CD73A0", 267, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-03T00:00:00", "12 32 37 41 52", "13", null ] -, [ 268, "579AAC40-3B30-4E09-87DD-B5A87C2D92A5", 268, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-07T00:00:00", "01 19 22 32 49", "29", null ] -, [ 269, "A3A9B945-6C27-48B4-AC62-8EE5F1FD0A30", 269, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-10T00:00:00", "22 23 37 42 47", "15", null ] -, [ 270, "8926C688-28B7-4534-AFE5-51FE044A3927", 270, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-14T00:00:00", "14 27 32 34 40", "02", null ] -, [ 271, "22DBCDF8-AEB6-4F84-865A-E25E670EE8A6", 271, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-17T00:00:00", "16 34 38 42 47", "01", null ] -, [ 272, "3F07DD76-991F-49F8-BE80-C9D05D80F060", 272, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-21T00:00:00", "07 22 27 31 38", "12", null ] -, [ 273, "41AC3E8D-EC34-4E08-AA87-5918880FE818", 273, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-24T00:00:00", "09 20 22 41 42", "10", null ] -, [ 274, "65F331BB-6BD2-495C-8FCB-E0460922F04E", 274, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-28T00:00:00", "18 29 32 38 43", "50", null ] -, [ 275, "588CD7B2-93DC-4A0F-9437-36D0C339AA9C", 275, 1362743863, "706580", 1362743863, "706580", "{\n}", "2004-12-31T00:00:00", "10 14 45 47 51", "20", null ] -, [ 276, "93825C54-2A7A-434A-AC7B-D60BEA85F53D", 276, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-04T00:00:00", "03 06 07 12 32", "30", null ] -, [ 277, "F4313158-89FD-4820-A8A7-36C5C88ED660", 277, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-07T00:00:00", "02 08 14 15 51", "38", null ] -, [ 278, "E8206E3B-51A1-4B45-A90E-CA2419422CA5", 278, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-11T00:00:00", "02 23 24 35 45", "18", null ] -, [ 279, "D3C97927-9FD1-4A11-BC1F-258ED901202F", 279, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-14T00:00:00", "15 19 24 40 47", "50", null ] -, [ 280, "B76A1E6C-C254-4CB3-AA0B-9E3D49472813", 280, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-18T00:00:00", "10 23 28 39 51", "05", null ] -, [ 281, "AF46D29A-1B37-4EEC-B4A5-E3B21DB5673A", 281, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-21T00:00:00", "17 27 39 40 41", "21", null ] -, [ 282, "929C4BC0-B7DC-458C-9230-1D510E57F709", 282, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-25T00:00:00", "02 10 21 25 45", "22", null ] -, [ 283, "AAF2C647-D464-4385-B732-B49913AF69CB", 283, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-01-28T00:00:00", "25 31 39 47 52", "43", null ] -, [ 284, "F1AF9F93-409C-4418-BCD8-390EA73B9336", 284, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-01T00:00:00", "03 17 21 42 44", "35", null ] -, [ 285, "DED59622-8D29-4664-8398-9FE120A46A87", 285, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-04T00:00:00", "03 12 14 30 52", "34", null ] -, [ 286, "6301C513-1F63-465C-9077-8FB388B4CEB4", 286, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-08T00:00:00", "08 11 14 23 25", "21", null ] -, [ 287, "B2F3018C-414F-4556-8635-405C6ADA0F10", 287, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-11T00:00:00", "06 14 21 24 50", "28", null ] -, [ 288, "12E0E1A8-1F85-4A57-B608-AD5AB2420CBF", 288, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-15T00:00:00", "03 16 20 21 38", "10", null ] -, [ 289, "82FC585B-BAAD-4725-A657-9646108D5DC4", 289, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-18T00:00:00", "01 19 31 35 42", "34", null ] -, [ 290, "5C140B83-2CEA-4985-B28B-663F7B5BABF3", 290, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-22T00:00:00", "15 18 28 41 45", "27", null ] -, [ 291, "4ADFED3A-9CF7-4D7B-A2CC-5A8F2053B472", 291, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-02-25T00:00:00", "04 13 37 38 50", "24", null ] -, [ 292, "1D4741B1-E68A-413C-B3BB-C403DB0C17DE", 292, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-01T00:00:00", "01 08 18 39 48", "01", null ] -, [ 293, "74C81011-F2BF-4720-B210-7743B22FBE8D", 293, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-04T00:00:00", "07 10 13 35 39", "21", null ] -, [ 294, "9B80E24B-1B29-406D-B39D-92CE0D9D84F3", 294, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-08T00:00:00", "08 14 15 22 31", "13", null ] -, [ 295, "31DF6251-BA07-45B6-A2F6-2C697D00C48E", 295, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-11T00:00:00", "18 19 31 35 36", "17", null ] -, [ 296, "708C6B64-35A2-42C9-8647-351C4BD30FDC", 296, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-15T00:00:00", "14 26 27 34 44", "27", null ] -, [ 297, "38357837-482D-41DD-AFD4-4AE48DF385CC", 297, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-18T00:00:00", "02 09 28 29 48", "33", null ] -, [ 298, "A7FA5D10-0B55-4947-B720-7C94D3610337", 298, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-22T00:00:00", "06 11 27 37 43", "34", null ] -, [ 299, "434ED7A8-6257-46F4-BBCC-D8A674C356F8", 299, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-25T00:00:00", "11 18 19 45 49", "02", null ] -, [ 300, "6CD696BD-A80A-44B1-B77D-FA1FF25E0F08", 300, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-03-29T00:00:00", "07 17 18 30 42", "38", null ] -, [ 301, "8CF288D1-0C69-4693-BE90-551A8127B384", 301, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-01T00:00:00", "11 19 28 32 45", "10", null ] -, [ 302, "8012F879-2E18-42E2-8711-19BE5F70B358", 302, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-05T00:00:00", "04 19 45 51 52", "22", null ] -, [ 303, "9B2671A2-C2BB-4A10-8205-F717FE4F741D", 303, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-08T00:00:00", "05 13 17 33 35", "35", null ] -, [ 304, "EDFB6722-641F-4EEC-B91C-EE7FE6E42B8F", 304, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-12T00:00:00", "15 20 43 47 50", "24", null ] -, [ 305, "37447A5F-204E-4912-9E95-5F017C168136", 305, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-15T00:00:00", "25 26 37 39 49", "29", null ] -, [ 306, "8E386A7C-E59E-42AA-B564-ECB8A4C383AA", 306, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-19T00:00:00", "05 06 14 42 47", "03", null ] -, [ 307, "0838C56E-BD1F-4819-9E52-2B4BFFDFDF66", 307, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-22T00:00:00", "23 25 43 46 49", "26", null ] -, [ 308, "559B2A64-C329-4BA1-9EE3-5B56BD11C81F", 308, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-26T00:00:00", "18 22 33 34 42", "16", null ] -, [ 309, "FE0AA6EB-B376-44B9-AB47-E2BA73934853", 309, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-04-29T00:00:00", "02 05 07 28 46", "21", null ] -, [ 310, "DC01C25F-6D99-46FE-A4A6-860DED5F011C", 310, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-03T00:00:00", "07 17 42 46 52", "47", null ] -, [ 311, "AA1EB43B-E2E0-403D-9D39-6B236AC3DE50", 311, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-06T00:00:00", "07 12 25 50 51", "19", null ] -, [ 312, "54907768-39E9-493F-B79D-54DD04E476F2", 312, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-10T00:00:00", "11 25 38 40 42", "40", null ] -, [ 313, "2EACE389-A6DB-459C-ADC5-AF98F96E5DC3", 313, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-13T00:00:00", "21 23 27 33 39", "08", null ] -, [ 314, "D0011038-F7E8-4ED5-A95E-EB30C075C01F", 314, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-17T00:00:00", "07 09 10 29 44", "17", null ] -, [ 315, "0695D550-C28B-4362-B428-CF02186E3AC6", 315, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-20T00:00:00", "03 06 27 40 44", "09", null ] -, [ 316, "F317FFE5-E091-476C-9ABA-DF9FF531C6D3", 316, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-24T00:00:00", "09 28 39 40 45", "24", null ] -, [ 317, "2CE91E33-2D19-4741-B712-B5A37A853E80", 317, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-27T00:00:00", "07 17 22 34 50", "24", null ] -, [ 318, "272EB917-BC29-44A6-B42F-2B1234927DB8", 318, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-05-31T00:00:00", "05 13 22 37 38", "11", null ] -, [ 319, "2C09A590-CE5E-4B0E-A216-49D6C1E2ED31", 319, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-03T00:00:00", "04 06 14 28 47", "42", null ] -, [ 320, "13B8AB19-B7DA-4DE8-B1FA-2F7B5C73B852", 320, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-07T00:00:00", "07 14 28 46 47", "25", null ] -, [ 321, "DE848D9F-40C5-4491-AFC6-66337901C5E2", 321, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-10T00:00:00", "14 29 31 37 50", "34", null ] -, [ 322, "B5DDE7DA-82E4-452E-AD3C-D0133EBC32E0", 322, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-14T00:00:00", "01 10 29 48 49", "36", null ] -, [ 323, "2B861970-45DA-4DD9-82B1-35FE957B34DE", 323, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-17T00:00:00", "16 35 40 49 50", "34", null ] -, [ 324, "B3FED69E-5468-4985-B4DC-89D71F6C06B0", 324, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-21T00:00:00", "09 13 40 46 50", "30", null ] -, [ 325, "033A0BD1-1324-4D5D-8409-6EE08E820D5E", 325, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-24T00:00:00", "14 43 44 50 56", "07", null ] -, [ 326, "83865852-9E82-454A-8334-B8E457FD5564", 326, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-06-28T00:00:00", "02 20 37 43 46", "04", null ] -, [ 327, "9AE7DD16-ABF4-4A5C-B036-1E3767164646", 327, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-01T00:00:00", "14 25 41 42 50", "40", null ] -, [ 328, "FAFFAC8C-2539-4ABC-AC83-F31E4745CD88", 328, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-05T00:00:00", "22 38 48 50 55", "29", null ] -, [ 329, "D031E86C-7BFC-46B8-8434-5ED4A422E3D5", 329, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-08T00:00:00", "09 23 45 48 50", "03", null ] -, [ 330, "A0C46007-15B5-428F-B3F9-65FE8F129069", 330, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-12T00:00:00", "05 17 32 39 53", "36", null ] -, [ 331, "F7E1B862-C554-4C22-BAA4-ACDDAC559AD7", 331, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-15T00:00:00", "09 13 25 36 48", "02", null ] -, [ 332, "C050912D-7E3B-4F8F-9317-51BDD65FE247", 332, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-19T00:00:00", "07 13 48 51 54", "11", null ] -, [ 333, "4DA6DF81-0826-413E-A33B-B149B510AA59", 333, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-22T00:00:00", "07 18 27 35 54", "34", null ] -, [ 334, "C43C9B1C-17E5-4148-BA4B-E5CEB3525941", 334, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-26T00:00:00", "01 10 18 29 55", "08", null ] -, [ 335, "561F43EE-FD24-4908-8042-F110C9D7FC98", 335, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-07-29T00:00:00", "04 16 23 25 40", "22", null ] -, [ 336, "13D5FF40-2E43-4A28-9FD9-E95FB19FE2AC", 336, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-02T00:00:00", "17 22 39 50 52", "46", null ] -, [ 337, "8B10E7B4-B3C5-4BCF-A62D-5B8BA3DE8355", 337, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-05T00:00:00", "03 05 48 50 53", "04", null ] -, [ 338, "E035770B-AAC3-40BC-AD66-E0D9E64372BC", 338, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-09T00:00:00", "13 35 36 43 52", "05", null ] -, [ 339, "0BC13F6C-2DF9-4834-B3D4-34F4E52DB6A0", 339, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-12T00:00:00", "08 37 38 45 54", "21", null ] -, [ 340, "40D316EA-945A-4584-A463-B7220694F598", 340, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-16T00:00:00", "09 15 20 24 55", "03", null ] -, [ 341, "2ECD8059-BFAD-4A9B-971E-C276188878C7", 341, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-19T00:00:00", "02 13 18 36 46", "36", null ] -, [ 342, "09F9240B-DF24-4C16-B8CB-813998920F64", 342, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-23T00:00:00", "06 07 08 13 40", "12", null ] -, [ 343, "08DC3E31-889F-4A80-9874-1A4FE05CFBF8", 343, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-26T00:00:00", "05 20 38 47 54", "35", null ] -, [ 344, "DFD70689-7341-47CD-B95F-BFE2D51D32C2", 344, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-08-30T00:00:00", "19 32 42 49 56", "29", null ] -, [ 345, "E5B9F273-A709-4583-8047-6FD74DE24846", 345, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-02T00:00:00", "01 04 14 45 53", "33", null ] -, [ 346, "ACC92702-99C0-4E8D-9C4D-5AF531E3E469", 346, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-06T00:00:00", "01 08 27 31 50", "40", null ] -, [ 347, "FC9EB200-2DF5-41F0-ABA3-AE199C366FF6", 347, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-09T00:00:00", "15 28 43 51 52", "11", null ] -, [ 348, "747A6C12-78D5-4FEF-8B8A-EF0FA8A3BC02", 348, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-13T00:00:00", "13 24 44 48 52", "30", null ] -, [ 349, "E81382F7-026A-4F8A-B94F-A37CCC4DCCD3", 349, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-16T00:00:00", "05 16 41 46 50", "01", null ] -, [ 350, "7ED2D57E-9121-440C-AA0F-C6B024E372EE", 350, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-20T00:00:00", "35 36 40 42 52", "45", null ] -, [ 351, "7328006D-B455-4A06-B68A-89FC788CBAFD", 351, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-23T00:00:00", "06 07 20 41 51", "38", null ] -, [ 352, "A9052160-FF2E-4C2F-8B1F-BFE55B0BD024", 352, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-27T00:00:00", "14 17 26 27 28", "05", null ] -, [ 353, "5A153CDF-3CB1-47D0-8242-899326BD456C", 353, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-09-30T00:00:00", "01 03 14 30 52", "10", null ] -, [ 354, "FE7185D0-A535-45CB-A6CC-01A0B09D6346", 354, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-04T00:00:00", "12 24 28 29 36", "41", null ] -, [ 355, "0ACAA2C4-D8AD-489E-8969-41FD4F1DA446", 355, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-07T00:00:00", "02 04 23 27 36", "37", null ] -, [ 356, "125F6530-E5F5-46C0-AEAA-67800AB47EBA", 356, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-11T00:00:00", "24 30 42 53 54", "20", null ] -, [ 357, "8AEE764F-10C9-4487-A4A7-BCC7B7432F4D", 357, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-14T00:00:00", "06 20 24 25 34", "44", null ] -, [ 358, "D1B8530E-5CE8-4CF8-9D8A-3E78F6D9711D", 358, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-18T00:00:00", "03 12 16 32 33", "15", null ] -, [ 359, "7FB69C53-5BCC-4612-963F-22A0FBE0D366", 359, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-21T00:00:00", "11 17 28 29 36", "42", null ] -, [ 360, "099CE0AD-F072-4A7F-9E16-24F9E265983B", 360, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-25T00:00:00", "07 12 18 31 55", "30", null ] -, [ 361, "82BD5396-346A-4808-8568-6DF24372709F", 361, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-10-28T00:00:00", "08 17 25 28 53", "01", null ] -, [ 362, "163D026B-60CB-4B09-B6C4-A7488308DD8E", 362, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-01T00:00:00", "05 18 21 28 36", "20", null ] -, [ 363, "2E75AF04-00FF-4E0E-BF24-395B9FB275E3", 363, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-04T00:00:00", "07 09 41 53 54", "38", null ] -, [ 364, "FC2FA6E3-E70C-4A4B-9F64-0FC75AC6BECF", 364, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-08T00:00:00", "08 16 21 25 27", "16", null ] -, [ 365, "B05C3588-63F4-4918-9A0B-22DC5BF62C32", 365, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-11T00:00:00", "09 14 34 50 51", "40", null ] -, [ 366, "97A88400-902F-44B4-A497-38AAAB38B7C5", 366, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-15T00:00:00", "02 04 05 40 48", "07", null ] -, [ 367, "2D471B32-ABF6-47E8-9B85-DE9BA6052D75", 367, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-18T00:00:00", "08 18 21 42 46", "11", null ] -, [ 368, "E21BBAC7-6A3A-411D-8328-9A3DAC360F70", 368, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-22T00:00:00", "09 22 37 41 43", "30", null ] -, [ 369, "F2DA346E-8664-43BC-8067-BF6F81FD71AD", 369, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-25T00:00:00", "05 25 31 33 34", "41", null ] -, [ 370, "3D150C47-1D71-4F59-9FAB-950EE578B141", 370, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-11-29T00:00:00", "07 08 47 51 52", "05", null ] -, [ 371, "D6D3E5D9-0AB1-41DD-88B8-70586D133D1E", 371, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-02T00:00:00", "03 12 21 38 44", "45", null ] -, [ 372, "C5BB8996-A321-4F80-BC0D-C2D880384DF1", 372, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-06T00:00:00", "06 10 26 30 33", "16", null ] -, [ 373, "F7F985C7-C509-4D77-B34A-FE8512F24EB3", 373, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-09T00:00:00", "14 15 31 32 43", "20", null ] -, [ 374, "90F85C5C-CDB9-42BE-AC2B-A7ADC515BAB2", 374, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-13T00:00:00", "09 10 12 22 41", "04", null ] -, [ 375, "F2ED349C-1FE5-4F23-BF41-D9D0CF91D948", 375, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-16T00:00:00", "14 25 26 31 56", "17", null ] -, [ 376, "156ED523-B9AE-4F78-9EA6-8AB545668B5C", 376, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-20T00:00:00", "06 20 23 40 56", "36", null ] -, [ 377, "16299179-341A-48BF-B14D-4F78593B59CA", 377, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-23T00:00:00", "10 37 39 49 54", "08", null ] -, [ 378, "F3F9CA26-835C-4F9F-AE53-9870DF0E82CB", 378, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-27T00:00:00", "11 24 27 49 55", "23", null ] -, [ 379, "E3B45416-2CE2-4FB7-9226-339ABDCF13D3", 379, 1362743863, "706580", 1362743863, "706580", "{\n}", "2005-12-30T00:00:00", "14 20 25 40 44", "37", null ] -, [ 380, "29E99521-1745-4BEA-8379-32E8A3B4EB71", 380, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-03T00:00:00", "15 19 20 32 38", "21", null ] -, [ 381, "23A4CE2F-D83A-4A90-9099-B224EDFCBD09", 381, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-06T00:00:00", "08 11 28 37 53", "12", null ] -, [ 382, "0BDE11E7-43EB-45A4-A01C-D8E922694253", 382, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-10T00:00:00", "07 27 32 37 38", "30", null ] -, [ 383, "167D5629-9E1C-4611-B2AE-2315FA48DCE5", 383, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-13T00:00:00", "05 21 27 44 53", "36", null ] -, [ 384, "0CA5B072-5559-4DA7-854A-560FAB3A1F9A", 384, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-17T00:00:00", "24 32 37 39 40", "44", null ] -, [ 385, "0359B182-D50B-48FF-A09F-D183DFD79088", 385, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-20T00:00:00", "18 22 28 44 53", "46", null ] -, [ 386, "D67E15A1-07AA-4C5F-83D3-E48B6CD1036C", 386, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-24T00:00:00", "31 34 36 51 55", "04", null ] -, [ 387, "CBE69F65-752B-4F95-A6E0-3D352BD3D73F", 387, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-27T00:00:00", "02 07 08 18 29", "46", null ] -, [ 388, "D9F7E97F-227D-443B-8981-FA36E63E6BE4", 388, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-01-31T00:00:00", "01 35 53 54 56", "44", null ] -, [ 389, "1064AE8D-A39B-4902-B11F-DA839EE81966", 389, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-03T00:00:00", "29 31 32 41 52", "42", null ] -, [ 390, "5C5F012B-1868-4006-BDF1-0C77C004B068", 390, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-07T00:00:00", "02 16 25 30 48", "26", null ] -, [ 391, "C8BCF21E-FA5E-46D6-9D6D-47E33673FD84", 391, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-10T00:00:00", "24 39 40 43 46", "02", null ] -, [ 392, "7B16B91E-5DAD-429E-B56A-308A7CC4F3C2", 392, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-14T00:00:00", "27 36 43 49 54", "33", null ] -, [ 393, "2C55BB3E-91D2-4E1A-90F9-99DBF303C292", 393, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-17T00:00:00", "16 25 31 43 46", "28", null ] -, [ 394, "DFF595AC-6BA2-400E-AFEA-684B14DB0ED7", 394, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-21T00:00:00", "14 23 27 36 45", "36", null ] -, [ 395, "D26EBE63-5EF4-428D-A3B9-E899335A7BF8", 395, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-24T00:00:00", "03 05 12 16 34", "27", null ] -, [ 396, "B75EBDD7-F67B-43ED-A426-204C3005ACBB", 396, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-02-28T00:00:00", "02 04 35 36 48", "22", null ] -, [ 397, "813AA2A0-653B-4DEA-95BC-842A99C81DE7", 397, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-03T00:00:00", "25 29 38 39 46", "04", null ] -, [ 398, "527704D6-2E02-457B-8149-F47FC0C8EB5E", 398, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-07T00:00:00", "15 27 36 38 42", "32", null ] -, [ 399, "2A55196C-4775-443A-B52F-48221944909B", 399, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-10T00:00:00", "04 17 18 51 54", "31", null ] -, [ 400, "DB2E7BA4-1A59-4A27-969E-2177D00567A7", 400, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-14T00:00:00", "27 28 30 42 50", "22", null ] -, [ 401, "7D7FB09E-BFED-4940-BE40-800C9B8E72DA", 401, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-17T00:00:00", "08 11 23 48 52", "05", null ] -, [ 402, "3CE93466-1F2F-4464-AD81-EA76817D9D1E", 402, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-21T00:00:00", "04 16 17 28 31", "08", null ] -, [ 403, "0A400896-D7C6-4572-96D9-81D24A122EA5", 403, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-24T00:00:00", "01 02 17 47 49", "19", null ] -, [ 404, "94CA0CC7-8204-4018-B709-397559907294", 404, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-28T00:00:00", "14 18 35 39 49", "14", null ] -, [ 405, "F745FFDD-883A-4C3D-9360-71F3A83E00FD", 405, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-03-31T00:00:00", "04 07 19 50 52", "15", null ] -, [ 406, "29EAB288-7556-4FCF-8189-080D1B2A59C0", 406, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-04T00:00:00", "09 25 48 51 56", "07", null ] -, [ 407, "CD488BBE-ACB3-40B0-BB7E-271B098F29DA", 407, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-07T00:00:00", "01 18 31 46 52", "37", null ] -, [ 408, "1DA1A60A-B1C2-426E-8852-9D39DBAEA790", 408, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-11T00:00:00", "02 12 45 46 56", "20", null ] -, [ 409, "93D317B3-E6EC-42D8-81AF-F2647E15F1C5", 409, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-14T00:00:00", "08 10 18 29 33", "10", null ] -, [ 410, "BA283EA9-2AD9-4E97-BB8A-3AC557F746DA", 410, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-18T00:00:00", "13 14 25 34 50", "06", null ] -, [ 411, "F3E9328B-F020-4C2E-AA17-08D20F513104", 411, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-21T00:00:00", "02 04 07 27 41", "04", null ] -, [ 412, "40BCF77C-5836-4312-A4DB-B307424B6DDE", 412, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-25T00:00:00", "01 20 32 37 39", "09", null ] -, [ 413, "25AEE37E-66F3-4507-86CB-1A787D01CD22", 413, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-04-28T00:00:00", "16 29 32 36 55", "12", null ] -, [ 414, "0D65468E-A001-4953-B9D7-3673D895BA94", 414, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-02T00:00:00", "07 11 22 27 31", "33", null ] -, [ 415, "3E43C068-9C2A-4A98-BD64-67B25F5385E9", 415, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-05T00:00:00", "08 20 39 53 55", "10", null ] -, [ 416, "196933EB-DC89-4F74-9489-4ADB3F0CB2D1", 416, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-09T00:00:00", "07 15 24 43 44", "22", null ] -, [ 417, "88B1ECC7-7F6D-46B3-B60A-8B2FE334AC29", 417, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-12T00:00:00", "06 36 39 45 52", "45", null ] -, [ 418, "69578B1A-F682-478A-B16F-786D601FB0D1", 418, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-16T00:00:00", "07 24 40 48 50", "15", null ] -, [ 419, "BA8F27F9-D6C8-4965-AFC6-C307D9377569", 419, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-19T00:00:00", "05 12 31 51 56", "01", null ] -, [ 420, "FDCA3825-57D6-4B86-8BFB-65FF69D2F961", 420, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-23T00:00:00", "17 21 28 48 54", "01", null ] -, [ 421, "DD8D9CD4-0283-4839-87A0-D018E4E994AE", 421, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-26T00:00:00", "12 14 20 47 48", "24", null ] -, [ 422, "287A016B-D049-48B5-AA90-BD3215D46D66", 422, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-05-30T00:00:00", "02 13 28 34 45", "36", null ] -, [ 423, "8FF174E9-FC60-48BE-832B-F1C2F283EC7D", 423, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-02T00:00:00", "03 10 18 36 38", "41", null ] -, [ 424, "74BD27FB-1F58-4935-9B0F-201B7394009D", 424, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-06T00:00:00", "05 29 35 52 53", "09", null ] -, [ 425, "9E40B131-700A-4BF5-924D-372AA99C2EEC", 425, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-09T00:00:00", "08 17 18 26 47", "37", null ] -, [ 426, "91BC5C38-BEFD-450E-B343-CF9C22ED4D37", 426, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-13T00:00:00", "01 20 23 24 33", "29", null ] -, [ 427, "26FA79C8-F2D2-4D0E-B2B8-592180AD8EA6", 427, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-16T00:00:00", "27 30 36 38 45", "13", null ] -, [ 428, "4C517676-2FE5-4574-8D14-60D2A7A470EA", 428, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-20T00:00:00", "11 21 37 53 54", "12", null ] -, [ 429, "137CCAD7-CCDD-47CF-8526-99BF3D6E13B6", 429, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-23T00:00:00", "13 17 24 34 56", "24", null ] -, [ 430, "3172D8F0-00D6-41EC-A33C-39DFACD85C54", 430, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-27T00:00:00", "02 14 20 29 44", "32", null ] -, [ 431, "721F7AD5-4110-4BA1-A481-4B872481540C", 431, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-06-30T00:00:00", "20 40 46 48 54", "27", null ] -, [ 432, "A3BCAF71-6B04-46AB-9DAF-C6F2AFCDDB22", 432, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-04T00:00:00", "09 15 31 42 45", "41", null ] -, [ 433, "3F716DED-DCC8-4F23-8654-A4AA0CE1F7BB", 433, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-07T00:00:00", "07 15 27 46 56", "39", null ] -, [ 434, "69D46A31-8B5E-46F0-BCFC-64804619BB0D", 434, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-11T00:00:00", "05 14 34 36 52", "42", null ] -, [ 435, "B0FC844B-8408-4DE9-8B9D-036CEA4A52D6", 435, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-14T00:00:00", "13 25 26 28 56", "39", null ] -, [ 436, "B9632DEA-2612-48E7-BFFF-59CCF6D7B195", 436, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-18T00:00:00", "12 13 29 49 52", "20", null ] -, [ 437, "AA05FDD3-F33B-445C-81D0-417531FFCAEE", 437, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-21T00:00:00", "18 26 35 36 43", "24", null ] -, [ 438, "B95A74B3-8357-48CA-81A6-08378A45C791", 438, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-25T00:00:00", "07 21 24 41 51", "10", null ] -, [ 439, "000D3A35-CA16-49E7-9989-E533E90F9B86", 439, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-07-28T00:00:00", "02 13 23 32 35", "04", null ] -, [ 440, "8BE39A1F-6479-4904-94C5-17761E012833", 440, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-01T00:00:00", "14 29 32 43 49", "14", null ] -, [ 441, "5D1B112D-E76B-4363-84E3-8F30AB59A225", 441, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-04T00:00:00", "02 24 31 50 55", "44", null ] -, [ 442, "FF4C81A1-0886-492A-A7E6-7E811B7618BE", 442, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-08T00:00:00", "01 05 13 18 33", "30", null ] -, [ 443, "6914B454-3487-4CF9-A7B3-E71B73DFC240", 443, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-11T00:00:00", "14 16 38 40 49", "29", null ] -, [ 444, "FD7B124A-D7D9-4769-8293-EE137100046F", 444, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-15T00:00:00", "10 12 22 44 48", "16", null ] -, [ 445, "1310D87A-CE78-4DEF-8C82-7D5C4F107A78", 445, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-18T00:00:00", "05 12 13 46 50", "10", null ] -, [ 446, "64AF74E8-B273-406F-A65B-21FF45A6EE97", 446, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-22T00:00:00", "03 04 05 07 36", "16", null ] -, [ 447, "FD99C149-C6DF-4716-9303-6CAE04DBC69B", 447, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-25T00:00:00", "17 24 35 46 54", "33", null ] -, [ 448, "4828E912-24A4-4EE2-A1EC-F4DD9C4D34F4", 448, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-08-29T00:00:00", "15 25 37 38 52", "04", null ] -, [ 449, "876BD770-0F17-4A55-9D1D-859ED0E71E43", 449, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-01T00:00:00", "05 06 51 53 55", "12", null ] -, [ 450, "3B501C09-05A2-4D12-988F-89CB2F762C24", 450, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-05T00:00:00", "01 32 36 42 53", "04", null ] -, [ 451, "81E6F31E-DF5C-43F6-A728-05585313E815", 451, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-08T00:00:00", "09 17 34 52 53", "02", null ] -, [ 452, "6EA79B46-5FC5-4A69-9233-944BAD07ADD7", 452, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-12T00:00:00", "03 16 25 30 44", "42", null ] -, [ 453, "009A90F0-5559-4268-987F-F6B82ECE62E8", 453, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-15T00:00:00", "06 26 33 39 55", "01", null ] -, [ 454, "E4BE828E-96E8-49C9-8CD3-22D163F8CA95", 454, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-19T00:00:00", "02 19 44 45 56", "43", null ] -, [ 455, "64115699-83B2-4A2F-AFCD-DB780FBF6EA4", 455, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-22T00:00:00", "07 12 17 22 43", "16", null ] -, [ 456, "F292063C-3138-4F0F-89CB-46D26C3A0458", 456, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-26T00:00:00", "03 06 38 42 45", "30", null ] -, [ 457, "012D91E0-729E-4072-B587-0BE7EAE01E69", 457, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-09-29T00:00:00", "03 25 43 45 55", "40", null ] -, [ 458, "6118DFB2-98F1-4083-917F-BEAB59C88D79", 458, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-03T00:00:00", "06 19 32 33 40", "39", null ] -, [ 459, "FEC3AA53-F3BC-4C7E-BFFD-094D134652ED", 459, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-06T00:00:00", "01 11 20 21 46", "18", null ] -, [ 460, "F59A1C13-3CA5-494D-92DE-A0D739B44578", 460, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-10T00:00:00", "14 30 35 40 43", "02", null ] -, [ 461, "261C39D5-E5FD-4454-A417-242D7D090B55", 461, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-13T00:00:00", "24 27 42 47 50", "08", null ] -, [ 462, "B36A2C2B-9501-4AF9-9754-8CE90B5BB31D", 462, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-17T00:00:00", "06 18 20 28 38", "37", null ] -, [ 463, "A7753123-848A-4066-A8AA-074FED6A5805", 463, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-20T00:00:00", "09 13 23 29 54", "34", null ] -, [ 464, "92DBCCC3-793A-427F-98BA-BBFECD7D078F", 464, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-24T00:00:00", "05 25 41 48 51", "35", null ] -, [ 465, "C5C9129D-0DDD-493C-BF76-FA9FF1B6918E", 465, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-27T00:00:00", "15 22 26 30 32", "31", null ] -, [ 466, "57CBB0CC-1645-46DB-9309-CC7BADDA9930", 466, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-10-31T00:00:00", "05 34 40 45 46", "21", null ] -, [ 467, "E35554AE-5653-4D27-949A-AEC4E3F061C9", 467, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-03T00:00:00", "08 10 22 25 55", "22", null ] -, [ 468, "2BEDBC19-AD7E-4DB0-806E-DFC3AC9695E5", 468, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-07T00:00:00", "13 22 33 51 52", "42", null ] -, [ 469, "A314EFBF-2B15-4FE9-B159-6AFAFE253953", 469, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-10T00:00:00", "11 42 52 53 55", "28", null ] -, [ 470, "3FE5905D-6A77-4DA2-BD41-97A8C35EA4A1", 470, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-14T00:00:00", "09 20 24 25 36", "23", null ] -, [ 471, "659F5995-2816-4F6D-B416-CA6202070B2F", 471, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-17T00:00:00", "05 19 25 30 50", "42", null ] -, [ 472, "596964AA-A8EC-4EF1-ABE1-88CEB210AC0F", 472, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-21T00:00:00", "07 13 20 42 47", "09", null ] -, [ 473, "65E180A1-4FDA-45E5-8527-D9CB3B9E06E9", 473, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-24T00:00:00", "14 35 40 47 48", "35", null ] -, [ 474, "5C995EB5-EDEA-4321-A9C3-56800D99F0BB", 474, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-11-28T00:00:00", "07 14 24 41 56", "07", null ] -, [ 475, "D130CD7B-53CD-472A-96DD-4D212DA0A53C", 475, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-01T00:00:00", "16 22 23 37 53", "35", null ] -, [ 476, "12FF9A05-37ED-4075-9439-04420AB4FCAB", 476, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-05T00:00:00", "06 09 13 43 46", "45", null ] -, [ 477, "2B26456D-4358-48A2-9B1B-DAEF68AB717B", 477, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-08T00:00:00", "01 15 29 32 45", "08", null ] -, [ 478, "1E3EDF59-31DC-4911-BB35-7D976DD611A9", 478, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-12T00:00:00", "20 30 31 35 49", "23", null ] -, [ 479, "C61F4D38-2EDD-4B77-9E83-2D02D4832CF7", 479, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-15T00:00:00", "06 07 17 28 40", "39", null ] -, [ 480, "E396FD08-5E4E-4150-BF25-753BF3B5338A", 480, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-19T00:00:00", "09 32 37 42 48", "07", null ] -, [ 481, "63BBEEBB-8051-4F72-AF25-8082D26CE558", 481, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-22T00:00:00", "05 12 15 25 34", "43", null ] -, [ 482, "0BDAA512-21EC-4665-8093-EF7813E19536", 482, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-26T00:00:00", "07 12 25 44 53", "03", null ] -, [ 483, "A2C16873-A6C5-4DD5-BED8-0774D4C51A6E", 483, 1362743863, "706580", 1362743863, "706580", "{\n}", "2006-12-29T00:00:00", "03 04 10 39 50", "29", null ] -, [ 484, "80DFE370-F29E-4FC6-ADD9-D2E1C6F285DF", 484, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-02T00:00:00", "09 10 38 51 53", "01", null ] -, [ 485, "1F4F9085-9D5D-4154-A7C9-07CC14B1360F", 485, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-05T00:00:00", "02 12 44 46 51", "06", null ] -, [ 486, "1C804255-DD48-459F-80B2-9A2A51F000E2", 486, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-09T00:00:00", "07 11 26 38 54", "13", null ] -, [ 487, "F2168D7F-692D-49E8-9BBD-9BAF919A429C", 487, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-12T00:00:00", "12 14 26 40 42", "22", null ] -, [ 488, "82A04EF2-AFDB-43AB-9AD5-35B5A52B0C7C", 488, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-16T00:00:00", "04 08 15 33 52", "10", null ] -, [ 489, "87CD8B58-A34F-447F-B738-338FAEA4ADA6", 489, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-19T00:00:00", "04 28 30 31 35", "17", null ] -, [ 490, "DFC10A63-3A94-4758-B7AE-72783F703352", 490, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-23T00:00:00", "03 05 15 26 53", "35", null ] -, [ 491, "A70BB32D-39D8-4140-8388-8FA026770676", 491, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-26T00:00:00", "16 17 36 49 54", "14", null ] -, [ 492, "63210A51-5D26-4FC2-BEFB-C39A41B76188", 492, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-01-30T00:00:00", "14 18 44 52 56", "25", null ] -, [ 493, "357413EB-414B-45C1-BE01-6C7811EFD331", 493, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-02T00:00:00", "22 33 35 40 53", "15", null ] -, [ 494, "B0C7B36A-3BC6-4A2D-B61B-CF6D59A2DE5D", 494, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-06T00:00:00", "16 21 35 36 46", "38", null ] -, [ 495, "44CD2B3C-DD2A-497D-9878-F4B724DF0C4F", 495, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-09T00:00:00", "32 39 46 48 49", "41", null ] -, [ 496, "7AE39468-C494-4058-BA75-4DC65DD0B14C", 496, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-13T00:00:00", "03 09 24 29 41", "41", null ] -, [ 497, "87D2E024-815A-486D-854E-3AE38F88E25B", 497, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-16T00:00:00", "17 35 40 46 48", "41", null ] -, [ 498, "29043663-7DA3-4E24-B131-FFD830CB4559", 498, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-20T00:00:00", "01 09 26 46 51", "11", null ] -, [ 499, "F1966050-1B54-4E51-BA1D-01D4885FF55A", 499, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-23T00:00:00", "03 18 21 38 50", "43", null ] -, [ 500, "CDC0E58D-A787-443D-B091-4C7B526B428E", 500, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-02-27T00:00:00", "18 31 44 45 48", "18", null ] -, [ 501, "027B2C00-9225-4D2C-BD32-40D24F18857C", 501, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-02T00:00:00", "14 21 33 35 51", "43", null ] -, [ 502, "3CCD3436-51C5-4009-8F83-0B6E1A2D9621", 502, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-06T00:00:00", "16 22 29 39 42", "20", null ] -, [ 503, "7EA1C45C-B586-4EE4-B220-2148621ABDF8", 503, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-09T00:00:00", "10 13 25 42 43", "30", null ] -, [ 504, "A328A035-D9CF-4A90-95F9-9E2B40EBA016", 504, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-13T00:00:00", "07 11 16 38 49", "35", null ] -, [ 505, "33DCB90F-A257-49AE-9BB5-C856E3519522", 505, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-16T00:00:00", "17 25 36 40 43", "09", null ] -, [ 506, "21F3B240-0B45-4F71-9511-B94C977B4A21", 506, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-20T00:00:00", "07 21 46 49 55", "15", null ] -, [ 507, "11C3082B-C804-4EB8-9B39-67548771671E", 507, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-23T00:00:00", "18 21 35 51 53", "36", null ] -, [ 508, "32E540A6-D425-404E-B2AD-0FEEC35D2F91", 508, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-27T00:00:00", "18 25 34 35 42", "06", null ] -, [ 509, "E6A20F49-B5F1-472B-BB7D-B06DD124AEFA", 509, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-03-30T00:00:00", "15 23 37 48 53", "22", null ] -, [ 510, "625A06C6-8963-4251-A51B-3229701ED972", 510, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-03T00:00:00", "16 26 33 34 46", "38", null ] -, [ 511, "CCDC57D2-0595-410A-8F16-5658A0715D7C", 511, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-06T00:00:00", "24 32 34 36 39", "06", null ] -, [ 512, "533647E4-C13D-4E9B-BAD2-3A3884B4BBC1", 512, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-10T00:00:00", "07 15 16 19 28", "10", null ] -, [ 513, "00A3835B-5630-4CE3-884E-8A721832B485", 513, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-13T00:00:00", "11 14 21 25 26", "33", null ] -, [ 514, "B05BDA43-8F9E-4780-A687-31592ADF193C", 514, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-17T00:00:00", "01 04 11 31 47", "37", null ] -, [ 515, "B0D1A237-A2D2-49DB-942F-04CF6403DDAF", 515, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-20T00:00:00", "01 09 10 23 53", "40", null ] -, [ 516, "CF0C9918-32B2-43E0-B1AA-BC8836DD8AAF", 516, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-24T00:00:00", "08 10 35 36 43", "14", null ] -, [ 517, "4860C387-45D4-43C8-9513-AA13684C6E55", 517, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-04-27T00:00:00", "05 07 26 38 56", "15", null ] -, [ 518, "8BBFFBDD-860A-46F4-9E37-899211A77BDE", 518, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-01T00:00:00", "11 16 31 52 53", "42", null ] -, [ 519, "9AA8796F-0E60-41D3-BEA8-DC65B72C0F9F", 519, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-04T00:00:00", "04 09 20 45 55", "34", null ] -, [ 520, "327324DA-C32B-4FC1-A2C8-83442FC0B4DC", 520, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-08T00:00:00", "16 24 41 43 54", "36", null ] -, [ 521, "590CB81B-44B8-4275-BCE8-18C4D8F912BF", 521, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-11T00:00:00", "28 30 33 48 54", "25", null ] -, [ 522, "CB538DA0-BE56-4F97-8806-353E9E13934C", 522, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-15T00:00:00", "06 13 42 46 56", "42", null ] -, [ 523, "71BCFD52-BC6E-4E35-ACA1-8F10909971D4", 523, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-18T00:00:00", "13 23 24 30 44", "05", null ] -, [ 524, "919DB6FB-31C9-4682-878E-13CA05A4655B", 524, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-22T00:00:00", "02 07 11 22 36", "35", null ] -, [ 525, "305E9588-E64D-4C2D-A4EF-E5B78518793B", 525, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-25T00:00:00", "10 14 22 42 43", "01", null ] -, [ 526, "4719B10B-AD10-4D50-8D46-A0CAE5F605C8", 526, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-05-29T00:00:00", "02 24 44 51 54", "07", null ] -, [ 527, "1A71051C-3A19-4D8C-9385-479010DB22F9", 527, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-01T00:00:00", "12 19 29 32 48", "09", null ] -, [ 528, "F9374DC6-B1DD-46B1-85FC-D5CB57642F63", 528, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-05T00:00:00", "27 35 38 49 56", "15", null ] -, [ 529, "D7CA0C49-B9CB-4112-B9EB-7F8FCFAB6D3D", 529, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-08T00:00:00", "06 26 29 31 39", "31", null ] -, [ 530, "0227FE28-D804-4BD3-A030-4BB9FE984784", 530, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-12T00:00:00", "03 13 19 31 50", "21", null ] -, [ 531, "21A96721-FEC2-4209-A12E-58DEB0C25565", 531, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-15T00:00:00", "01 05 16 26 30", "21", null ] -, [ 532, "8B7CDDBD-DE8F-43C1-8432-4749207D9C90", 532, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-19T00:00:00", "05 16 31 49 54", "19", null ] -, [ 533, "40A021A2-FB3D-4F3E-8B75-53906F89BE63", 533, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-22T00:00:00", "11 14 21 24 31", "23", null ] -, [ 534, "219E423B-F4F8-4FED-8F15-DB0BAFF558B6", 534, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-26T00:00:00", "04 10 20 29 45", "21", null ] -, [ 535, "17E57B87-08C2-4C62-BDFD-23B8EA26B4D8", 535, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-06-29T00:00:00", "01 17 40 51 52", "07", null ] -, [ 536, "32A17E56-EBE7-4251-BD2A-D19BE4CB117D", 536, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-03T00:00:00", "21 35 37 39 40", "35", null ] -, [ 537, "E8DD110B-0D8B-408D-A8EA-7ACA299EA6C5", 537, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-06T00:00:00", "03 09 12 25 47", "37", null ] -, [ 538, "E251BA7F-0AFF-4C05-A888-BE5DB36870C8", 538, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-10T00:00:00", "19 24 30 34 56", "19", null ] -, [ 539, "8693C58E-FFB4-4391-89A4-CA39898C188B", 539, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-13T00:00:00", "07 39 41 48 53", "21", null ] -, [ 540, "FCA45A5C-8B1B-48AD-A423-9E6ACBD9FA39", 540, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-17T00:00:00", "16 30 38 46 51", "05", null ] -, [ 541, "6F819E39-2FC5-47B6-81BB-C07A9EE6AD78", 541, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-20T00:00:00", "06 13 30 41 52", "26", null ] -, [ 542, "935E5F56-B297-4BEF-AF4E-798BD16FB200", 542, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-24T00:00:00", "08 17 20 23 50", "17", null ] -, [ 543, "DCCBD8F4-950D-4DD4-8625-8CD371BF0537", 543, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-27T00:00:00", "07 12 35 54 55", "02", null ] -, [ 544, "C7946459-75F4-4873-B7A9-4B2D4117C172", 544, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-07-31T00:00:00", "05 18 37 39 43", "42", null ] -, [ 545, "5A5EC1A5-F598-49F8-B294-B0742BAB9FE8", 545, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-03T00:00:00", "16 29 42 46 51", "40", null ] -, [ 546, "733BBBEB-B041-4E3C-AC7F-B061D9FDC2E2", 546, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-07T00:00:00", "36 41 50 55 56", "09", null ] -, [ 547, "8CF32173-2825-4083-94EC-3CA62231EB32", 547, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-10T00:00:00", "10 20 32 33 54", "39", null ] -, [ 548, "71255C58-16DF-464C-9910-B7C5E9368B80", 548, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-14T00:00:00", "05 08 09 24 34", "17", null ] -, [ 549, "29B14293-5FF6-4A9B-8A6D-9F4979AC2A3C", 549, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-17T00:00:00", "02 08 33 38 53", "12", null ] -, [ 550, "DBCFD864-00A3-4C73-B98E-168D7C7A7298", 550, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-21T00:00:00", "08 38 54 55 56", "02", null ] -, [ 551, "71581616-86DC-43A6-8E97-EB71AC7EAF9E", 551, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-24T00:00:00", "04 21 46 51 53", "05", null ] -, [ 552, "395D50C8-FFDC-4EB7-9BED-D46B60EF4A4F", 552, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-28T00:00:00", "37 40 48 53 56", "44", null ] -, [ 553, "024142D8-A96F-48DB-A5CE-BD82D129A146", 553, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-08-31T00:00:00", "08 18 22 40 44", "11", null ] -, [ 554, "7C7DA9A9-8A93-4DEC-A838-25ADA4688FB0", 554, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-04T00:00:00", "03 06 11 42 46", "38", null ] -, [ 555, "0579315D-E2CF-49AF-885E-71B088019AF1", 555, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-07T00:00:00", "14 19 27 34 48", "03", null ] -, [ 556, "971171AF-EFBA-4484-A414-5B01B9452D5F", 556, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-11T00:00:00", "09 10 17 21 35", "06", null ] -, [ 557, "28285D15-4A1A-44D3-9333-8239592BDE99", 557, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-14T00:00:00", "05 09 12 33 40", "27", null ] -, [ 558, "94B57E37-496D-4389-ADE3-55BC6C5D2BC5", 558, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-18T00:00:00", "20 24 31 34 49", "08", null ] -, [ 559, "5BEA0A7E-308C-4AB5-9EB3-E7829A54DE9A", 559, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-21T00:00:00", "05 21 23 33 45", "43", null ] -, [ 560, "2E981127-7486-4C6B-A8B5-97AC12022114", 560, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-25T00:00:00", "02 19 23 47 54", "16", null ] -, [ 561, "5105617C-AB05-4AB1-8AF0-51695E69D2C2", 561, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-09-28T00:00:00", "04 13 20 25 33", "42", null ] -, [ 562, "2437D531-AB19-4459-A67A-121972794A47", 562, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-02T00:00:00", "28 37 40 43 44", "20", null ] -, [ 563, "27284339-0E47-4BA9-A613-AA77CDC172FB", 563, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-05T00:00:00", "10 19 37 40 48", "01", null ] -, [ 564, "E0DD475C-1A32-4FD7-931A-1ED646B58376", 564, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-09T00:00:00", "01 10 17 32 51", "44", null ] -, [ 565, "6EFE62AE-AE28-44F7-AA85-286B4D0C9282", 565, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-12T00:00:00", "21 26 34 44 54", "23", null ] -, [ 566, "D5D353C1-8580-4064-8E83-78A727163693", 566, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-16T00:00:00", "01 02 05 41 44", "25", null ] -, [ 567, "8A6A4478-06D9-4120-9D60-736EC2D928F4", 567, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-19T00:00:00", "05 15 18 23 46", "14", null ] -, [ 568, "89ED8174-0D4D-4DBB-BFA0-EEE2ED2A191A", 568, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-23T00:00:00", "02 07 45 52 53", "18", null ] -, [ 569, "A4FD154B-73D1-4BDB-ADE9-1DA2FC880D58", 569, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-26T00:00:00", "12 20 24 38 51", "03", null ] -, [ 570, "27BFB91C-1B21-42B2-B974-7BBF668A0B96", 570, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-10-30T00:00:00", "02 08 44 46 51", "22", null ] -, [ 571, "583F59AF-3EC3-4912-B2B2-456D72F114E0", 571, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-02T00:00:00", "01 03 34 49 52", "19", null ] -, [ 572, "5EF7A2A3-960B-42CA-8D65-8607614DF1CC", 572, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-06T00:00:00", "03 17 43 46 47", "02", null ] -, [ 573, "3847BF2B-6773-4D29-938F-3806665D4FC1", 573, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-09T00:00:00", "11 33 41 42 46", "21", null ] -, [ 574, "FA9EA266-45A8-42C8-8D47-1D8BEB542211", 574, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-13T00:00:00", "15 26 36 39 40", "45", null ] -, [ 575, "50D7079B-6127-44CC-A4E0-263E7D452B52", 575, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-16T00:00:00", "12 13 30 31 39", "29", null ] -, [ 576, "56852C92-2149-4F4A-A660-59F939102925", 576, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-20T00:00:00", "14 20 23 42 43", "06", null ] -, [ 577, "39B6B3A1-52EE-4AC4-9676-DC4AE52237E8", 577, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-23T00:00:00", "18 21 33 42 56", "11", null ] -, [ 578, "D4194C06-722A-4E27-8F44-3D0C22B6A3DF", 578, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-27T00:00:00", "09 10 26 29 39", "10", null ] -, [ 579, "3932D673-921C-49E3-9291-BE717E702397", 579, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-11-30T00:00:00", "05 06 12 26 51", "07", null ] -, [ 580, "85FB5051-629B-436F-A43D-4C016A1DF93E", 580, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-04T00:00:00", "16 27 30 45 53", "43", null ] -, [ 581, "CF8D92A3-D767-42DA-B2F7-C8E790ECB065", 581, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-07T00:00:00", "12 18 26 28 51", "35", null ] -, [ 582, "8114AD78-1E0C-4F9C-AADB-508EDF06E336", 582, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-11T00:00:00", "06 25 27 30 45", "46", null ] -, [ 583, "43ACA759-99D1-4D7A-9089-6E639ADDFEDE", 583, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-14T00:00:00", "04 07 12 17 30", "44", null ] -, [ 584, "F2CAB9C2-553C-488A-9E30-CFA7DC65F412", 584, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-18T00:00:00", "03 23 46 48 49", "02", null ] -, [ 585, "9B44D4A4-0F8E-4213-A25F-E6BD1069DF0F", 585, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-21T00:00:00", "14 19 20 43 53", "07", null ] -, [ 586, "3E2922D0-284D-4614-8272-F83BBA38DDF5", 586, 1362743863, "706580", 1362743863, "706580", "{\n}", "2007-12-28T00:00:00", "02 19 22 28 54", "25", null ] -, [ 587, "04551495-BED3-4C37-9648-2FFA8347B05B", 587, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-01T00:00:00", "13 16 25 30 54", "11", null ] -, [ 588, "43BA977B-D380-48A8-85D9-EAF2A7A3AFA0", 588, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-04T00:00:00", "24 31 39 40 56", "32", null ] -, [ 589, "BA466130-57DE-4D6D-9FCD-C95831A4200D", 589, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-08T00:00:00", "10 29 45 52 54", "10", null ] -, [ 590, "AFF26B6A-34B8-4F89-8A85-88ED3C831D30", 590, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-11T00:00:00", "22 36 42 45 55", "42", null ] -, [ 591, "5DD841B2-F85D-493D-AFA2-F8164983D88B", 591, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-15T00:00:00", "21 30 42 44 50", "06", null ] -, [ 592, "CE5E4BA5-75FA-45B6-8C3E-F6EE890F8BAD", 592, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-18T00:00:00", "12 22 33 43 44", "15", null ] -, [ 593, "54B02ECF-BAC1-4940-BF9D-6D1DDD8561BB", 593, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-22T00:00:00", "12 15 22 25 33", "02", null ] -, [ 594, "B59B30E0-5386-455D-94D1-2EFBC646D36C", 594, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-25T00:00:00", "05 12 22 38 56", "22", null ] -, [ 595, "F99E577B-F55E-45E1-93D2-5832E92A52B8", 595, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-01-29T00:00:00", "08 23 39 40 42", "24", null ] -, [ 596, "4B67172C-E66E-4497-AE02-779DFC91A478", 596, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-01T00:00:00", "03 14 30 44 56", "05", null ] -, [ 597, "E604D301-A1AB-4D1F-BC23-70A17775C9F7", 597, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-05T00:00:00", "04 05 17 40 51", "38", null ] -, [ 598, "7EE23997-BF93-4901-8DBE-C4E394C1D211", 598, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-08T00:00:00", "21 30 43 46 50", "18", null ] -, [ 599, "D44E343F-CBED-4A68-98BC-92A0B0BF5920", 599, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-12T00:00:00", "14 27 39 47 50", "12", null ] -, [ 600, "52AAF078-59D5-4833-BA90-49B772ECAD50", 600, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-15T00:00:00", "07 11 26 30 53", "14", null ] -, [ 601, "2331FF0B-08D0-44C4-87C2-4841BB08040C", 601, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-19T00:00:00", "01 38 42 55 56", "34", null ] -, [ 602, "8EFEACF5-1F4F-4F67-8299-A13BC7B83C97", 602, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-22T00:00:00", "07 12 13 19 22", "10", null ] -, [ 603, "2D979590-2BF1-4EA5-A0D2-810843EDD84A", 603, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-26T00:00:00", "09 12 30 36 55", "15", null ] -, [ 604, "EF8F8EF7-18A9-4416-9A40-8B537E58D37A", 604, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-02-29T00:00:00", "05 17 22 26 55", "38", null ] -, [ 605, "AFD6E03E-C539-47CB-9BE2-6AA2E7CACBDB", 605, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-04T00:00:00", "07 15 30 33 56", "22", null ] -, [ 606, "54BC1E13-8915-40A8-88DA-15614181D8C4", 606, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-07T00:00:00", "19 32 33 41 48", "12", null ] -, [ 607, "511B590A-2D57-4C79-8F52-35E42CC64ED5", 607, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-11T00:00:00", "04 13 35 41 47", "44", null ] -, [ 608, "D62F24D8-6136-41FB-A019-03C0E9CC9406", 608, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-14T00:00:00", "03 12 18 25 52", "21", null ] -, [ 609, "B9FA4CFD-CD64-44C2-95A9-2BD4D042A75F", 609, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-18T00:00:00", "13 15 20 25 44", "37", null ] -, [ 610, "EA5686F4-4CB3-4DFF-816A-C1D94A1B1F48", 610, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-21T00:00:00", "05 08 17 19 41", "21", null ] -, [ 611, "AC709B10-C196-4023-AB43-7E95A7CC950D", 611, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-25T00:00:00", "38 42 43 48 53", "12", null ] -, [ 612, "6DF05F03-4E2F-49A0-9413-01B84EEAD863", 612, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-03-28T00:00:00", "07 26 27 40 43", "10", null ] -, [ 613, "1A9F5D9F-4E82-4903-B7AF-E391E31213F2", 613, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-01T00:00:00", "04 17 26 46 56", "25", null ] -, [ 614, "CB9B12F8-FBAC-41F2-A914-AF6455F0FF01", 614, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-04T00:00:00", "03 05 40 45 49", "17", null ] -, [ 615, "C20A8974-D7CF-424B-A508-C18AA16EF0BF", 615, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-08T00:00:00", "08 09 31 37 44", "38", null ] -, [ 616, "DD901315-2325-4C18-8319-81B01B0DFE1D", 616, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-11T00:00:00", "14 18 27 31 42", "07", null ] -, [ 617, "7D3AC251-031A-4D46-B6E3-D57950F6CB58", 617, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-15T00:00:00", "12 13 27 48 50", "30", null ] -, [ 618, "72EDF49D-BC25-4A23-956A-57D27374E917", 618, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-18T00:00:00", "24 28 36 50 53", "29", null ] -, [ 619, "BBC81A36-EBE1-4963-99CF-0FF40F70EC1F", 619, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-22T00:00:00", "03 22 31 48 54", "09", null ] -, [ 620, "A7BFDD05-2042-47C7-B393-067E4B9008A5", 620, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-25T00:00:00", "19 32 37 45 52", "41", null ] -, [ 621, "D766A4DB-4E03-4DD3-9141-2DEACE174839", 621, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-04-29T00:00:00", "19 24 35 44 51", "26", null ] -, [ 622, "39338F15-1D3D-4B25-8E41-A47775643753", 622, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-02T00:00:00", "08 28 37 53 55", "26", null ] -, [ 623, "61E2B968-18EA-4661-97D8-1557EA46EF07", 623, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-06T00:00:00", "04 21 46 53 54", "26", null ] -, [ 624, "858831D9-54C7-4330-BDB5-5B034C4BE4E4", 624, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-09T00:00:00", "16 31 43 46 56", "22", null ] -, [ 625, "D0CEF627-5AF9-42F9-AA58-4686413929C9", 625, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-13T00:00:00", "20 24 27 31 47", "15", null ] -, [ 626, "9009BD57-C8CE-4668-9CE0-F5D59CA5F172", 626, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-16T00:00:00", "06 11 39 46 47", "26", null ] -, [ 627, "A991C2F5-559D-44FE-8C0D-9BCAA3E344A5", 627, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-20T00:00:00", "02 14 26 32 41", "32", null ] -, [ 628, "91E9434A-7FBF-444A-B4B1-613B961F2A48", 628, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-23T00:00:00", "04 08 11 22 30", "04", null ] -, [ 629, "DC5EED77-8143-4F86-97DE-13972F2B2AFC", 629, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-27T00:00:00", "14 24 32 45 49", "17", null ] -, [ 630, "97097C20-BC7D-43E1-AAC5-F48B2F638E45", 630, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-05-30T00:00:00", "39 40 47 53 55", "32", null ] -, [ 631, "1BF2908A-5A66-4E7D-9F48-A22B94C280F0", 631, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-03T00:00:00", "04 19 24 32 54", "05", null ] -, [ 632, "79E09164-E650-489E-9641-DC52D4203F50", 632, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-06T00:00:00", "08 09 43 44 54", "27", null ] -, [ 633, "F2AF63EE-E3A5-4D2C-90C7-0D4B0003792D", 633, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-10T00:00:00", "03 05 15 43 51", "11", null ] -, [ 634, "7A95EAC2-EB23-4F35-BB91-7B291DC85943", 634, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-13T00:00:00", "08 09 14 38 44", "36", null ] -, [ 635, "BA5F710C-0B05-4FEB-9DB9-DE4E80C23089", 635, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-17T00:00:00", "05 14 25 47 49", "36", null ] -, [ 636, "07ABF657-5309-4D77-9BE4-716F3E48BE4E", 636, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-20T00:00:00", "11 17 25 36 42", "13", null ] -, [ 637, "441E43A9-2BFE-4EDD-86A5-7D0237E40AD9", 637, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-24T00:00:00", "10 22 36 50 53", "39", null ] -, [ 638, "B7473E75-6067-4E58-B934-81512155CC22", 638, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-06-27T00:00:00", "08 14 22 39 50", "44", null ] -, [ 639, "E498C1F6-8191-4DCF-97D5-B4838C72B27E", 639, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-01T00:00:00", "01 22 33 43 52", "36", null ] -, [ 640, "E6F1EB36-9C3D-432B-955A-5A87B91CF56A", 640, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-04T00:00:00", "01 03 12 19 20", "28", null ] -, [ 641, "7B9F9687-FA7C-4C35-9CD0-C75C24F6B843", 641, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-08T00:00:00", "01 20 22 29 41", "35", null ] -, [ 642, "DF85FE52-BB4B-42DC-B762-FFE86C7287FF", 642, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-11T00:00:00", "05 14 16 39 51", "34", null ] -, [ 643, "C2952461-9560-42BF-89D7-A128C11664A2", 643, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-15T00:00:00", "19 24 34 45 51", "40", null ] -, [ 644, "61469DD6-B4E4-4BCC-90AB-A71BAC7567CE", 644, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-18T00:00:00", "17 29 36 53 55", "26", null ] -, [ 645, "536EA679-7D1A-4740-8B02-EE9C33B203E7", 645, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-22T00:00:00", "02 16 23 29 32", "46", null ] -, [ 646, "95937200-82F3-402E-8248-B8951D1C1873", 646, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-25T00:00:00", "02 16 19 35 52", "17", null ] -, [ 647, "05997811-B217-45CA-9EAB-3126E3C649CD", 647, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-07-29T00:00:00", "11 13 20 30 42", "03", null ] -, [ 648, "FAF32B79-7770-4454-B053-47F6965910B8", 648, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-01T00:00:00", "09 13 17 18 56", "02", null ] -, [ 649, "BB9F5AC4-4B54-4EFC-B40E-28A4ABD26D63", 649, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-05T00:00:00", "09 21 36 38 55", "13", null ] -, [ 650, "809C3172-9F6E-4E8A-9EB5-CC9D1EBD7FDB", 650, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-08T00:00:00", "11 17 28 32 50", "33", null ] -, [ 651, "04182DD5-998D-44E2-B594-64556A39C8CD", 651, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-12T00:00:00", "02 07 23 38 40", "40", null ] -, [ 652, "8381CACD-0581-40DE-9D78-1402384FAE15", 652, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-15T00:00:00", "08 23 29 30 53", "07", null ] -, [ 653, "1B4D963D-ADAB-4871-B192-4B985AC36F31", 653, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-19T00:00:00", "09 18 19 26 40", "38", null ] -, [ 654, "C4183FB9-A12F-4E51-8630-6D4C4FF6236E", 654, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-22T00:00:00", "12 13 15 41 42", "37", null ] -, [ 655, "B5863FA9-E005-4C28-BB32-9132851D9C19", 655, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-26T00:00:00", "06 16 24 34 36", "30", null ] -, [ 656, "3BF0DDAC-D674-4055-9A4B-DA9AC99E0D82", 656, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-08-29T00:00:00", "21 25 26 50 51", "22", null ] -, [ 657, "19B8A21B-A93F-42E5-B8A2-B65B17C03CBC", 657, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-02T00:00:00", "14 23 43 44 54", "39", null ] -, [ 658, "0B7BF62B-A20B-4B31-AD56-A24C98307C57", 658, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-05T00:00:00", "01 06 15 27 46", "39", null ] -, [ 659, "6292265B-0462-4FAE-A4BE-CF94C20DB96F", 659, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-09T00:00:00", "22 23 28 49 52", "02", null ] -, [ 660, "948DD599-9C55-40F8-89FD-8D67E835938C", 660, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-12T00:00:00", "01 12 14 25 35", "38", null ] -, [ 661, "EBAB9596-15F7-4E80-9AE5-B2614299CD35", 661, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-16T00:00:00", "13 24 39 51 52", "44", null ] -, [ 662, "32E7961A-6226-4037-9A77-D7B26D188DC2", 662, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-19T00:00:00", "02 09 41 48 51", "37", null ] -, [ 663, "EE6BA26A-7962-4738-AD11-1ABDF472E47D", 663, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-23T00:00:00", "09 32 34 43 52", "04", null ] -, [ 664, "67930A86-D27C-4F43-81D8-1B04573D642F", 664, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-26T00:00:00", "06 13 14 31 36", "36", null ] -, [ 665, "90B63F14-6644-42AF-9827-4DAE75D83F76", 665, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-09-30T00:00:00", "09 30 35 39 49", "36", null ] -, [ 666, "E4AB005C-DE82-4FF3-B929-59933A564E52", 666, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-03T00:00:00", "13 28 32 41 52", "16", null ] -, [ 667, "8306F542-EDF9-4ABE-ABEA-BE7FF13F5F45", 667, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-07T00:00:00", "02 25 35 38 42", "34", null ] -, [ 668, "E60DF50F-8CE6-4B60-AA78-F7BD1CB2E8E6", 668, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-10T00:00:00", "14 15 43 46 48", "21", null ] -, [ 669, "217D2DF3-97B0-48EF-9F35-01FCFB97B83F", 669, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-14T00:00:00", "14 35 41 42 51", "23", null ] -, [ 670, "DD45E22D-72A2-4052-838A-7E236925AFAB", 670, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-17T00:00:00", "07 15 27 28 31", "35", null ] -, [ 671, "FC5BB8FE-AFD6-4784-A950-25D21B85493F", 671, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-21T00:00:00", "16 19 39 42 44", "38", null ] -, [ 672, "0CD5FC5D-4989-496C-B575-11EAAAD6115C", 672, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-24T00:00:00", "05 33 34 47 52", "18", null ] -, [ 673, "3F9A2F2B-919D-4F31-B636-52862546E3BB", 673, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-28T00:00:00", "06 39 45 46 48", "36", null ] -, [ 674, "E02FF34D-3A58-42C9-8722-0347598852F7", 674, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-10-31T00:00:00", "02 07 17 29 47", "40", null ] -, [ 675, "6DF2E2C0-A871-4AFE-9E12-738CBE7AF05D", 675, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-04T00:00:00", "10 21 23 41 55", "09", null ] -, [ 676, "7B508DB8-75A8-4C05-BB9A-63697C7A0A4D", 676, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-07T00:00:00", "14 24 32 43 44", "21", null ] -, [ 677, "808AB5CA-F5CA-47B7-8F73-1517D8892037", 677, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-11T00:00:00", "05 27 38 42 55", "41", null ] -, [ 678, "B0536821-95CC-4733-84C7-F4F052327A8E", 678, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-14T00:00:00", "03 18 19 30 34", "03", null ] -, [ 679, "74023E2B-EEB5-44BF-9694-3E044C8C83F5", 679, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-18T00:00:00", "10 15 22 52 53", "12", null ] -, [ 680, "4C086620-5B40-41D6-B9B4-F79479D5F2ED", 680, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-21T00:00:00", "01 22 52 53 56", "45", null ] -, [ 681, "57EEB3E2-33B7-4FF1-BB90-8A6005FA79DE", 681, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-25T00:00:00", "02 11 22 51 52", "46", null ] -, [ 682, "CBBEE8D1-B7C9-40B4-A622-D061805B9B7D", 682, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-11-28T00:00:00", "10 30 44 46 48", "44", null ] -, [ 683, "F5376D25-5DF8-42C3-B344-AA5CE2F413D7", 683, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-02T00:00:00", "02 17 22 32 51", "35", null ] -, [ 684, "52198556-DA62-4169-AA41-D92046DD93FD", 684, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-05T00:00:00", "21 27 46 52 55", "14", null ] -, [ 685, "6DDE7205-0EB7-46EB-8F9B-B2FF0B217AC8", 685, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-09T00:00:00", "11 12 26 31 33", "27", null ] -, [ 686, "2BE6965D-BF8A-4145-8C6B-094C377A8BEA", 686, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-12T00:00:00", "10 16 19 27 48", "25", null ] -, [ 687, "8483A370-5A9E-4C91-BC8B-AD11582907D3", 687, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-16T00:00:00", "10 14 16 29 40", "06", null ] -, [ 688, "EDBFF068-2C35-433F-882A-D56A37C36747", 688, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-19T00:00:00", "03 13 16 39 54", "32", null ] -, [ 689, "85088580-AC76-4A88-9A43-CA57062D3991", 689, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-23T00:00:00", "01 08 13 27 41", "45", null ] -, [ 690, "41BB763A-B7EE-4B77-B46C-35B2D4D11397", 690, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-26T00:00:00", "06 19 29 33 37", "31", null ] -, [ 691, "F45C1691-4DCA-4754-ACDC-370D4D1BD7C0", 691, 1362743863, "706580", 1362743863, "706580", "{\n}", "2008-12-30T00:00:00", "01 22 29 44 52", "39", null ] -, [ 692, "DA9A9104-C0DB-4306-BCE5-B825281DFA12", 692, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-02T00:00:00", "02 11 19 21 34", "38", null ] -, [ 693, "457BD885-F877-4984-B9EC-CB13469E7BF7", 693, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-06T00:00:00", "03 11 12 19 33", "30", null ] -, [ 694, "006D900C-426D-43BB-B1D7-2C7B407BC426", 694, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-09T00:00:00", "23 25 30 45 50", "08", null ] -, [ 695, "A4775431-5ADA-4A87-AE5F-C6E639F9E631", 695, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-13T00:00:00", "22 25 33 36 48", "40", null ] -, [ 696, "67534450-D8C3-40A5-8913-84D193109350", 696, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-16T00:00:00", "02 04 21 39 51", "29", null ] -, [ 697, "C93BDF71-0B5F-4EEE-BFF0-06559684E40B", 697, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-20T00:00:00", "01 09 10 35 46", "09", null ] -, [ 698, "87AE85FC-0B31-4036-8BB1-3EB6BFB12353", 698, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-23T00:00:00", "02 17 20 27 28", "07", null ] -, [ 699, "0C8FCC5D-F1AA-4F04-AE12-EBDCDD302550", 699, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-27T00:00:00", "03 11 12 14 21", "25", null ] -, [ 700, "4598C166-E066-430F-A34B-191133D82DC0", 700, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-01-30T00:00:00", "13 16 19 53 55", "02", null ] -, [ 701, "84952D50-FB23-41B8-B8B9-7C563FB0DEF3", 701, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-03T00:00:00", "04 15 29 43 56", "29", null ] -, [ 702, "4FBD061D-4178-478A-A9DA-0591952AF4A1", 702, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-06T00:00:00", "02 12 18 28 31", "03", null ] -, [ 703, "61079EAE-409B-4FA4-AF31-BD6290B4DECD", 703, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-10T00:00:00", "18 29 38 43 47", "07", null ] -, [ 704, "BC0C8E66-8F2B-4627-A61F-16476BE4D0D1", 704, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-13T00:00:00", "25 36 37 40 51", "20", null ] -, [ 705, "02D3567D-CDCA-4E4B-8558-805A7F344CA8", 705, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-17T00:00:00", "01 09 23 27 33", "24", null ] -, [ 706, "D5889D79-7B25-4EB4-B609-E985347A3E6D", 706, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-20T00:00:00", "21 28 41 45 55", "24", null ] -, [ 707, "DBD4B0BD-CCDC-4E1D-AEAC-7B1CFD1863CC", 707, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-24T00:00:00", "01 27 28 35 40", "06", null ] -, [ 708, "A4B1FE35-873D-46EA-890E-CA09F4A445A7", 708, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-02-27T00:00:00", "24 37 44 50 56", "35", null ] -, [ 709, "813AE8F3-A520-4B94-9830-51FC6CFAEE27", 709, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-03T00:00:00", "26 32 35 43 52", "10", null ] -, [ 710, "FC0C4C98-0E7B-42C7-9D18-9707EBD8BC8E", 710, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-06T00:00:00", "11 18 37 46 55", "45", null ] -, [ 711, "9A17DCEE-779A-4020-9CEC-8064B73B0EAC", 711, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-10T00:00:00", "02 27 31 39 40", "23", null ] -, [ 712, "C2055A92-0EA6-46BF-A085-D1B2F2FD9F87", 712, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-13T00:00:00", "10 12 26 46 50", "23", null ] -, [ 713, "471EB7B1-EC76-428C-B4C1-D4746EE3B5BD", 713, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-17T00:00:00", "09 15 24 28 31", "17", null ] -, [ 714, "AEC2FFB5-3CF4-4541-AF59-429BA4EA88ED", 714, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-20T00:00:00", "15 16 20 39 40", "26", null ] -, [ 715, "5D59F47E-FDB3-4D75-8726-A89B26E960EB", 715, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-24T00:00:00", "04 25 34 43 44", "45", null ] -, [ 716, "E3C8C9EC-2595-43D8-9220-801A471A0785", 716, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-27T00:00:00", "10 15 24 38 50", "19", null ] -, [ 717, "75F8683A-8CB5-4A64-B394-F3856113C734", 717, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-03-31T00:00:00", "14 39 47 48 53", "29", null ] -, [ 718, "1DFBD7FB-D346-47E3-8055-650E565084DB", 718, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-03T00:00:00", "16 22 38 39 48", "42", null ] -, [ 719, "F2228ABC-483D-4402-885C-07F9CA41D3FF", 719, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-07T00:00:00", "02 04 13 17 36", "15", null ] -, [ 720, "23C5D3A0-28C4-414A-AA41-56BB9FF9E4D6", 720, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-10T00:00:00", "18 25 36 42 51", "22", null ] -, [ 721, "7214BB77-B931-442E-8656-AF6388E58DA0", 721, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-14T00:00:00", "04 11 22 48 50", "42", null ] -, [ 722, "103C24D8-2F24-4B67-B25B-BE1E6CE96A85", 722, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-17T00:00:00", "05 13 26 35 45", "32", null ] -, [ 723, "74CD43FF-6C29-42F2-8492-1D9FD9BE1B96", 723, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-21T00:00:00", "05 24 37 47 52", "06", null ] -, [ 724, "0B0DCFE8-1FEF-437F-BD58-33EAEA95BBDE", 724, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-24T00:00:00", "09 20 21 48 49", "07", null ] -, [ 725, "21DCD08A-3F15-4065-A97B-85B46045F5D3", 725, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-04-28T00:00:00", "15 20 24 36 44", "06", null ] -, [ 726, "351EBC69-A427-4C20-B798-68E178E5088B", 726, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-01T00:00:00", "09 16 24 40 43", "35", null ] -, [ 727, "168B47E6-6EB9-4387-B9AB-FBEE6E70187B", 727, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-05T00:00:00", "05 23 38 39 54", "03", null ] -, [ 728, "D87CA568-F428-44DC-8E0D-938DAE764D2D", 728, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-08T00:00:00", "12 27 29 32 34", "34", null ] -, [ 729, "BE8F8E4C-87AC-419E-8B35-25B645F733A0", 729, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-12T00:00:00", "04 08 10 14 51", "31", null ] -, [ 730, "81151545-D0DE-4732-A845-747FD7B426A0", 730, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-15T00:00:00", "07 12 24 36 48", "27", null ] -, [ 731, "AFAB890B-9AE6-4DC4-9E2F-FBBDD5CAA71F", 731, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-19T00:00:00", "02 04 09 15 42", "13", null ] -, [ 732, "3FB0BBB5-9305-4AD1-A8EF-677EB14D739A", 732, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-22T00:00:00", "03 29 34 42 49", "29", null ] -, [ 733, "11EA5295-1010-4F48-9FA7-166D5CE49043", 733, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-26T00:00:00", "09 18 21 37 55", "33", null ] -, [ 734, "81049EB0-34A3-404C-805D-EC79155BD474", 734, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-05-29T00:00:00", "23 30 36 39 48", "34", null ] -, [ 735, "F22FA563-2C4C-49CD-A213-F3B0258DD2F7", 735, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-02T00:00:00", "09 13 26 30 35", "33", null ] -, [ 736, "339FAF34-DD23-4C2C-8FF1-11BC297110D5", 736, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-05T00:00:00", "05 20 38 41 52", "20", null ] -, [ 737, "572A228E-A2B7-4853-AC56-B51FA3E4E977", 737, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-09T00:00:00", "05 17 31 36 56", "46", null ] -, [ 738, "B1912705-910F-40B0-B26C-C080AE03A64E", 738, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-12T00:00:00", "06 11 20 32 44", "38", null ] -, [ 739, "18C01ED7-F086-462D-952C-3690822D9EB3", 739, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-16T00:00:00", "09 15 21 26 45", "25", null ] -, [ 740, "778E58D2-A4BF-4397-ACB4-CD45F4594E02", 740, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-19T00:00:00", "04 09 12 16 46", "44", null ] -, [ 741, "EBD03D4A-8D22-4069-BB9C-85B2905C1908", 741, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-23T00:00:00", "12 14 16 31 50", "09", null ] -, [ 742, "946BC592-27E8-4679-8A4F-D1ADE23BCAB2", 742, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-26T00:00:00", "11 15 17 29 46", "16", null ] -, [ 743, "37C1E7E8-D038-4632-8095-CF7C367AF16C", 743, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-06-30T00:00:00", "07 34 49 54 55", "34", null ] -, [ 744, "0CEAED99-4AF4-4C56-BDBE-2CD11790E752", 744, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-03T00:00:00", "05 06 07 11 25", "31", null ] -, [ 745, "56165FDF-EACB-4D44-8FD0-19188EBF9FDB", 745, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-07T00:00:00", "25 27 35 38 39", "28", null ] -, [ 746, "F75DCF35-BB8A-4E25-A08A-C70AED507E1B", 746, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-10T00:00:00", "05 10 26 27 28", "04", null ] -, [ 747, "A5AED3DC-82D1-47B2-AD84-3E4CFF492863", 747, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-14T00:00:00", "20 29 35 45 53", "41", null ] -, [ 748, "CBC7B3F7-A0FB-4B17-8FC9-B584A48ACE1A", 748, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-17T00:00:00", "08 17 40 47 50", "13", null ] -, [ 749, "3972E622-3A12-4459-A2F3-853C6E3DF528", 749, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-21T00:00:00", "03 08 21 50 52", "02", null ] -, [ 750, "36750E7C-756E-46DE-9C57-1CDB57C686AF", 750, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-24T00:00:00", "03 06 43 51 52", "36", null ] -, [ 751, "0ED2B295-A760-4BFF-A56B-A303E61A48C2", 751, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-28T00:00:00", "04 17 24 25 48", "34", null ] -, [ 752, "FC76F901-1F35-4951-9FB1-E2FF0688D0C5", 752, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-07-31T00:00:00", "17 35 44 52 56", "22", null ] -, [ 753, "7F2411E9-C4EE-4D90-94DF-387E3D33E14C", 753, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-04T00:00:00", "01 28 34 42 50", "27", null ] -, [ 754, "B19ED6DC-2FE3-4379-B92F-F4E04BD8B602", 754, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-07T00:00:00", "07 18 35 45 56", "03", null ] -, [ 755, "CAF2B068-BCB0-4E9E-B094-3C092814F3D6", 755, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-11T00:00:00", "06 12 15 32 42", "40", null ] -, [ 756, "BE14FCFA-6D56-4B87-9428-F036AF6A153A", 756, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-14T00:00:00", "08 22 25 33 35", "46", null ] -, [ 757, "9D7178FE-3F92-4B7C-A73B-30933BA111C6", 757, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-18T00:00:00", "04 05 26 37 56", "25", null ] -, [ 758, "DAD3C7AA-522B-4F6F-A217-6B18954EF1D4", 758, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-21T00:00:00", "09 38 44 48 49", "13", null ] -, [ 759, "AA1A3D6E-3344-435B-B813-971C58193477", 759, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-25T00:00:00", "03 12 19 22 40", "02", null ] -, [ 760, "F24708B7-2F8E-4551-908C-C221C7A9C5D3", 760, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-08-28T00:00:00", "01 17 31 37 54", "31", null ] -, [ 761, "7D46008B-19E9-4BA4-8E63-846F0F8F7C11", 761, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-01T00:00:00", "02 09 28 51 53", "19", null ] -, [ 762, "146376B5-76BF-492D-828D-3CA640DFDBDA", 762, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-04T00:00:00", "02 04 06 21 44", "37", null ] -, [ 763, "74CBE867-A0EA-4BDD-903C-CBCF649F0852", 763, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-08T00:00:00", "04 10 18 28 50", "35", null ] -, [ 764, "C5083416-19DA-4EB2-BB73-F106C6714BCD", 764, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-11T00:00:00", "16 27 48 49 54", "02", null ] -, [ 765, "54B77269-DF10-43D2-85AC-87310F635F40", 765, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-15T00:00:00", "29 30 32 35 41", "39", null ] -, [ 766, "9F3A9E56-B7C2-49BA-AC52-1A9845358AD1", 766, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-18T00:00:00", "18 27 31 36 52", "33", null ] -, [ 767, "83DD43D5-A17C-4BC0-A94B-CE5C98800671", 767, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-22T00:00:00", "26 29 33 39 46", "24", null ] -, [ 768, "E2289CDE-FE3A-4572-BDDF-7B796DDE0F48", 768, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-25T00:00:00", "07 27 42 49 52", "19", null ] -, [ 769, "6C158BB8-3C8D-4821-A36A-12D493870B1D", 769, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-09-29T00:00:00", "02 21 25 45 50", "21", null ] -, [ 770, "14EF87A6-B943-4168-A85C-92986474FE73", 770, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-02T00:00:00", "15 24 51 53 55", "11", null ] -, [ 771, "2940046E-0856-4C27-BDEC-0081153FE6D9", 771, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-06T00:00:00", "09 33 51 53 56", "39", null ] -, [ 772, "4B1ECB95-422B-4E5C-AE4A-A36CC7289AE2", 772, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-09T00:00:00", "03 14 21 24 51", "14", null ] -, [ 773, "917603BF-CE49-4D4C-B344-4F7BFB4A3000", 773, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-13T00:00:00", "17 31 34 45 51", "24", null ] -, [ 774, "C4B244A5-71AE-4737-8696-FAD69FCC4306", 774, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-16T00:00:00", "10 13 18 33 51", "43", null ] -, [ 775, "B09A6263-AE32-48A1-B27F-5261FF85BB0A", 775, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-20T00:00:00", "13 17 25 45 55", "08", null ] -, [ 776, "49AC2B38-0F01-4ECF-97F9-DFEE683496FB", 776, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-23T00:00:00", "27 45 48 54 56", "02", null ] -, [ 777, "8F5C36CD-13DA-482D-8D06-C70FAD47E5DD", 777, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-27T00:00:00", "07 13 37 46 51", "02", null ] -, [ 778, "EC9A3519-606B-4389-9A2E-39C962F5E2B4", 778, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-10-30T00:00:00", "04 15 17 29 38", "20", null ] -, [ 779, "167BFB3F-0E07-4C16-978E-FBE7FFD5B68B", 779, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-03T00:00:00", "05 18 23 31 38", "20", null ] -, [ 780, "E701E122-932C-47DB-91E4-8EDEC824EF6D", 780, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-06T00:00:00", "07 11 27 40 46", "08", null ] -, [ 781, "7DDD4033-B3ED-48A6-806C-8886C6A2BE5B", 781, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-10T00:00:00", "08 21 29 34 37", "15", null ] -, [ 782, "65739373-4856-4DEB-B8EB-D2A5867F6AF7", 782, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-13T00:00:00", "27 43 45 49 54", "44", null ] -, [ 783, "BD325C4F-DC06-4DE8-8AB0-B0CA898310D2", 783, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-17T00:00:00", "08 22 27 49 50", "28", null ] -, [ 784, "BA3F8A87-E1F8-4518-AFA7-6E6CB0094ADE", 784, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-20T00:00:00", "03 04 07 16 56", "39", null ] -, [ 785, "10601DE2-F74F-4A16-A5AE-D9B528F37947", 785, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-24T00:00:00", "10 11 35 37 50", "12", null ] -, [ 786, "028E0467-039A-4646-B805-419A7EA4215F", 786, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-11-27T00:00:00", "12 25 37 39 45", "11", null ] -, [ 787, "CCA3BDA4-4EA3-4847-B489-DA31CE612F46", 787, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-01T00:00:00", "17 30 39 52 53", "21", null ] -, [ 788, "5A4D2F95-05B7-45B0-AFC6-0C8671090078", 788, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-04T00:00:00", "04 33 41 51 56", "38", null ] -, [ 789, "1AFDE069-1C2C-4B11-ABF2-5D34C99F8009", 789, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-08T00:00:00", "20 23 28 30 46", "29", null ] -, [ 790, "C8688557-3C55-40B1-8547-F8F63EA978E2", 790, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-11T00:00:00", "02 21 27 34 44", "45", null ] -, [ 791, "170F03BB-4FA6-4012-9DEA-3F355327CB2D", 791, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-15T00:00:00", "27 31 32 36 47", "35", null ] -, [ 792, "A1C9B69C-F6E9-4F03-BD08-3612C8130DB2", 792, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-18T00:00:00", "10 20 30 44 49", "24", null ] -, [ 793, "2DF0DE5D-822C-4B1F-8189-150829710D6D", 793, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-22T00:00:00", "03 33 35 39 45", "13", null ] -, [ 794, "2BFF67A2-5627-45EB-9332-DFA144B11A4E", 794, 1362743863, "706580", 1362743863, "706580", "{\n}", "2009-12-29T00:00:00", "02 05 29 35 51", "03", null ] -, [ 795, "2A5CE53D-DC71-4E03-9BE0-75214C869310", 795, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-01T00:00:00", "06 08 27 40 41", "21", null ] -, [ 796, "E0C0761D-CDE8-4951-8FAD-1649611251D5", 796, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-05T00:00:00", "13 28 39 50 55", "10", null ] -, [ 797, "FC60EB92-6CC8-4E00-92ED-329B206F34BF", 797, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-08T00:00:00", "18 20 31 36 43", "33", null ] -, [ 798, "1395E5F5-EAD5-4A9E-8E30-3D4ED3180582", 798, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-12T00:00:00", "05 09 31 37 56", "16", null ] -, [ 799, "61176EE6-194E-4B7A-8289-641D6D73E30F", 799, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-15T00:00:00", "04 07 19 21 38", "29", null ] -, [ 800, "053F0AAB-3C80-4608-A15B-11EF823A97A0", 800, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-19T00:00:00", "04 05 34 38 41", "18", null ] -, [ 801, "11D64BB4-E070-4C24-8369-142791A0DB96", 801, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-22T00:00:00", "08 13 27 28 52", "09", null ] -, [ 802, "D8151C78-F265-4CBB-99A2-42E38293079D", 802, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-26T00:00:00", "07 08 38 39 48", "22", null ] -, [ 803, "0CCA6D18-2074-488C-A3D0-DA64DFFD8AA4", 803, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-01-29T00:00:00", "01 10 22 23 38", "19", null ] -, [ 804, "F5782C73-F67B-4BC7-88C1-D27461D9D2D3", 804, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-02T00:00:00", "06 07 26 27 49", "09", null ] -, [ 805, "31DB7363-8E05-4A5F-B44A-2084214F4376", 805, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-05T00:00:00", "10 20 45 51 53", "41", null ] -, [ 806, "F1F49235-006D-4983-8E66-C28093B9935C", 806, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-09T00:00:00", "02 17 20 26 48", "12", null ] -, [ 807, "1AF21D48-A038-4F94-AB71-EB64D7ADD2AC", 807, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-12T00:00:00", "14 16 17 33 47", "23", null ] -, [ 808, "3B55D6A9-90F8-4A0E-9231-AB28F15F994E", 808, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-16T00:00:00", "11 12 21 29 45", "05", null ] -, [ 809, "A119EC98-37A8-48EC-BE53-DEFE528ED3DB", 809, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-19T00:00:00", "01 22 39 42 46", "36", null ] -, [ 810, "2FE766E0-110C-4FCE-80B2-179AF7347FAE", 810, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-23T00:00:00", "04 16 36 40 53", "18", null ] -, [ 811, "DB5883CA-B9DD-471A-99AC-07BFDB428539", 811, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-02-26T00:00:00", "04 14 29 54 56", "40", null ] -, [ 812, "15CB5697-EB46-4932-8B7F-19A32ACF2340", 812, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-02T00:00:00", "09 12 47 48 56", "25", null ] -, [ 813, "CF4EB296-ABBE-4034-A548-A8CC9917EC24", 813, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-05T00:00:00", "11 31 34 44 52", "32", null ] -, [ 814, "A1EDA1B5-B783-4732-89DC-A359CB1FD0C7", 814, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-09T00:00:00", "14 16 18 19 29", "16", null ] -, [ 815, "1D791D17-41CD-4053-804F-3A7058B0EC24", 815, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-12T00:00:00", "02 15 25 48 53", "41", null ] -, [ 816, "D4C9077C-B7DD-4890-A6C1-DF0228AA3B1C", 816, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-16T00:00:00", "03 22 48 52 56", "13", null ] -, [ 817, "32DD92A6-6176-421B-AD93-6467660CF6D2", 817, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-19T00:00:00", "10 31 45 50 54", "25", null ] -, [ 818, "E773448F-7D8E-41B3-A08F-118B31FEB680", 818, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-23T00:00:00", "03 25 28 29 40", "13", null ] -, [ 819, "24388C14-9B3E-43A6-A07A-C80597855505", 819, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-26T00:00:00", "23 41 46 47 52", "22", null ] -, [ 820, "FC270668-BDB7-47E6-BA4D-7639B11FF369", 820, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-03-30T00:00:00", "01 11 24 38 44", "41", null ] -, [ 821, "FDF67DCE-BF83-4409-AFC6-A2FC0E1C35C9", 821, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-02T00:00:00", "02 17 22 30 31", "19", null ] -, [ 822, "F8EE5F90-48B8-4E4D-BE7B-F9A3780C04B0", 822, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-06T00:00:00", "16 43 44 52 56", "26", null ] -, [ 823, "2D4979F0-21FA-4EB4-A12F-A82ECAD11C85", 823, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-09T00:00:00", "15 18 39 48 53", "03", null ] -, [ 824, "3AD05007-2EBF-4675-BCAC-8D7610966D5C", 824, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-13T00:00:00", "03 12 27 39 47", "32", null ] -, [ 825, "671D846F-3632-44D6-98E4-E267DA8D19AB", 825, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-16T00:00:00", "10 16 31 48 50", "44", null ] -, [ 826, "9217DF4A-F053-4D12-AC26-DE254B56E4B0", 826, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-20T00:00:00", "05 08 10 34 42", "25", null ] -, [ 827, "AE0105AC-6C6E-4F11-9879-42A06D3090A3", 827, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-23T00:00:00", "19 26 28 37 52", "18", null ] -, [ 828, "65A9C9F5-5792-4D64-B225-3CF46C8D0026", 828, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-27T00:00:00", "23 37 41 50 55", "06", null ] -, [ 829, "5423D260-E2FC-4F86-8618-AAFAC601760B", 829, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-04-30T00:00:00", "14 20 41 47 53", "40", null ] -, [ 830, "45A9F9A3-30E6-41F0-A703-56B4F9E07294", 830, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-04T00:00:00", "09 21 31 36 43", "08", null ] -, [ 831, "1C82A9F5-D878-492C-A2CE-B37E205DB898", 831, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-07T00:00:00", "02 07 20 34 50", "40", null ] -, [ 832, "9615C4EB-1283-420B-94A2-48DBDD59A26A", 832, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-11T00:00:00", "26 33 43 46 54", "09", null ] -, [ 833, "1A730B61-1C5D-4EBB-8BD2-763F8EA4E8A5", 833, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-14T00:00:00", "20 21 40 47 56", "12", null ] -, [ 834, "1CAB05D1-6329-48C2-B5B4-253E53B89D46", 834, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-18T00:00:00", "11 13 19 37 40", "26", null ] -, [ 835, "EE46E0D7-377B-4075-9E44-618AC3F3F437", 835, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-21T00:00:00", "15 20 23 26 30", "17", null ] -, [ 836, "80585183-B52E-4348-9B2A-FF02017789B8", 836, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-25T00:00:00", "05 14 17 19 24", "25", null ] -, [ 837, "749A0427-5968-45CE-BD6C-C864F6F26A71", 837, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-05-28T00:00:00", "03 11 20 29 39", "26", null ] -, [ 838, "D72ACE65-0BFD-4826-8747-3CBB207764FA", 838, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-01T00:00:00", "12 27 44 45 51", "30", null ] -, [ 839, "78CFF352-C91F-4F79-9985-988B16077D13", 839, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-04T00:00:00", "12 13 15 17 50", "23", null ] -, [ 840, "3357706B-14F6-4A84-82EA-0BA1AD4705CE", 840, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-08T00:00:00", "12 18 28 48 54", "06", null ] -, [ 841, "F5926E9D-91D0-4FA0-9657-255273DA02BB", 841, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-11T00:00:00", "06 13 33 34 42", "25", null ] -, [ 842, "EE8D88B6-371B-48D8-B55F-0226F5058211", 842, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-15T00:00:00", "04 12 13 21 27", "46", null ] -, [ 843, "B584633B-6A66-4F79-8F2F-1609E41A44A5", 843, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-18T00:00:00", "11 36 37 41 55", "07", null ] -, [ 844, "47480512-F3C4-4411-BCED-EADC1B42F0D5", 844, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-22T00:00:00", "12 17 21 23 30", "24", null ] -, [ 845, "508956C9-C492-4141-9CE6-0DCBCE172E9D", 845, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-25T00:00:00", "01 02 13 19 27", "21", null ] -, [ 846, "9510B976-63F8-4F92-830F-BB53C4B7D35C", 846, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-06-29T00:00:00", "03 04 15 27 37", "35", null ] -, [ 847, "914A95CB-37B6-496A-8A7D-5A27B9F3E497", 847, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-02T00:00:00", "01 10 12 32 36", "25", null ] -, [ 848, "AB8D3AC8-D4F4-45A4-A8B9-4A398D6161FF", 848, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-06T00:00:00", "08 18 45 47 50", "36", null ] -, [ 849, "3CAF750C-2F9E-4805-AF9D-2F7A17D7390C", 849, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-09T00:00:00", "01 31 33 34 50", "41", null ] -, [ 850, "42BB83DD-69F5-4DD0-B7F6-B09CB72F84BB", 850, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-13T00:00:00", "07 11 14 15 34", "14", null ] -, [ 851, "A54BB62A-B5C4-4D33-8BF6-A47AD370146C", 851, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-16T00:00:00", "02 15 18 20 39", "34", null ] -, [ 852, "35689336-FA69-430B-BB7B-9D8757F5C563", 852, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-20T00:00:00", "12 18 28 36 43", "19", null ] -, [ 853, "79CF2CDF-F4FE-41AF-948C-679C89573D5A", 853, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-23T00:00:00", "16 19 39 44 49", "26", null ] -, [ 854, "8F6A8839-96B9-4695-B375-9D6ADC32915A", 854, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-27T00:00:00", "02 07 10 16 29", "08", null ] -, [ 855, "07371AEF-A119-4A98-BDC6-1E08263E3F78", 855, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-07-30T00:00:00", "11 30 40 48 52", "42", null ] -, [ 856, "A66E6504-5920-439B-88CA-8F0736C2CA2C", 856, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-03T00:00:00", "04 13 20 22 56", "32", null ] -, [ 857, "E3EC6624-7BB5-470B-AC8A-5CFB8289E377", 857, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-06T00:00:00", "07 13 30 33 54", "30", null ] -, [ 858, "A141A3CC-BD51-4E30-84C0-2A7D994FC250", 858, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-10T00:00:00", "02 14 26 50 56", "12", null ] -, [ 859, "A0E7F6EB-D326-4A9F-A31D-094EAD6A518E", 859, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-13T00:00:00", "06 17 24 43 55", "36", null ] -, [ 860, "D5438DC0-4EC6-48D9-B519-AD24C0B3FB25", 860, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-17T00:00:00", "11 19 40 43 44", "33", null ] -, [ 861, "5219DDB6-E022-4D60-9BFE-34FD4ECB709E", 861, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-20T00:00:00", "04 13 20 29 48", "36", null ] -, [ 862, "E662E6C4-0BE4-421F-893D-3527D5D5502C", 862, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-24T00:00:00", "04 23 24 28 32", "31", null ] -, [ 863, "805E4BEC-91C1-4A75-8465-568254B40416", 863, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-27T00:00:00", "04 10 26 32 41", "31", null ] -, [ 864, "8C850AB9-558A-4129-8544-0D9A634FA9E3", 864, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-08-31T00:00:00", "10 20 29 47 48", "38", null ] -, [ 865, "88CC3B82-9F43-4566-B130-C5517DBC33BA", 865, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-03T00:00:00", "10 13 20 28 36", "09", null ] -, [ 866, "E902EE49-B63A-4DB6-B67C-0FAAC30C3932", 866, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-07T00:00:00", "08 18 22 24 38", "23", null ] -, [ 867, "C78C1DE3-8629-429A-BD5B-C42A6F797F9C", 867, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-10T00:00:00", "11 12 17 21 23", "20", null ] -, [ 868, "CEBD219F-94FD-4152-9EC0-1A8395E776C9", 868, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-14T00:00:00", "06 14 50 55 56", "01", null ] -, [ 869, "2815439B-B45A-48AB-BC06-4E95BBDFED63", 869, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-17T00:00:00", "03 04 14 18 27", "13", null ] -, [ 870, "A4C211ED-A3C8-454D-B9AA-ED672D593BC0", 870, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-21T00:00:00", "03 20 43 47 52", "26", null ] -, [ 871, "3AE643AE-3752-4D4A-A8E3-A1EB0A794A48", 871, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-24T00:00:00", "02 28 38 42 55", "25", null ] -, [ 872, "1C36A6DE-F815-4E0C-BA3C-9144DA40C6B5", 872, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-09-28T00:00:00", "02 10 13 36 38", "18", null ] -, [ 873, "54F92A9D-74F4-4E96-802D-4C9838159251", 873, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-01T00:00:00", "03 08 21 28 52", "43", null ] -, [ 874, "A907DF1F-CDF1-4896-91D7-7FC18AEECBE6", 874, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-05T00:00:00", "10 19 24 37 44", "27", null ] -, [ 875, "8A737E94-9C1C-4D08-8BC8-9269BBC8D96F", 875, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-08T00:00:00", "24 29 37 48 50", "19", null ] -, [ 876, "E2152E19-B4AF-4B12-822B-4F8B9222C1ED", 876, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-12T00:00:00", "10 31 36 37 43", "15", null ] -, [ 877, "F3D56D53-59CA-4F5B-9758-79848E9FAF15", 877, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-15T00:00:00", "09 10 13 31 50", "10", null ] -, [ 878, "22C9895B-CEDF-400F-92EA-223B53FDA227", 878, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-19T00:00:00", "02 09 14 37 42", "41", null ] -, [ 879, "A0A4388D-A0C0-4614-8CE5-0EC197C3A92F", 879, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-22T00:00:00", "02 07 18 32 53", "18", null ] -, [ 880, "21185BC4-A0B6-401F-966C-F05F66A4AAAB", 880, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-26T00:00:00", "15 21 30 31 32", "26", null ] -, [ 881, "FF4917B9-749B-4410-B9AB-52130F6DF61C", 881, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-10-29T00:00:00", "04 19 26 28 39", "14", null ] -, [ 882, "6807A66D-E7DC-419D-AF2D-E4F2FCBCB6F4", 882, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-02T00:00:00", "01 03 12 16 54", "46", null ] -, [ 883, "FAA07034-9641-44B4-B65A-DBEBBD6750AC", 883, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-05T00:00:00", "19 25 34 46 53", "15", null ] -, [ 884, "B4C6A53B-F3AF-4867-84F5-55FB664CB90B", 884, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-09T00:00:00", "08 26 28 33 53", "11", null ] -, [ 885, "02A30C8B-B84D-4933-B04C-9188538A5FA7", 885, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-12T00:00:00", "09 26 28 35 38", "10", null ] -, [ 886, "11F16F0E-CB24-4E7D-A5F4-4BBF478A37FE", 886, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-16T00:00:00", "01 26 27 39 46", "21", null ] -, [ 887, "9E8A03C2-DFEC-4112-A696-EA9DDAD9E046", 887, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-19T00:00:00", "07 14 31 51 54", "35", null ] -, [ 888, "A96DE32B-3967-48BA-B33B-D1018E35334B", 888, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-23T00:00:00", "02 06 12 34 35", "33", null ] -, [ 889, "4CA5F4E1-FBE4-4E1E-A4B7-1C587DAB70ED", 889, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-26T00:00:00", "05 09 34 43 47", "08", null ] -, [ 890, "0AA621FC-44F6-487F-B81C-E2AE461301EF", 890, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-11-30T00:00:00", "11 16 19 47 53", "02", null ] -, [ 891, "D1529B07-F805-41BC-A0C0-1551575AE197", 891, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-03T00:00:00", "06 11 12 18 56", "12", null ] -, [ 892, "04CE11BD-8B0D-437E-8E0C-0C4B1D14C47D", 892, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-07T00:00:00", "04 38 45 53 54", "09", null ] -, [ 893, "BBE92898-012A-42EF-B481-64C5226EB753", 893, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-10T00:00:00", "23 27 33 44 46", "36", null ] -, [ 894, "9002B5AC-EE00-4406-A18D-3F2B219DC32A", 894, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-14T00:00:00", "18 22 25 31 38", "29", null ] -, [ 895, "FC1726CE-A844-4A99-9DFA-D539BDDCA6D4", 895, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-17T00:00:00", "11 20 26 46 53", "12", null ] -, [ 896, "A09E249A-42AA-4FC7-A7AE-DE5A7A81730D", 896, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-21T00:00:00", "08 11 12 31 32", "29", null ] -, [ 897, "06BBE3E8-F94D-4C38-84D0-B69EA134FFBF", 897, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-24T00:00:00", "15 16 27 40 52", "16", null ] -, [ 898, "20564B01-7B85-4448-B8E7-20634A4F9BDF", 898, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-28T00:00:00", "06 18 36 40 49", "07", null ] -, [ 899, "13965554-94D3-4B1F-918E-873DBCAF3770", 899, 1362743863, "706580", 1362743863, "706580", "{\n}", "2010-12-31T00:00:00", "10 12 13 35 56", "09", null ] -, [ 900, "2C0357BE-D0C4-4F6B-AD5D-454A3B01C445", 900, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-04T00:00:00", "04 08 15 25 47", "42", null ] -, [ 901, "77D470C4-97D8-4CD6-9CA7-E859EEAB4ED4", 901, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-07T00:00:00", "04 22 42 46 53", "20", null ] -, [ 902, "26BAF649-07AE-4D93-B04E-FBE9CC8E49C7", 902, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-11T00:00:00", "01 04 11 16 45", "37", null ] -, [ 903, "ED65CBC2-082D-49D7-A606-6BE130637FD4", 903, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-14T00:00:00", "02 15 17 33 35", "08", null ] -, [ 904, "79DED60A-4528-436F-96B3-20A5ECD2A325", 904, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-18T00:00:00", "04 27 29 38 45", "05", "04" ] -, [ 905, "E504A2AA-4A80-4CA3-87F4-7126B60E3CB2", 905, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-21T00:00:00", "05 09 21 35 38", "20", "04" ] -, [ 906, "6F676480-6614-4824-B7A0-A26A8B685BFE", 906, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-25T00:00:00", "05 08 31 46 50", "04", "04" ] -, [ 907, "C299984A-6FD1-46F2-A7FE-BF6FBA223648", 907, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-01-28T00:00:00", "14 33 48 49 50", "18", "04" ] -, [ 908, "DB803BB1-1023-4152-BE1A-677F08638237", 908, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-01T00:00:00", "16 22 23 26 35", "31", "04" ] -, [ 909, "59B74F61-2A5E-45D6-A80C-555F393BE9D2", 909, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-04T00:00:00", "06 20 29 48 55", "06", "04" ] -, [ 910, "ED342343-2A2F-43D9-A4AF-B0E8975A8D4F", 910, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-08T00:00:00", "25 35 36 47 48", "18", "02" ] -, [ 911, "997BA78B-4852-4D68-9136-0985CFF2A1B2", 911, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-11T00:00:00", "08 09 17 32 34", "13", "02" ] -, [ 912, "B9185736-00EE-445E-ABF2-68FD1FD9D41A", 912, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-15T00:00:00", "17 18 24 35 39", "18", "04" ] -, [ 913, "97470996-54FB-43DD-A51C-DCAC8B285499", 913, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-18T00:00:00", "05 06 07 30 45", "42", "03" ] -, [ 914, "1648D615-BF93-43BB-914C-ED9917530014", 914, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-22T00:00:00", "15 22 23 48 55", "31", "04" ] -, [ 915, "1706FD60-3151-4521-8369-ECCF5713BDF4", 915, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-02-25T00:00:00", "04 05 17 19 50", "07", "04" ] -, [ 916, "C31F64C8-FC0C-4378-A874-B3525CAEB27B", 916, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-01T00:00:00", "01 12 19 20 47", "25", "03" ] -, [ 917, "E7B38725-6D52-4D74-BE16-3EA8FDD10522", 917, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-04T00:00:00", "08 10 15 23 41", "07", "04" ] -, [ 918, "85F41156-0B86-480C-B223-BF206B9C4E8C", 918, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-08T00:00:00", "03 17 19 41 55", "24", "04" ] -, [ 919, "9377C452-D026-450A-B335-10C3709281F7", 919, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-11T00:00:00", "14 19 21 42 45", "06", "02" ] -, [ 920, "ED632697-783D-40E4-BBFA-BC9082954A7C", 920, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-15T00:00:00", "10 11 12 28 43", "45", "04" ] -, [ 921, "8681263B-5DAA-42EF-91EC-B7696A1E0849", 921, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-18T00:00:00", "14 33 34 54 56", "37", "04" ] -, [ 922, "3A284E39-1A0C-437A-A226-D221A4662F82", 922, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-22T00:00:00", "01 14 35 50 53", "43", "04" ] -, [ 923, "0CA4411F-F91F-4E80-B481-B5623FD47A33", 923, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-25T00:00:00", "22 24 31 52 54", "04", "04" ] -, [ 924, "CA55CA0F-FA9E-4348-B093-FC8A814140CB", 924, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-03-29T00:00:00", "06 15 23 34 38", "43", "04" ] -, [ 925, "EE5FC4AE-6C59-49BD-A6B9-CB0A04129E71", 925, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-01T00:00:00", "13 14 35 36 53", "19", "03" ] -, [ 926, "B70B7726-A102-489D-BF40-EB1F09381F4F", 926, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-05T00:00:00", "01 19 20 31 36", "09", "02" ] -, [ 927, "12A34C6D-6E1C-4888-B5F8-897E69681A44", 927, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-08T00:00:00", "06 40 45 50 56", "11", "03" ] -, [ 928, "8A851800-D763-454E-82FC-A8EBABA79F79", 928, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-12T00:00:00", "10 23 39 41 45", "15", "02" ] -, [ 929, "DFD2C533-7E17-4E64-8DE2-708A88683D96", 929, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-15T00:00:00", "22 23 33 39 48", "29", "03" ] -, [ 930, "C91C01F8-E7EF-4BBF-BCD3-C10695E342D3", 930, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-19T00:00:00", "20 24 32 45 51", "43", "04" ] -, [ 931, "C9A991A6-F088-4BF5-86CC-7786BCC4B8BF", 931, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-22T00:00:00", "03 18 46 51 53", "17", "03" ] -, [ 932, "082306E6-63D4-4E90-885E-4F29F45038B2", 932, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-26T00:00:00", "19 29 32 38 55", "15", "03" ] -, [ 933, "FDB58993-7061-4DCD-BD25-97ED0F318800", 933, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-04-29T00:00:00", "09 10 11 33 51", "29", "04" ] -, [ 934, "E042D17F-5ECB-40B2-8F2B-8326E77CFAD1", 934, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-03T00:00:00", "01 16 29 36 50", "16", "02" ] -, [ 935, "BCB6D64F-B258-40C3-BC82-EA562C957524", 935, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-06T00:00:00", "06 18 26 37 41", "09", "03" ] -, [ 936, "53C3DF38-DE02-49F1-90A2-108EB17948DD", 936, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-10T00:00:00", "11 16 34 40 51", "34", "04" ] -, [ 937, "9062FC96-A0F7-4EBC-9222-207F6758945C", 937, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-13T00:00:00", "03 33 39 47 53", "09", "04" ] -, [ 938, "32BB7177-E9EB-47B6-84FC-548D8B8A8406", 938, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-17T00:00:00", "01 02 17 25 48", "45", "04" ] -, [ 939, "27A3671C-10EF-401B-A767-610E60A6D0D4", 939, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-20T00:00:00", "10 17 19 45 48", "30", "04" ] -, [ 940, "3F03D46F-A972-431C-9605-B0CEDDFBB538", 940, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-24T00:00:00", "09 12 21 42 43", "42", "03" ] -, [ 941, "B4084B59-39C3-4252-9F9A-BB40B2CDB0E3", 941, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-27T00:00:00", "05 07 14 28 56", "10", "04" ] -, [ 942, "D7487BF7-2906-4A83-9BD9-98340B7FF036", 942, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-05-31T00:00:00", "28 30 31 37 55", "13", "03" ] -, [ 943, "361175FE-70B8-4080-BCBE-DB3E33556884", 943, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-03T00:00:00", "20 23 41 49 53", "31", "03" ] -, [ 944, "78C57DD5-875D-4F58-BFD9-121A6426D17B", 944, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-07T00:00:00", "29 32 35 47 52", "13", "04" ] -, [ 945, "9B6A425B-C5D3-4060-BAE7-97BDCC0BA7A4", 945, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-10T00:00:00", "18 21 27 37 38", "07", "03" ] -, [ 946, "9FDFF7B8-D455-4EE2-9AF2-7863146C4254", 946, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-14T00:00:00", "09 10 20 51 53", "24", "04" ] -, [ 947, "E4FE6C91-145A-4F31-9329-2976DC2DC0B1", 947, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-17T00:00:00", "12 29 46 47 51", "24", "04" ] -, [ 948, "12BDCBD8-F24B-48B1-867C-FD63ACC61CBF", 948, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-21T00:00:00", "11 24 25 31 46", "17", "03" ] -, [ 949, "1767DF09-F7CC-4762-B402-0E78147849D2", 949, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-24T00:00:00", "10 14 40 49 51", "04", "03" ] -, [ 950, "75829CF8-883B-4288-A747-9CF265DA50D9", 950, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-06-28T00:00:00", "12 17 27 47 48", "33", "04" ] -, [ 951, "C4C4306D-220A-43A8-A17B-6CFB22A90C45", 951, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-01T00:00:00", "12 17 30 35 47", "26", "04" ] -, [ 952, "1D651FF1-7190-422B-9E1C-9A964497C63B", 952, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-05T00:00:00", "01 10 13 18 46", "19", "02" ] -, [ 953, "15662C19-F99B-4447-9E80-6C8BDD767BBD", 953, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-08T00:00:00", "01 02 22 37 50", "45", "03" ] -, [ 954, "F61F010C-3070-4BCA-B84E-9040E840FB7B", 954, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-12T00:00:00", "03 09 11 44 49", "09", "04" ] -, [ 955, "03407F0F-604A-442F-A41E-4EA6CAFF01B7", 955, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-15T00:00:00", "16 29 30 46 56", "06", "03" ] -, [ 956, "4F5FE17B-8F5B-4648-9C22-FF9C6CB4626A", 956, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-19T00:00:00", "02 09 10 16 35", "40", "04" ] -, [ 957, "FE5C7077-5151-4BDF-A84B-148E50276C42", 957, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-22T00:00:00", "23 31 32 39 56", "38", "04" ] -, [ 958, "7AB8C5B6-90EB-4D60-9460-5F2AA356D05F", 958, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-26T00:00:00", "20 25 35 52 55", "10", "03" ] -, [ 959, "4083D81B-59EA-4E2D-B1F4-BEA1BCB41C25", 959, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-07-29T00:00:00", "08 10 22 47 48", "35", "04" ] -, [ 960, "61B4C46D-7E74-4438-950B-90514726608E", 960, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-02T00:00:00", "14 17 19 20 32", "28", "04" ] -, [ 961, "2CC54035-3718-4107-97B6-4BE09FD71596", 961, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-05T00:00:00", "06 24 28 33 42", "19", "03" ] -, [ 962, "C857D075-C3B6-4F20-A7DA-1DC845609E06", 962, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-09T00:00:00", "11 19 39 45 54", "15", "04" ] -, [ 963, "2CA2F348-42C1-4F15-8DDB-98966C409F07", 963, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-12T00:00:00", "09 43 51 54 55", "13", "04" ] -, [ 964, "1C06FA2B-34CA-4FF9-839A-FA0CBD905412", 964, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-16T00:00:00", "04 38 41 42 43", "44", "04" ] -, [ 965, "A7002E4C-D525-4F4C-A6AD-CBCB5A398BF1", 965, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-19T00:00:00", "05 15 53 54 56", "22", "02" ] -, [ 966, "D9A6699C-0C64-4546-8D22-6D6AC65F2EEF", 966, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-23T00:00:00", "11 21 44 48 49", "23", "03" ] -, [ 967, "E52436B0-9F29-4E7F-81D9-D21216826900", 967, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-26T00:00:00", "02 03 27 30 47", "36", "03" ] -, [ 968, "A26F102A-2C79-4F3D-A3E7-F3C58BF013A5", 968, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-08-30T00:00:00", "02 22 25 28 50", "18", "04" ] -, [ 969, "C577652E-D5BA-4C64-95CD-7FE4113D1534", 969, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-02T00:00:00", "25 44 48 49 55", "20", "03" ] -, [ 970, "353CE32E-67DD-4000-A3B2-165DBE4F2AAD", 970, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-06T00:00:00", "01 36 38 42 49", "19", "04" ] -, [ 971, "DA63C527-7600-4B8C-B383-C60019F11E5A", 971, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-09T00:00:00", "07 12 19 23 31", "45", "04" ] -, [ 972, "1A5842C0-C7C8-4AE5-B7A0-C6E8526ECD60", 972, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-13T00:00:00", "22 31 43 48 56", "45", "04" ] -, [ 973, "B7BAA60D-4658-4CB5-A865-D8C09693BBE7", 973, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-16T00:00:00", "06 23 41 45 56", "24", "04" ] -, [ 974, "A79C80C8-5F1B-43F2-A85A-4EABE40717B1", 974, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-20T00:00:00", "06 29 38 50 51", "39", "04" ] -, [ 975, "9C7F9D8A-9F22-4D27-AA9F-6B33AC7E70C1", 975, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-23T00:00:00", "27 31 32 40 52", "36", "04" ] -, [ 976, "AD2198FD-D11B-4183-9795-0F6E1B615274", 976, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-27T00:00:00", "02 20 28 36 45", "37", "04" ] -, [ 977, "14359A50-4A72-49E1-BA4F-88F1D18FEDFD", 977, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-09-30T00:00:00", "03 19 21 44 45", "29", "04" ] -, [ 978, "30A42918-32C3-4CE6-987F-AA1F27428177", 978, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-04T00:00:00", "03 26 40 45 52", "11", "03" ] -, [ 979, "01BF3321-0A60-4A1E-B5BE-81C2EFF99377", 979, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-07T00:00:00", "05 15 19 23 38", "19", "04" ] -, [ 980, "151F6F6E-3E97-4C7D-B393-6F4E62FF5239", 980, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-11T00:00:00", "25 34 38 44 56", "27", "04" ] -, [ 981, "786305BD-AE43-4B74-904E-236BDC499173", 981, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-14T00:00:00", "13 35 42 45 54", "26", "04" ] -, [ 982, "4D851549-3C28-40F9-9007-52231A2ED3EC", 982, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-18T00:00:00", "24 25 45 47 53", "42", "02" ] -, [ 983, "9EF3EFE4-9B8F-4014-8255-65EE45D9C3BE", 983, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-21T00:00:00", "06 21 35 37 38", "17", "03" ] -, [ 984, "5A28EBCE-5991-4A98-9931-5F1188307510", 984, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-25T00:00:00", "13 33 40 44 46", "08", "04" ] -, [ 985, "9B8BD3AB-FC4E-4877-856E-ACBC96EB4FCA", 985, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-10-28T00:00:00", "13 31 49 52 56", "41", "04" ] -, [ 986, "23D572A8-4943-416E-8344-79058FA41CDD", 986, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-01T00:00:00", "27 31 39 40 46", "36", "03" ] -, [ 987, "AE43DCE8-48BD-4103-A73D-1A9727E2616D", 987, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-04T00:00:00", "26 30 32 33 44", "01", "04" ] -, [ 988, "86A6904E-420B-4093-B38E-5B2786E20787", 988, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-08T00:00:00", "05 31 45 47 54", "04", "04" ] -, [ 989, "FCB62BE1-0722-40C7-A08E-C6E4938DC12C", 989, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-11T00:00:00", "02 16 22 29 50", "27", "04" ] -, [ 990, "7AE6EB76-503C-4BD5-BF39-A80C061F7F41", 990, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-15T00:00:00", "03 06 24 30 33", "21", "04" ] -, [ 991, "E5B962F9-B0B4-458D-9E1D-9E13AB973BD5", 991, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-18T00:00:00", "04 13 33 39 55", "03", "04" ] -, [ 992, "EB0D798E-AE4A-43BA-95DF-C7BBC32EBD9B", 992, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-22T00:00:00", "04 16 23 33 48", "38", "02" ] -, [ 993, "ACF4DF8E-BE16-45A6-BEDF-88206B701D0B", 993, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-25T00:00:00", "22 28 42 49 54", "43", "03" ] -, [ 994, "165668FF-6882-4BD5-8F20-466C5642A6CF", 994, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-11-29T00:00:00", "17 29 43 48 52", "36", "04" ] -, [ 995, "A2363856-2A4E-4701-A67B-94FC6ACA1DB0", 995, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-02T00:00:00", "24 30 48 51 56", "45", "04" ] -, [ 996, "532D6096-7C43-49C0-BB8C-212540A0DE99", 996, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-06T00:00:00", "07 21 29 35 49", "39", "04" ] -, [ 997, "C4B9DE45-9917-4551-9E78-8DA354CD74A6", 997, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-09T00:00:00", "04 12 29 49 51", "44", "04" ] -, [ 998, "24CB3C7A-76D3-4FCA-8ECE-C49794E30096", 998, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-13T00:00:00", "05 06 22 26 41", "06", "04" ] -, [ 999, "C30F212B-2CE3-406A-B3CB-28B6307A4A5D", 999, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-16T00:00:00", "02 04 26 36 39", "27", "03" ] -, [ 1000, "CD1A74E7-9E48-485B-8821-BFF2B6ECB703", 1000, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-20T00:00:00", "20 24 27 45 51", "31", "04" ] -, [ 1001, "4EDD3812-7564-4A29-B3E8-D64EE36AC9A7", 1001, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-23T00:00:00", "03 05 08 18 29", "14", "04" ] -, [ 1002, "D387D16A-8078-4E85-B4A1-E24BBDF45CC8", 1002, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-27T00:00:00", "23 32 33 39 43", "08", "03" ] -, [ 1003, "2F7BF875-07B8-4155-A068-229749172CDE", 1003, 1362743863, "706580", 1362743863, "706580", "{\n}", "2011-12-30T00:00:00", "04 24 45 46 52", "01", "04" ] -, [ 1004, "889504F6-0DFA-46AE-A744-B83293ABC371", 1004, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-03T00:00:00", "02 03 15 22 36", "23", "02" ] -, [ 1005, "76A27770-967F-411A-9748-CF2390EE3076", 1005, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-06T00:00:00", "09 17 28 34 48", "46", "02" ] -, [ 1006, "BA255100-BE0C-4719-A6D8-8E4E9BEA6A6C", 1006, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-10T00:00:00", "04 10 16 38 48", "34", "03" ] -, [ 1007, "82C36070-B9A3-4229-941D-B78430B169E2", 1007, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-13T00:00:00", "10 27 28 37 51", "19", "03" ] -, [ 1008, "75E0C7D8-ECD3-4DE1-9A7D-535F3B20CB3B", 1008, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-17T00:00:00", "03 15 31 36 53", "27", "02" ] -, [ 1009, "4ED7B6B9-35E5-42F5-B252-E57C515EE88E", 1009, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-20T00:00:00", "01 09 28 38 47", "08", "02" ] -, [ 1010, "BC86C784-2F3B-4403-A7DA-AD689471EC92", 1010, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-24T00:00:00", "10 22 24 36 49", "33", "04" ] -, [ 1011, "B8BD18B7-206A-4EBE-8DF8-45758EAA7A9D", 1011, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-27T00:00:00", "03 05 30 36 48", "23", "04" ] -, [ 1012, "3BBB4C54-DAF1-4D85-964B-D454BD35F996", 1012, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-01-31T00:00:00", "09 17 18 28 43", "09", "03" ] -, [ 1013, "EE2BB967-740B-41F2-8E2F-C714F30640E3", 1013, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-03T00:00:00", "07 19 21 49 53", "35", "04" ] -, [ 1014, "70FCEB5F-1CF6-4FFB-AD16-BAD74E82508E", 1014, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-07T00:00:00", "17 23 30 37 45", "04", "04" ] -, [ 1015, "32CE4FC2-B7D8-4D53-8BE9-5C71C805DB1E", 1015, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-10T00:00:00", "03 04 18 29 50", "20", "04" ] -, [ 1016, "A6C2E716-7C33-4C21-8F6D-FD67832236CF", 1016, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-14T00:00:00", "03 05 10 26 27", "27", "02" ] -, [ 1017, "78CC6486-2735-47CA-871D-EB288034B18F", 1017, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-17T00:00:00", "16 25 28 32 40", "03", "03" ] -, [ 1018, "47263F7C-71EE-43E4-975B-3C5DF80046B7", 1018, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-21T00:00:00", "09 30 39 42 47", "37", "03" ] -, [ 1019, "B5FD41BF-5398-4E7C-A04B-6110ABD8EEED", 1019, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-24T00:00:00", "01 16 18 25 27", "03", "04" ] -, [ 1020, "2568AF78-E4B3-4C0A-9D84-EB2BBA8674C7", 1020, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-02-28T00:00:00", "06 15 29 39 51", "36", "03" ] -, [ 1021, "A33ED94D-C63F-4D5A-A22D-74A6B3B37642", 1021, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-02T00:00:00", "16 29 48 52 54", "05", "02" ] -, [ 1022, "59AE5BFB-80D6-405A-9625-2B69FCD4B05E", 1022, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-06T00:00:00", "20 24 31 33 36", "44", "04" ] -, [ 1023, "032F093E-4D73-4CBE-8326-F24E4EA1ED75", 1023, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-09T00:00:00", "09 10 27 36 42", "11", "04" ] -, [ 1024, "CA113647-C098-4AEF-A96D-15D60FB897F8", 1024, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-13T00:00:00", "02 08 30 36 48", "31", "03" ] -, [ 1025, "44AA3D24-858A-406C-B594-06AE881897FE", 1025, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-16T00:00:00", "28 29 43 51 53", "07", "03" ] -, [ 1026, "24B69175-A86E-4AFA-8907-6B9ECFFD4D90", 1026, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-20T00:00:00", "01 04 06 11 14", "30", "04" ] -, [ 1027, "2D3BF97D-85C5-4BAD-ABF3-8E2D6376AA64", 1027, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-23T00:00:00", "06 17 19 20 21", "20", "04" ] -, [ 1028, "287A0E8A-4CA3-46CD-99D5-DA0C70EA8623", 1028, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-27T00:00:00", "09 19 34 44 51", "24", "03" ] -, [ 1029, "E0CBAB93-0D60-4131-B751-AF175E839DC5", 1029, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-03-30T00:00:00", "02 04 23 38 46", "23", "03" ] -, [ 1030, "2B8F29D2-4F87-4FF3-940F-61A8BB5EAEF5", 1030, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-03T00:00:00", "11 35 38 41 52", "40", "04" ] -, [ 1031, "4C5219FC-B9CE-49D3-B015-16B2E70787E4", 1031, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-06T00:00:00", "02 19 20 24 33", "39", "04" ] -, [ 1032, "A9D5BE40-C127-4D07-B697-FF1A5C1F23D0", 1032, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-10T00:00:00", "02 06 12 31 48", "25", "04" ] -, [ 1033, "2800F10F-2350-4D18-90BD-08B9D6AB5147", 1033, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-13T00:00:00", "09 14 17 36 42", "33", "04" ] -, [ 1034, "30125944-9595-44DC-9BC2-496EF0A18A0F", 1034, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-17T00:00:00", "01 16 24 32 48", "02", "04" ] -, [ 1035, "B1EC5474-6214-4C5C-8AF8-DB582A346125", 1035, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-20T00:00:00", "14 23 26 33 35", "40", "03" ] -, [ 1036, "5F6AEAD5-C667-4EFF-93F6-55E65CDD6E53", 1036, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-24T00:00:00", "03 09 15 37 38", "39", "04" ] -, [ 1037, "0F0DA791-5E11-413F-9116-17E2CA8A4393", 1037, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-04-27T00:00:00", "02 05 45 46 47", "37", "04" ] -, [ 1038, "0C71166B-0DEE-4DC7-91B1-C07F5A983930", 1038, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-01T00:00:00", "24 27 31 45 52", "38", "04" ] -, [ 1039, "B932BD1C-ADB6-4055-BA78-6C974B288CA4", 1039, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-04T00:00:00", "04 11 21 42 53", "38", "04" ] -, [ 1040, "BE8AF87B-F38F-4E90-94AA-A7DFC3311A72", 1040, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-08T00:00:00", "02 06 08 18 51", "19", "03" ] -, [ 1041, "A94A8741-F148-4E47-8537-2D677D998EA8", 1041, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-11T00:00:00", "03 15 29 35 54", "08", "04" ] -, [ 1042, "72D8AD79-C9F3-4DF2-BADF-3DE68622F209", 1042, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-15T00:00:00", "10 11 12 14 24", "06", "04" ] -, [ 1043, "6C599BA2-2F12-42D0-92BD-08C0C744DC82", 1043, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-18T00:00:00", "03 11 22 34 49", "01", "04" ] -, [ 1044, "723FDBC5-CFF6-4E47-BF82-2239FFD02151", 1044, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-22T00:00:00", "10 14 35 43 52", "16", "02" ] -, [ 1045, "A5BBE96D-3E42-4E92-BDCB-EB8AE2FEE2E6", 1045, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-25T00:00:00", "09 15 21 40 54", "11", "04" ] -, [ 1046, "305F4750-B4FE-4239-94CC-200981921FE8", 1046, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-05-29T00:00:00", "02 14 29 53 55", "31", "03" ] -, [ 1047, "BED1DE4C-7487-4697-ABB0-6EE0DE1D4C04", 1047, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-01T00:00:00", "02 27 38 46 52", "45", "03" ] -, [ 1048, "B6CC489D-1533-43CA-89AA-DEC3FA71868C", 1048, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-05T00:00:00", "37 39 42 53 55", "22", "03" ] -, [ 1049, "B282494C-029B-48A5-A971-BA1921A48F9C", 1049, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-08T00:00:00", "04 09 34 40 48", "25", "03" ] -, [ 1050, "705B58FB-961E-4DFB-9CE5-DD699AE6FE85", 1050, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-12T00:00:00", "02 09 17 34 50", "45", "04" ] -, [ 1051, "1AA6BC29-665A-4273-A019-CB18A0EF7E50", 1051, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-15T00:00:00", "08 12 18 30 40", "04", "03" ] -, [ 1052, "D28DA568-A586-4B07-BFCA-B6EFFF9E1E31", 1052, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-19T00:00:00", "11 21 27 30 53", "11", "02" ] -, [ 1053, "3AF12744-1D00-4BAC-8FA5-2843BBA1A78D", 1053, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-22T00:00:00", "10 16 19 32 36", "13", "03" ] -, [ 1054, "8EAB153B-B676-4A10-A75F-8360F91F7055", 1054, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-26T00:00:00", "03 16 23 35 36", "20", "04" ] -, [ 1055, "5352FDFD-E36E-422B-ADA4-587EC8275C8F", 1055, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-06-29T00:00:00", "28 34 39 45 53", "34", "04" ] -, [ 1056, "26E044FD-9174-44BF-9C91-E9FA6815CEF0", 1056, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-03T00:00:00", "03 04 24 36 52", "45", "04" ] -, [ 1057, "2FA5C720-4FDC-4A9F-B91F-07D4A92EA36C", 1057, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-06T00:00:00", "20 23 28 35 39", "21", "03" ] -, [ 1058, "7A122C50-A85E-403D-B68B-93290FAAC6D0", 1058, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-10T00:00:00", "03 11 19 23 36", "21", "04" ] -, [ 1059, "5478F179-CB82-4D15-8BFF-406E7560B55C", 1059, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-13T00:00:00", "06 07 13 24 46", "34", "02" ] -, [ 1060, "87740C9F-5839-4E38-8941-538016EB7A1B", 1060, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-17T00:00:00", "01 13 21 49 55", "17", "04" ] -, [ 1061, "E8F5ECD9-405B-4DDC-BB35-6247149D2DD7", 1061, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-20T00:00:00", "02 44 48 50 52", "03", "03" ] -, [ 1062, "21E69FF5-7872-4D58-AD7D-419F6B34AB5B", 1062, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-24T00:00:00", "05 09 38 46 51", "05", "04" ] -, [ 1063, "2714EA68-34BE-4055-8BC1-C907DE0D79FD", 1063, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-27T00:00:00", "02 03 04 08 43", "26", "03" ] -, [ 1064, "F0BBD71B-BB7C-4A97-8582-F86CA8B2F948", 1064, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-07-31T00:00:00", "05 18 21 29 41", "37", "03" ] -, [ 1065, "D86272A6-5D75-425F-A394-6165EA82158F", 1065, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-03T00:00:00", "02 10 13 38 46", "02", "03" ] -, [ 1066, "24D037E0-9557-4E57-AEB6-EECC0B19A7EE", 1066, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-07T00:00:00", "30 32 33 42 48", "07", "04" ] -, [ 1067, "50ECF7BF-2414-4BDA-837F-37F70F919736", 1067, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-10T00:00:00", "10 18 36 38 44", "08", "04" ] -, [ 1068, "49E869CF-430E-40E1-9505-A56BF9E5C452", 1068, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-14T00:00:00", "15 23 34 39 55", "32", "04" ] -, [ 1069, "4C5FA5C7-BA64-457B-86B4-0E8DB3627DBA", 1069, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-17T00:00:00", "08 20 24 35 56", "24", "03" ] -, [ 1070, "81506B15-2BAB-43FE-B9D7-9C71A8AF4EE9", 1070, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-21T00:00:00", "05 13 20 23 33", "30", "02" ] -, [ 1071, "952B076F-8AE1-400D-93BA-9867E014DFA2", 1071, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-24T00:00:00", "25 34 45 46 49", "34", "02" ] -, [ 1072, "3AFF5326-08D1-4F56-BEAE-51B9F7D0996A", 1072, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-28T00:00:00", "04 09 40 45 50", "39", "04" ] -, [ 1073, "537C9CD1-1310-4E5E-809B-D3E090056EE7", 1073, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-08-31T00:00:00", "31 40 41 47 48", "45", "03" ] -, [ 1074, "DF515955-CF4F-45B9-9936-F22EAF2DB035", 1074, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-04T00:00:00", "16 32 39 41 53", "16", "03" ] -, [ 1075, "C58215A7-C613-40B9-8927-C97403B4E82E", 1075, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-07T00:00:00", "15 32 38 42 46", "31", "04" ] -, [ 1076, "245ED977-E62E-4E8C-B64C-B17A1402870B", 1076, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-11T00:00:00", "05 11 20 33 36", "11", "03" ] -, [ 1077, "9F3F66A2-40BD-4955-B76E-EDCEBBAB20B0", 1077, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-14T00:00:00", "16 17 21 40 51", "20", "04" ] -, [ 1078, "2BE42A83-7582-4311-976D-63325F6C3321", 1078, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-18T00:00:00", "05 09 22 36 49", "36", "03" ] -, [ 1079, "DF65731A-4ADB-4724-B5B1-C2D61E1D39E6", 1079, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-21T00:00:00", "03 13 14 46 55", "34", "04" ] -, [ 1080, "7EF88A92-5329-4F32-8B37-43827B42F8D5", 1080, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-25T00:00:00", "07 08 23 50 51", "26", "03" ] -, [ 1081, "DFF13765-B557-4D84-80BF-8020B16F7107", 1081, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-09-28T00:00:00", "06 08 14 43 56", "28", "04" ] -, [ 1082, "E85924F2-4908-48C8-B845-CF32BE2D6D82", 1082, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-02T00:00:00", "10 11 20 42 55", "09", "04" ] -, [ 1083, "4136F9B6-D4E6-406E-A256-F09FE9C08F6A", 1083, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-05T00:00:00", "08 09 16 32 39", "15", "03" ] -, [ 1084, "8FC75879-BBB0-4BFD-817D-DFAC4BC5FC53", 1084, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-09T00:00:00", "06 15 16 22 37", "03", "04" ] -, [ 1085, "DA6C0387-AAC5-4D7B-8AB8-ACFB2DE932D7", 1085, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-12T00:00:00", "06 10 24 26 42", "15", "04" ] -, [ 1086, "77632ABE-F1FE-4DF7-9A02-4F3971F88C0A", 1086, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-16T00:00:00", "13 37 40 46 52", "29", "04" ] -, [ 1087, "35A41C79-9F9F-4051-8324-4E01959AF6F2", 1087, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-19T00:00:00", "14 34 36 48 53", "42", "03" ] -, [ 1088, "C43C079A-8259-46AE-AD0C-C1171C0D9702", 1088, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-23T00:00:00", "01 17 42 46 55", "01", "02" ] -, [ 1089, "46175276-4C66-4662-A23B-43E736DA2823", 1089, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-26T00:00:00", "04 15 24 36 40", "44", "02" ] -, [ 1090, "717D3849-2E82-4B11-8869-916662186A7D", 1090, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-10-30T00:00:00", "05 12 18 29 56", "38", "04" ] -, [ 1091, "37B75EFB-58C1-4F42-8B5C-F8EC5B381204", 1091, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-02T00:00:00", "04 18 22 38 44", "24", "03" ] -, [ 1092, "BA9E7188-173F-4C06-94C2-FA01ED9B3A64", 1092, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-06T00:00:00", "03 05 13 32 35", "06", "03" ] -, [ 1093, "D4EF0869-D9F0-4ADC-BE7B-356178EBA83A", 1093, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-09T00:00:00", "18 22 33 35 40", "11", "04" ] -, [ 1094, "167AB7D8-1685-45F9-B174-BBD1A7209F65", 1094, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-13T00:00:00", "06 12 31 46 56", "34", "02" ] -, [ 1095, "00FEB10F-0562-4691-9475-2E8DBF917745", 1095, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-16T00:00:00", "05 24 26 29 53", "36", "04" ] -, [ 1096, "FF917F07-13CC-4BA0-B947-7317F69BBD5D", 1096, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-20T00:00:00", "09 13 22 38 52", "44", "04" ] -, [ 1097, "EDE051F2-8DAF-4C2B-A7EE-A86E4C90C301", 1097, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-23T00:00:00", "08 37 44 47 48", "27", "04" ] -, [ 1098, "4FF05C3B-F34D-489D-A3BD-BF21FC01E90D", 1098, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-27T00:00:00", "05 12 26 42 49", "24", "04" ] -, [ 1099, "2CE2BB7D-AC4B-4524-8A19-EAEC23D1DB03", 1099, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-11-30T00:00:00", "11 22 24 28 31", "46", "03" ] -, [ 1100, "59EC55D3-6A65-4B9E-B764-A97714792364", 1100, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-04T00:00:00", "03 19 24 32 43", "44", "04" ] -, [ 1101, "F5EB2D52-1B44-493A-AAE3-7B024D35A473", 1101, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-07T00:00:00", "07 43 44 51 56", "04", "03" ] -, [ 1102, "4514531E-80EE-4556-B1A1-988590D025CC", 1102, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-11T00:00:00", "39 44 51 52 54", "13", "04" ] -, [ 1103, "B81A703D-FAC1-44E6-9686-652FD8271F71", 1103, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-14T00:00:00", "11 28 33 41 43", "41", "04" ] -, [ 1104, "7CEC7CB4-D889-44F3-8B63-6F8E50BD311A", 1104, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-18T00:00:00", "01 06 07 18 29", "16", "03" ] -, [ 1105, "F932DB93-4B9E-4563-A4B8-77E44190251B", 1105, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-21T00:00:00", "03 18 32 41 56", "19", "03" ] -, [ 1106, "F9751A75-3897-4B2A-A8B6-41481F808EB6", 1106, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-25T00:00:00", "02 03 18 34 48", "36", "04" ] -, [ 1107, "802578FB-DD16-4547-935D-D1148FBA842D", 1107, 1362743863, "706580", 1362743863, "706580", "{\n}", "2012-12-28T00:00:00", "10 13 32 40 41", "32", "04" ] -, [ 1108, "52CE7186-5986-428E-A395-B1C5D65A0BC0", 1108, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-01T00:00:00", "04 11 21 25 44", "29", "04" ] -, [ 1109, "AFC4FC11-6440-4195-A4D7-7BABF693798C", 1109, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-04T00:00:00", "01 02 23 25 55", "39", "04" ] -, [ 1110, "C7038282-827D-49CE-9421-AE78FADC4136", 1110, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-08T00:00:00", "03 20 21 38 42", "19", "04" ] -, [ 1111, "A1EE93AE-0700-4CEB-AAC1-E400CE47CF5E", 1111, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-11T00:00:00", "24 29 30 34 56", "01", "04" ] -, [ 1112, "6E6B28D8-DA3A-4A18-ACAA-ED5FBEE6F765", 1112, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-15T00:00:00", "01 06 12 19 41", "14", "04" ] -, [ 1113, "1CDA422F-6161-45AB-A608-3265EE8A02DF", 1113, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-18T00:00:00", "08 18 25 42 49", "14", "03" ] -, [ 1114, "D9BF1554-63B5-4AAB-B731-BDAC2ED2B49C", 1114, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-22T00:00:00", "07 11 16 39 54", "13", "03" ] -, [ 1115, "D9E2F748-C7A5-498C-9C34-ACCF4CD59C53", 1115, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-25T00:00:00", "11 12 17 31 48", "01", "04" ] -, [ 1116, "D354463F-ED6D-4C64-97BD-02F99BBFE12D", 1116, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-01-29T00:00:00", "08 12 27 46 47", "06", "03" ] -, [ 1117, "344BF005-5F14-456D-8F66-B045F0BDD0CF", 1117, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-01T00:00:00", "01 30 32 40 41", "17", "03" ] -, [ 1118, "FF269451-6A86-4792-86A0-F47F087E7B8C", 1118, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-05T00:00:00", "02 05 10 26 44", "46", "04" ] -, [ 1119, "946D9BF5-21CE-445F-9B54-23C00BF6B9A4", 1119, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-08T00:00:00", "06 15 20 39 50", "05", "04" ] -, [ 1120, "CCE92EEE-5DFE-46DC-A811-FB8FB6C42BDE", 1120, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-12T00:00:00", "09 22 32 38 55", "44", "03" ] -, [ 1121, "6E8DC59E-A1D3-4BE3-AD94-C9DDC798BCFD", 1121, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-15T00:00:00", "11 35 41 42 44", "42", "04" ] -, [ 1122, "267D0BD4-D7EF-4376-95B2-D11B5E4E4D2E", 1122, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-19T00:00:00", "01 15 19 30 56", "28", "03" ] -, [ 1123, "8E59FD84-CE6F-4F32-8BD6-24F2B2C6761A", 1123, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-22T00:00:00", "09 13 24 38 49", "30", "03" ] -, [ 1124, "CE025393-8E66-4A35-9785-3AF57314120E", 1124, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-02-26T00:00:00", "06 07 13 15 43", "07", "04" ] -, [ 1125, "41BAA06F-92DA-4FBD-BD08-6E0F30CC74EE", 1125, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-03-01T00:00:00", "17 30 38 43 51", "20", "04" ] -, [ 1126, "3C759335-70F9-43D8-8579-B10EE02BBA92", 1126, 1362743863, "706580", 1362743863, "706580", "{\n}", "2013-03-05T00:00:00", "06 20 39 41 46", "42", "03" ] -, [ 1128, "3BEE54D7-5827-423D-A45B-57280225C64B", 1128, 1363348969, "708543", 1363348969, "708543", "{\n}", "2013-03-08T00:00:00", "04 11 25 34 35", "44", "04" ] -, [ 1129, "9BA95032-4CD2-47C0-8849-B2763A756018", 1129, 1363348969, "708543", 1363348969, "708543", "{\n}", "2013-03-12T00:00:00", "09 12 19 20 30", "39", "04" ] -, [ 1131, "9EC242F7-CAF9-4BEE-8B68-69FFA06FD50E", 1131, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-03-15T00:00:00", "04 08 17 22 32", "08", "02" ] -, [ 1132, "ED91D5E6-75D0-461F-B75F-C71D05680F9A", 1132, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-03-19T00:00:00", "03 06 14 21 37", "35", "03" ] -, [ 1133, "484C92DF-9C91-44F8-A0D5-E6B1CA710ECE", 1133, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-03-22T00:00:00", "14 27 34 37 41", "38", "04" ] -, [ 1134, "3AE3734D-4290-4BFF-BEDC-6C80DFE1E017", 1134, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-03-26T00:00:00", "20 33 46 49 51", "46", "04" ] -, [ 1135, "D94AD183-ACB1-497A-8D41-0D4CB7C7A9B3", 1135, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-03-29T00:00:00", "25 31 36 46 53", "21", "04" ] -, [ 1136, "AAD7C104-063F-44FE-9871-D57F7AB15BCF", 1136, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-04-02T00:00:00", "07 10 14 40 47", "34", "04" ] -, [ 1137, "51CAFA51-4C1A-4680-A871-B8E95A4D5BC3", 1137, 1365512815, "708543", 1365512815, "708543", "{\n}", "2013-04-05T00:00:00", "08 15 23 36 41", "05", "03" ] -, [ 1139, "A6BC9F0F-78FE-46C4-A8B2-A814751D8620", 1139, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-09T00:00:00", "17 30 41 48 54", "13", "04" ] -, [ 1140, "31755A74-A1D7-4D79-9036-655BB9675711", 1140, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-12T00:00:00", "01 10 13 19 21", "28", "03" ] -, [ 1141, "C8DCB5D0-D886-4EA0-B036-2D28D8E566D2", 1141, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-16T00:00:00", "02 05 15 18 39", "42", "02" ] -, [ 1142, "68ACECAD-8C19-4528-9D43-66172BD23FF4", 1142, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-19T00:00:00", "06 08 12 22 43", "28", "04" ] -, [ 1143, "FB784F0E-D578-4096-BDB8-FE6B0AA6438B", 1143, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-23T00:00:00", "09 21 22 32 50", "10", "03" ] -, [ 1144, "51267C00-092E-4FAD-A0C2-0E80E5B287F8", 1144, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-26T00:00:00", "17 42 49 54 55", "31", "04" ] -, [ 1145, "BE7FCB7C-6D9A-4C53-9003-1762D1002834", 1145, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-04-30T00:00:00", "21 30 34 39 49", "43", "03" ] -, [ 1146, "37489A5A-AE35-4963-818A-79C81D7C420E", 1146, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-03T00:00:00", "02 20 34 42 54", "39", "02" ] -, [ 1147, "4103658B-1FCC-4C61-BD60-A25F14D7CB76", 1147, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-07T00:00:00", "01 06 13 20 51", "31", "04" ] -, [ 1148, "73828964-F4E0-4D97-9BE0-1030C96C06DD", 1148, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-10T00:00:00", "01 19 20 39 49", "28", "04" ] -, [ 1149, "CD109F37-1660-453B-B11F-E1A042F6367A", 1149, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-14T00:00:00", "06 10 12 28 32", "38", "04" ] -, [ 1150, "134C197F-4D35-46D5-97A8-363EC85C5F7A", 1150, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-17T00:00:00", "11 15 35 43 49", "41", "04" ] -, [ 1151, "D31E4D6A-1ED7-46E9-8801-C538F2B00DF8", 1151, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-21T00:00:00", "02 15 17 48 55", "11", "04" ] -, [ 1152, "67A3676C-9CE9-4AD5-AA4D-816428CD9DD6", 1152, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-24T00:00:00", "04 05 16 18 53", "28", "04" ] -, [ 1153, "2C1F1E98-3526-4DCA-99F6-3232C975FF7A", 1153, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-28T00:00:00", "04 12 25 32 54", "36", "04" ] -, [ 1154, "281321B5-0D36-4873-BA58-CFF592F88283", 1154, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-05-31T00:00:00", "02 20 26 44 46", "26", "03" ] -, [ 1155, "DE8A7985-1514-45D2-B3F4-71066E9A93EA", 1155, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-04T00:00:00", "10 11 12 20 55", "19", "03" ] -, [ 1156, "88A78BA1-75B1-4B19-B86B-E3E7A4B56DF3", 1156, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-07T00:00:00", "01 10 37 48 55", "21", "04" ] -, [ 1157, "19D77AD1-099E-4B73-867E-AE0E030A1D1B", 1157, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-11T00:00:00", "15 40 45 50 53", "28", "04" ] -, [ 1158, "6B2CFEC0-1059-42BB-8177-9884ED63A7FD", 1158, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-14T00:00:00", "02 05 31 33 34", "20", "04" ] -, [ 1159, "43196123-3624-4EAA-B62B-CDCE787D5891", 1159, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-18T00:00:00", "06 17 34 40 48", "30", "02" ] -, [ 1160, "E696EFBB-4D90-4788-AD22-DB95B76CF993", 1160, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-21T00:00:00", "03 14 17 40 50", "03", "03" ] -, [ 1161, "CF648C6E-2F7F-4E79-9CBE-A77779667BBC", 1161, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-25T00:00:00", "03 05 28 33 51", "16", "02" ] -, [ 1162, "8DE750D6-72BB-4DFE-BD37-E4B79A787AF5", 1162, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-06-28T00:00:00", "08 15 35 46 52", "38", "04" ] -, [ 1163, "F6C35A37-9C0A-497E-84AF-8C541B723501", 1163, 1373464329, "708543", 1373464329, "708543", "{\n}", "2013-07-02T00:00:00", "36 42 51 52 53", "40", "04" ] -, [ 1165, "B57DBFEB-3CE5-421A-B4D0-1C6FE19CD9D1", 1165, 1373960495, "708543", 1373960495, "708543", "{\n}", "2013-07-05T00:00:00", "02 23 41 47 54", "42", "04" ] -, [ 1166, "C39FE0CC-B623-4A5C-93B0-978C7D117C57", 1166, 1373960495, "708543", 1373960495, "708543", "{\n}", "2013-07-09T00:00:00", "03 21 43 45 48", "14", "02" ] -, [ 1168, "B8FC6747-8337-4895-9B3E-EBB6D585DFD1", 1168, 1375427752, "708543", 1375427752, "708543", "{\n}", "2013-07-12T00:00:00", "04 05 25 27 51", "10", "03" ] -, [ 1169, "8FE98420-15E7-46B3-80B8-5C969B920EF1", 1169, 1375427752, "708543", 1375427752, "708543", "{\n}", "2013-07-16T00:00:00", "10 14 21 40 53", "20", "02" ] -, [ 1170, "DD88EF69-CD96-4E83-89E2-6B53BD97EE73", 1170, 1375427752, "708543", 1375427752, "708543", "{\n}", "2013-07-19T00:00:00", "16 20 24 39 42", "46", "03" ] -, [ 1171, "1C7ADA59-1801-4B96-968C-B77854440912", 1171, 1375427752, "708543", 1375427752, "708543", "{\n}", "2013-07-23T00:00:00", "25 32 35 50 51", "46", "03" ] -, [ 1172, "EACD3FC7-2935-458E-AA95-44F2C20CB220", 1172, 1375427752, "708543", 1375427752, "708543", "{\n}", "2013-07-26T00:00:00", "04 22 23 27 38", "42", "04" ] -, [ 1173, "7DF345B2-D9AE-41E3-9C50-4820B5F6BEC7", 1173, 1375427752, "708543", 1375427752, "708543", "{\n}", "2013-07-30T00:00:00", "25 27 36 42 44", "39", "03" ] -, [ 1175, "6373BCDC-8BED-494F-9EF6-27C2632D5059", 1175, 1375712208, "708543", 1375712208, "708543", "{\n}", "2013-08-02T00:00:00", "08 21 23 25 39", "04", "02" ] -, [ 1177, "FDC98341-B359-4B13-9ACC-E56CD21D3006", 1177, 1376034895, "708543", 1376034895, "708543", "{\n}", "2013-08-06T00:00:00", "01 11 16 51 55", "41", "03" ] -, [ 1179, "4671157E-B666-4D37-BD2D-6BC7301F134C", 1179, 1376312414, "708543", 1376312414, "708543", "{\n}", "2013-08-09T00:00:00", "11 20 30 34 38", "12", "03" ] -, [ 1181, "8DDBA2CD-DB9C-4C8D-82FD-6966BE6A59E4", 1181, 1376486912, "708543", 1376486912, "708543", "{\n}", "2013-08-13T00:00:00", "02 31 32 37 41", "40", "04" ] -, [ 1183, "0911616E-2F9E-4473-B45B-16E2636132EE", 1183, 1376921184, "708543", 1376921184, "708543", "{\n}", "2013-08-16T00:00:00", "07 13 26 36 46", "37", "04" ] -, [ 1185, "54AF8A3A-8432-41BA-9DAB-4005B31898E6", 1185, 1377071706, "708543", 1377071706, "708543", "{\n}", "2013-08-20T00:00:00", "13 28 35 38 41", "33", "03" ] -, [ 1187, "75FE181F-FD04-449B-B905-DDE3E9D8B45A", 1187, 1377509016, "708543", 1377509016, "708543", "{\n}", "2013-08-23T00:00:00", "01 09 17 20 53", "14", "04" ] -, [ 1189, "AF8A2810-0255-4390-89B7-01B9CD3714B7", 1189, 1377695374, "708543", 1377695374, "708543", "{\n}", "2013-08-27T00:00:00", "04 07 30 36 38", "38", "04" ] -, [ 1191, "F340F4D7-005E-43A7-835C-5F437C8CE980", 1191, 1377918076, "708543", 1377918076, "708543", "{\n}", "2013-08-30T00:00:00", "06 19 24 43 44", "33", "02" ] -, [ 1193, "57668138-D77E-41A4-A653-A502920BAE5E", 1193, 1378263736, "708543", 1378263736, "708543", "{\n}", "2013-09-03T00:00:00", "04 13 14 28 41", "28", "03" ] -, [ 1197, "67057DAF-BB8E-49A3-A9E5-9C4498E7759F", 1197, 1378566096, "708543", 1378566096, "708543", "{\n}", "2013-09-06T00:00:00", "02 16 17 22 41", "31", "04" ] -, [ 1203, "2F3EFDD8-73E0-4577-A717-F943FE97BBD0", 1203, 1378868474, "708543", 1378868474, "708543", "{\n}", "2013-09-10T00:00:00", "02 12 18 54 56", "01", "03" ] -, [ 1205, "6CD062A7-159D-4079-92DB-AE8C20424C63", 1205, 1379127654, "708543", 1379127654, "708543", "{\n}", "2013-09-13T00:00:00", "09 22 28 48 54", "08", "04" ] -, [ 1207, "CFB168A0-A233-48E8-88B8-6EAB7721AD7B", 1207, 1379473264, "708543", 1379473264, "708543", "{\n}", "2013-09-17T00:00:00", "06 15 27 31 39", "25", "02" ] -, [ 1209, "B7FB8DDD-3DC7-472E-8C06-CDF77B7A1D20", 1209, 1379732475, "708543", 1379732475, "708543", "{\n}", "2013-09-20T00:00:00", "01 15 20 21 47", "34", "02" ] -, [ 1211, "7A049284-67B5-4A91-AF01-9914E831CDA7", 1211, 1380078065, "708543", 1380078065, "708543", "{\n}", "2013-09-24T00:00:00", "04 11 32 39 40", "33", "03" ] -, [ 1213, "7D185A57-BF93-48FC-89C5-13047BB01971", 1213, 1380337279, "708543", 1380337279, "708543", "{\n}", "2013-09-27T00:00:00", "09 23 27 49 51", "38", "02" ] -, [ 1215, "C521C07D-8F39-415E-B899-05489EEECD08", 1215, 1380682866, "708543", 1380682866, "708543", "{\n}", "2013-10-01T00:00:00", "07 10 30 37 53", "01", "03" ] -, [ 1217, "DA977317-43B0-4A2D-A0DE-BBD02E216397", 1217, 1380942064, "708543", 1380942064, "708543", "{\n}", "2013-10-04T00:00:00", "04 16 24 25 44", "05", "03" ] -, [ 1219, "178C758D-E83D-45DA-8B41-5FC1668DF08D", 1219, 1381287665, "708543", 1381287665, "708543", "{\n}", "2013-10-08T00:00:00", "06 15 19 23 40", "05", "03" ] -, [ 1221, "B591BCA6-8B28-4784-8291-E22BAA150DC9", 1221, 1381546854, "708543", 1381546854, "708543", "{\n}", "2013-10-11T00:00:00", "03 27 37 45 48", "46", "04" ] -, [ 1223, "1D2A1993-B0E0-4D79-AAB5-4CDD63EBBE74", 1223, 1381892445, "708543", 1381892445, "708543", "{\n}", "2013-10-15T00:00:00", "04 23 30 43 50", "11", "04" ] -, [ 1225, "05047244-5520-4963-9631-FB059B1D818D", 1225, 1382497255, "708543", 1382497255, "708543", "{\n}", "2013-10-22T00:00:00", "02 03 19 52 71", "14", "05" ] -, [ 1227, "F67117B4-9506-4B0F-AFB3-2068AFC40EBD", 1227, 1382756454, "708543", 1382756454, "708543", "{\n}", "2013-10-25T00:00:00", "06 16 45 54 60", "15", "02" ] -, [ 1229, "A1912FEE-CCAD-4455-BA2A-C7B70FFBEFA0", 1229, 1383102063, "708543", 1383102063, "708543", "{\n}", "2013-10-29T00:00:00", "20 33 50 53 54", "07", "03" ] -, [ 1231, "EF38518A-5261-432F-8C5A-AB1DB4938019", 1231, 1383361276, "708543", 1383361276, "708543", "{\n}", "2013-11-01T00:00:00", "32 35 49 62 67", "01", "05" ] -, [ 1233, "EBE1179F-A084-44F1-9CE4-93DAA1E8B5EA", 1233, 1383706866, "708543", 1383706866, "708543", "{\n}", "2013-11-05T00:00:00", "02 11 42 64 74", "02", "05" ] -, [ 1235, "2621B189-2DA4-4442-81E3-A5C5B3C45E9C", 1235, 1383966043, "708543", 1383966043, "708543", "{\n}", "2013-11-08T00:00:00", "41 42 51 57 65", "07", "02" ] -, [ 1237, "240EC7B3-968C-49A8-8964-6BA21C62B9B0", 1237, 1384335595, "708543", 1384335595, "708543", "{\n}", "2013-11-12T00:00:00", "20 30 32 42 71", "15", "05" ] -, [ 1239, "0DE2D9C9-90A2-4935-AD2C-3E83D65F9146", 1239, 1384571065, "708543", 1384571065, "708543", "{\n}", "2013-11-15T00:00:00", "25 44 49 54 63", "08", "04" ] -, [ 1241, "7935AC34-8C2D-41B9-AD70-D961EA870C52", 1241, 1384916445, "708543", 1384916445, "708543", "{\n}", "2013-11-19T00:00:00", "14 15 29 49 63", "02", "03" ] -, [ 1243, "28E02973-21FA-4667-8338-1EAD00A18DD3", 1243, 1385175654, "708543", 1385175654, "708543", "{\n}", "2013-11-22T00:00:00", "17 23 35 36 44", "08", "03" ] -, [ 1245, "78A29F4C-E6D8-4220-9BAF-A39EC86B01B1", 1245, 1385521297, "708543", 1385521297, "708543", "{\n}", "2013-11-26T00:00:00", "27 44 59 74 75", "03", "05" ] -, [ 1247, "23D353A9-9DA9-48CF-831F-1A1814B3338F", 1247, 1385780464, "708543", 1385780464, "708543", "{\n}", "2013-11-29T00:00:00", "09 41 43 47 57", "05", "04" ] -, [ 1249, "F65A0532-2E1D-4F37-8DC8-4393915B1311", 1249, 1386126046, "708543", 1386126046, "708543", "{\n}", "2013-12-03T00:00:00", "07 12 41 44 59", "03", "03" ] -, [ 1251, "B2E81356-B8CB-401B-BB42-2B76AD3FF125", 1251, 1386385254, "708543", 1386385254, "708543", "{\n}", "2013-12-06T00:00:00", "11 29 44 63 64", "03", "03" ] -, [ 1253, "418BDDC3-6283-4D2B-932E-25AE4BE0E39A", 1253, 1386730867, "708543", 1386730867, "708543", "{\n}", "2013-12-10T00:00:00", "05 12 22 41 65", "13", "02" ] -, [ 1255, "9C4371B8-472D-43C9-909F-A2C4853559ED", 1255, 1386990065, "708543", 1386990065, "708543", "{\n}", "2013-12-13T00:00:00", "19 24 26 27 70", "12", "02" ] -, [ 1257, "026F619A-B4D9-424B-AF29-10337E920A41", 1257, 1387335655, "708543", 1387335655, "708543", "{\n}", "2013-12-17T00:00:00", "08 14 17 20 39", "07", "04" ] -, [ 1259, "68BF57AC-6C45-4467-B7A8-B779BDC0962D", 1259, 1387594857, "708543", 1387594857, "708543", "{\n}", "2013-12-20T00:00:00", "03 04 31 49 57", "06", "02" ] -, [ 1261, "6DB61C6B-B71C-423D-A1CE-1339FCAB9E4A", 1261, 1387940464, "708543", 1387940464, "708543", "{\n}", "2013-12-24T00:00:00", "23 34 53 58 73", "02", "03" ] -, [ 1263, "F015A899-E4DE-4107-93A9-8A2B153B86CF", 1263, 1388286160, "708543", 1388286160, "708543", "{\n}", "2013-12-27T00:00:00", "04 15 35 48 49", "11", "05" ] -, [ 1265, "BEB24506-D802-409A-A5F2-BBFFDA30EF3F", 1265, 1388545256, "708543", 1388545256, "708543", "{\n}", "2013-12-31T00:00:00", "08 12 34 52 58", "08", "03" ] -, [ 1267, "42CF4EA0-F05B-47C9-96C4-0988DBFB9E43", 1267, 1388804475, "708543", 1388804475, "708543", "{\n}", "2014-01-03T00:00:00", "22 24 25 40 70", "05", "05" ] -, [ 1269, "759EF80C-6780-4CC8-A27B-F715230A2FB2", 1269, 1389150065, "708543", 1389150065, "708543", "{\n}", "2014-01-07T00:00:00", "13 34 56 62 64", "06", "05" ] -, [ 1271, "10DAB9D2-46FC-449B-8B66-EBF65D9FD40C", 1271, 1389409265, "708543", 1389409265, "708543", "{\n}", "2014-01-10T00:00:00", "08 28 36 37 57", "08", "03" ] -, [ 1273, "9A60089C-24F6-424F-B5CB-D4CCBE7F5988", 1273, 1389754865, "708543", 1389754865, "708543", "{\n}", "2014-01-14T00:00:00", "04 23 26 62 69", "13", "03" ] -, [ 1275, "FA057396-A897-42CD-A4FC-6CA5ABBA1C4F", 1275, 1390014118, "708543", 1390014118, "708543", "{\n}", "2014-01-17T00:00:00", "01 10 26 31 51", "11", "04" ] -, [ 1277, "D3DFB854-FC39-4840-8827-7D1019D3DA67", 1277, 1390359685, "708543", 1390359685, "708543", "{\n}", "2014-01-21T00:00:00", "08 23 33 45 52", "04", "04" ] -, [ 1279, "B9C11D6D-6EAF-46DA-888F-3631F2F8F57F", 1279, 1390618854, "708543", 1390618854, "708543", "{\n}", "2014-01-24T00:00:00", "22 45 46 47 65", "10", "05" ] -, [ 1281, "6C8D1F24-E450-49BB-BCC0-3E6EAE0FE1EB", 1281, 1390964455, "708543", 1390964455, "708543", "{\n}", "2014-01-28T00:00:00", "07 16 28 53 60", "02", "03" ] -, [ 1283, "382CEE0F-C829-4AFF-BF00-8B39312C4F9C", 1283, 1391223655, "708543", 1391223655, "708543", "{\n}", "2014-01-31T00:00:00", "03 09 13 47 52", "08", "04" ] -, [ 1285, "86776381-2947-4FA4-86FC-F558D7CC86E5", 1285, 1391569286, "708543", 1391569286, "708543", "{\n}", "2014-02-04T00:00:00", "25 44 49 60 73", "09", "03" ] -, [ 1287, "873B54D5-CB06-4D9B-A0D7-A48660F76ADD", 1287, 1391828465, "708543", 1391828465, "708543", "{\n}", "2014-02-07T00:00:00", "11 21 23 35 64", "10", "03" ] -, [ 1289, "FD28870B-0C80-4AF1-B2DF-4C52D4D79E58", 1289, 1392174055, "708543", 1392174055, "708543", "{\n}", "2014-02-11T00:00:00", "43 64 67 71 73", "04", "02" ] -, [ 1291, "5159CE5E-66B0-4DB9-9DD9-5B9B4D0745FD", 1291, 1392433255, "708543", 1392433255, "708543", "{\n}", "2014-02-14T00:00:00", "20 28 35 71 72", "07", "03" ] -, [ 1293, "DEAFD715-D7CD-4708-B535-D9899DD4621D", 1293, 1392778855, "708543", 1392778855, "708543", "{\n}", "2014-02-18T00:00:00", "23 29 31 37 70", "14", "05" ] -, [ 1295, "158825F3-5163-42A3-81DC-70D7B74D3F97", 1295, 1393038044, "708543", 1393038044, "708543", "{\n}", "2014-02-21T00:00:00", "23 29 32 45 46", "15", "05" ] -, [ 1297, "40802F04-A3AC-43C2-9734-1D1DC7C3B974", 1297, 1393383657, "708543", 1393383657, "708543", "{\n}", "2014-02-25T00:00:00", "12 18 25 35 66", "15", "05" ] -, [ 1299, "5ACF39BD-F796-425E-9F66-CB0B27E7C6B1", 1299, 1393642845, "708543", 1393642845, "708543", "{\n}", "2014-02-28T00:00:00", "03 31 50 58 59", "06", "04" ] -, [ 1301, "A28FF876-2890-4BF6-99DD-C392F055CACD", 1301, 1393988455, "708543", 1393988455, "708543", "{\n}", "2014-03-04T00:00:00", "10 29 31 35 45", "10", "02" ] -, [ 1303, "A92F3246-6DA4-48B7-90EA-B2D9A5DBFFB3", 1303, 1394247656, "708543", 1394247656, "708543", "{\n}", "2014-03-07T00:00:00", "11 13 51 57 69", "01", "04" ] -, [ 1305, "FDEA8FEE-8538-40FC-AEF4-DB0F81B3EB1A", 1305, 1394593254, "708543", 1394593254, "708543", "{\n}", "2014-03-11T00:00:00", "09 14 56 57 69", "10", "04" ] -, [ 1307, "BCB912F4-419E-4BE3-983B-200EBAA821E3", 1307, 1394852454, "708543", 1394852454, "708543", "{\n}", "2014-03-14T00:00:00", "07 20 40 54 69", "12", "03" ] -, [ 1309, "1030DC1D-317C-4D87-B1B9-C06B46814C7A", 1309, 1395198065, "708543", 1395198065, "708543", "{\n}", "2014-03-18T00:00:00", "11 19 24 33 51", "07", "03" ] -, [ 1311, "C4CB2C86-7538-4347-9CD1-070BC0C71401", 1311, 1395457255, "708543", 1395457255, "708543", "{\n}", "2014-03-21T00:00:00", "02 23 30 35 53", "10", "05" ] -, [ 1313, "C836D6E0-C01E-4E00-BD1C-A14D1CF63588", 1313, 1395802856, "708543", 1395802856, "708543", "{\n}", "2014-03-25T00:00:00", "19 26 51 57 73", "15", "03" ] -, [ 1315, "5448D834-9CE6-4F77-AE17-19710BA851DC", 1315, 1396105275, "708543", 1396105275, "708543", "{\n}", "2014-03-28T00:00:00", "02 03 09 50 73", "12", "03" ] -, [ 1317, "5F48BA5C-1DC0-49F2-9AEF-8DCAE61E57CC", 1317, 1396407655, "708543", 1396407655, "708543", "{\n}", "2014-04-01T00:00:00", "10 23 68 74 75", "09", "05" ] -, [ 1319, "802D51AA-4C72-4264-8A00-6F1FEB1CA238", 1319, 1396666854, "708543", 1396666854, "708543", "{\n}", "2014-04-04T00:00:00", "01 10 15 41 54", "09", "02" ] -, [ 1321, "01F73B3B-B197-4BCE-8F02-95115A601CB5", 1321, 1397012466, "708543", 1397012466, "708543", "{\n}", "2014-04-08T00:00:00", "35 36 41 60 71", "03", "03" ] -, [ 1323, "6C79075A-EB20-4E77-89DB-C663CA5BF346", 1323, 1397271699, "708543", 1397271699, "708543", "{\n}", "2014-04-11T00:00:00", "03 42 44 47 57", "08", "05" ] -, [ 1325, "E45F48E3-1406-45F0-AB43-FE8D891EBD27", 1325, 1397617245, "708543", 1397617245, "708543", "{\n}", "2014-04-15T00:00:00", "04 39 46 47 70", "13", "03" ] -, [ 1327, "5EB30A7D-8459-4869-AE84-2A2DD1DB5B26", 1327, 1397876455, "708543", 1397876455, "708543", "{\n}", "2014-04-18T00:00:00", "18 25 38 45 63", "09", "02" ] -, [ 1329, "F7877028-A351-43B9-BD5A-D308A12C0115", 1329, 1398222385, "708543", 1398222385, "708543", "{\n}", "2014-04-22T00:00:00", "02 18 19 49 50", "01", "03" ] -, [ 1331, "6BD4A8B0-05E1-4C3B-BBB1-67CB07D2375D", 1331, 1398481352, "708543", 1398481352, "708543", "{\n}", "2014-04-25T00:00:00", "03 11 18 20 66", "09", "02" ] -, [ 1333, "AD580C79-D981-4492-9C81-4D975790086E", 1333, 1398826854, "708543", 1398826854, "708543", "{\n}", "2014-04-29T00:00:00", "07 43 59 61 66", "03", "03" ] -, [ 1335, "E2A087C6-174E-4627-925E-DE97C997ABED", 1335, 1399086054, "708543", 1399086054, "708543", "{\n}", "2014-05-02T00:00:00", "01 18 26 35 40", "13", "05" ] -, [ 1337, "2FDCA593-5848-467B-B3BF-730AED119414", 1337, 1399431741, "708543", 1399431741, "708543", "{\n}", "2014-05-06T00:00:00", "18 20 27 48 51", "05", "03" ] -, [ 1339, "B9E82F60-40BE-4CF4-88A5-FC6BD28807D1", 1339, 1399690844, "708543", 1399690844, "708543", "{\n}", "2014-05-09T00:00:00", "10 28 39 51 59", "14", "02" ] -, [ 1341, "90CF704A-3004-4DA4-BCE4-A5E1A8D717D3", 1341, 1400036529, "708543", 1400036529, "708543", "{\n}", "2014-05-13T00:00:00", "37 46 48 70 74", "01", "02" ] -, [ 1343, "DA1069E2-CB5D-451C-BB3C-7D1C35F561B0", 1343, 1400295664, "708543", 1400295664, "708543", "{\n}", "2014-05-16T00:00:00", "13 14 16 50 56", "11", "05" ] -, [ 1345, "F0CCE86A-0493-4D82-BCA8-CCE4EEBA9CB7", 1345, 1400641329, "708543", 1400641329, "708543", "{\n}", "2014-05-20T00:00:00", "10 40 63 64 69", "07", "02" ] -, [ 1347, "7FAD9C65-4F10-418D-B767-66A240EE8C87", 1347, 1400900518, "708543", 1400900518, "708543", "{\n}", "2014-05-23T00:00:00", "12 14 21 38 70", "15", "04" ] -, [ 1349, "791FB6CC-F7D0-4C9D-BFCE-4F068C0E7F4C", 1349, 1401246129, "708543", 1401246129, "708543", "{\n}", "2014-05-27T00:00:00", "01 06 10 46 58", "13", "02" ] -, [ 1351, "99C102A0-EE2C-4831-A852-FFDCAA15BCDC", 1351, 1401505329, "708543", 1401505329, "708543", "{\n}", "2014-05-30T00:00:00", "10 13 42 43 62", "02", "04" ] -, [ 1353, "CFDC3F17-1919-4AB6-B8F7-3591D7C31688", 1353, 1402024243, "708543", 1402024243, "708543", "{\n}", "2014-06-03T00:00:00", "19 28 62 66 74", "06", "03" ] -, [ 1355, "0FC680AA-3BF1-4785-AD94-A3088BAE1937", 1355, 1402110057, "708543", 1402110057, "708543", "{\n}", "2014-06-06T00:00:00", "12 29 37 49 72", "09", "04" ] -, [ 1357, "28AD4295-DD5E-483A-B44C-4C49E82467C9", 1357, 1402455655, "708543", 1402455655, "708543", "{\n}", "2014-06-10T00:00:00", "02 10 24 26 74", "07", "05" ] -, [ 1359, "2A70E1C3-7D5F-4525-92BD-CFCFAB3D3CBF", 1359, 1402714928, "708543", 1402714928, "708543", "{\n}", "2014-06-13T00:00:00", "07 38 46 49 56", "01", "05" ] -, [ 1361, "94CEE9E6-8F91-4BE7-ABCA-7B2129DC86C4", 1361, 1403060540, "708543", 1403060540, "708543", "{\n}", "2014-06-17T00:00:00", "10 14 24 47 60", "03", "04" ] -, [ 1363, "E71CDAAF-A30A-4D3E-9705-96DF940C1792", 1363, 1403319665, "708543", 1403319665, "708543", "{\n}", "2014-06-20T00:00:00", "01 22 25 29 56", "03", "05" ] -, [ 1365, "78923DD8-7B8A-4095-A4B5-DE0F205C7455", 1365, 1403665339, "708543", 1403665339, "708543", "{\n}", "2014-06-24T00:00:00", "13 17 24 47 65", "10", "04" ] -, [ 1367, "201A2006-4B49-4B3A-A99C-56E811DB26DB", 1367, 1403924475, "708543", 1403924475, "708543", "{\n}", "2014-06-27T00:00:00", "15 29 31 46 64", "10", "03" ] -, [ 1369, "B51C0FFE-A2F8-43A3-BFF9-F13ED5437EAC", 1369, 1404270128, "708543", 1404270128, "708543", "{\n}", "2014-07-01T00:00:00", "09 22 38 47 49", "15", "03" ] -, [ 1371, "B421489C-518C-44E2-B4E1-1739115E80A4", 1371, 1404529254, "708543", 1404529254, "708543", "{\n}", "2014-07-04T00:00:00", "16 33 39 58 69", "02", "05" ] -, [ 1373, "B9CC2A6E-9DDC-4D54-8BB8-C0DE58D4CCAF", 1373, 1404874864, "708543", 1404874864, "708543", "{\n}", "2014-07-08T00:00:00", "14 25 27 48 49", "09", "05" ] -, [ 1375, "9A035F2C-B234-4592-BF32-C88182E53A4C", 1375, 1405134066, "708543", 1405134066, "708543", "{\n}", "2014-07-11T00:00:00", "09 13 30 35 69", "10", "05" ] -, [ 1377, "4BF0FB2B-65A8-40DA-9DBA-697D7861AD00", 1377, 1405479645, "708543", 1405479645, "708543", "{\n}", "2014-07-15T00:00:00", "02 04 17 36 40", "05", "02" ] -, [ 1379, "108F044B-4621-4389-B12F-29CEACF20F30", 1379, 1405738855, "708543", 1405738855, "708543", "{\n}", "2014-07-18T00:00:00", "05 08 59 65 72", "03", "03" ] -, [ 1381, "D8B6033E-27F9-40AD-BE99-7F115C07D3A9", 1381, 1406084465, "708543", 1406084465, "708543", "{\n}", "2014-07-22T00:00:00", "14 18 22 31 47", "15", "03" ] -, [ 1383, "23AEF0BE-4851-4489-8195-0B5D084A5D76", 1383, 1406343656, "708543", 1406343656, "708543", "{\n}", "2014-07-25T00:00:00", "22 29 33 41 68", "12", "05" ] -, [ 1385, "781CE161-A749-41BC-8128-06367FB855CE", 1385, 1406689245, "708543", 1406689245, "708543", "{\n}", "2014-07-29T00:00:00", "02 08 16 43 74", "01", "04" ] -, [ 1387, "EC807140-3D55-49C4-BE48-2CD4847B5B50", 1387, 1406948455, "708543", 1406948455, "708543", "{\n}", "2014-08-01T00:00:00", "13 29 34 37 72", "06", "05" ] -, [ 1389, "437853F0-FAFD-4FFB-ACC5-9581E3335D29", 1389, 1407294066, "708543", 1407294066, "708543", "{\n}", "2014-08-05T00:00:00", "25 28 36 45 53", "06", "05" ] -, [ 1391, "283739E2-D52E-4A05-B041-C3832A4FD03F", 1391, 1407553265, "708543", 1407553265, "708543", "{\n}", "2014-08-08T00:00:00", "09 16 61 70 75", "07", "05" ] -, [ 1393, "F9F5E31F-0AF3-48CC-9243-EA28B055525B", 1393, 1407898866, "708543", 1407898866, "708543", "{\n}", "2014-08-12T00:00:00", "32 53 60 63 68", "06", "04" ] -, [ 1395, "A551D24C-0E35-43C7-AFD7-BCFC9B1A8458", 1395, 1408158065, "708543", 1408158065, "708543", "{\n}", "2014-08-15T00:00:00", "16 19 28 29 68", "09", "02" ] -, [ 1397, "932D43AF-18E1-4C9D-90AC-0EBB473DA2AE", 1397, 1408503656, "708543", 1408503656, "708543", "{\n}", "2014-08-19T00:00:00", "22 39 56 67 71", "15", "04" ] -, [ 1399, "869D1C4F-05FE-4CB7-B2B8-2226D93B2BEE", 1399, 1408762865, "708543", 1408762865, "708543", "{\n}", "2014-08-22T00:00:00", "05 31 34 41 74", "03", "05" ] -, [ 1401, "5DD5D9B1-0338-4C20-AA2D-6FA5E96F59E0", 1401, 1409108455, "708543", 1409108455, "708543", "{\n}", "2014-08-26T00:00:00", "29 31 51 60 64", "01", "05" ] -, [ 1403, "068A5120-3B84-41C2-A798-4D29C04252EF", 1403, 1409367666, "708543", 1409367666, "708543", "{\n}", "2014-08-29T00:00:00", "03 26 45 58 73", "12", "02" ] -, [ 1405, "E0F9E0B8-89FE-4966-A782-DC09D6359977", 1405, 1409713276, "708543", 1409713276, "708543", "{\n}", "2014-09-02T00:00:00", "01 08 54 69 72", "01", "03" ] -, [ 1407, "509607B9-9609-481E-83C7-DB52AA1DFF16", 1407, 1409972456, "708543", 1409972456, "708543", "{\n}", "2014-09-05T00:00:00", "07 12 20 24 59", "07", "02" ] -, [ 1409, "587B5A59-F548-457D-9936-71C0D6749539", 1409, 1410359284, "708543", 1410359284, "708543", "{\n}", "2014-09-09T00:00:00", "25 34 55 70 71", "01", "04" ] -, [ 1411, "109218EC-770D-4D23-8FC1-170CAB79D91B", 1411, 1410857469, "708543", 1410857469, "708543", "{\n}", "2014-09-12T00:00:00", "18 28 33 36 42", "07", "03" ] -, [ 1413, "3B36FBD4-980C-412C-BE40-DC647C1BC1EC", 1413, 1410922895, "708543", 1410922895, "708543", "{\n}", "2014-09-16T00:00:00", "25 45 51 53 73", "02", "02" ] -, [ 1415, "25B65074-AEBB-4AC5-8773-26ECC64BE53B", 1415, 1411225291, "708543", 1411225291, "708543", "{\n}", "2014-09-19T00:00:00", "16 25 27 29 34", "02", "02" ] -, [ 1417, "5743D5F1-F6EC-4C4B-A823-8EA8F70F8472", 1417, 1411527691, "708543", 1411527691, "708543", "{\n}", "2014-09-23T00:00:00", "21 24 25 40 43", "12", "05" ] -, [ 1419, "3E083094-377E-4539-82CE-9DBEF1F04FF7", 1419, 1411786960, "708543", 1411786960, "708543", "{\n}", "2014-09-26T00:00:00", "17 26 35 46 62", "09", "05" ] -, [ 1421, "D765F55E-7EEA-407C-B053-16503F02985E", 1421, 1412175692, "708543", 1412175692, "708543", "{\n}", "2014-09-30T00:00:00", "03 16 52 54 61", "06", "05" ] -, [ 1423, "A2B9AB24-47CD-42F2-96AC-EEA20DD75824", 1423, 1412391627, "708543", 1412391627, "708543", "{\n}", "2014-10-03T00:00:00", "03 20 34 58 67", "06", "03" ] -, [ 1425, "28DCADB9-7202-4BBF-89B9-B3740E7D1DBD", 1425, 1412780470, "708543", 1412780470, "708543", "{\n}", "2014-10-07T00:00:00", "16 29 46 48 55", "02", "03" ] -, [ 1427, "48C60FDD-51FA-4DEA-A448-B4BA3AEEFB6F", 1427, 1412996487, "708543", 1412996487, "708543", "{\n}", "2014-10-10T00:00:00", "02 32 35 50 59", "03", "05" ] -, [ 1429, "141DA9CF-E55A-479C-B882-08951E859ECD", 1429, 1413342225, "708543", 1413342225, "708543", "{\n}", "2014-10-14T00:00:00", "11 37 46 64 68", "15", "03" ] -, [ 1431, "C9ADA820-57B4-48F6-8E63-4D73F2B38278", 1431, 1413601288, "708543", 1413601288, "708543", "{\n}", "2014-10-17T00:00:00", "21 31 43 56 60", "12", "04" ] -, [ 1433, "C8637DC5-F6BC-48BA-86A2-C8C3EA59D9C0", 1433, 1413946886, "708543", 1413946886, "708543", "{\n}", "2014-10-21T00:00:00", "05 35 37 41 66", "11", "05" ] -, [ 1435, "F66ADFB5-6426-4807-9FAD-7D32A44811FA", 1435, 1414206088, "708543", 1414206088, "708543", "{\n}", "2014-10-24T00:00:00", "02 14 21 28 55", "03", "03" ] -, [ 1437, "AA6A6599-1679-4CEB-A74B-B01FDC4479AF", 1437, 1414551686, "708543", 1414551686, "708543", "{\n}", "2014-10-28T00:00:00", "03 50 57 58 60", "11", "05" ] -, [ 1439, "540D4B98-5003-4DE4-9D65-9815DC33BB18", 1439, 1414810889, "708543", 1414810889, "708543", "{\n}", "2014-10-31T00:00:00", "11 29 36 58 67", "15", "02" ] -, [ 1441, "50B7B5D2-D3DF-4E29-8D09-95AF015916CB", 1441, 1415156491, "708543", 1415156491, "708543", "{\n}", "2014-11-04T00:00:00", "09 15 24 39 41", "01", "04" ] -, [ 1443, "5578102D-B814-45E5-88E3-92E8546BA3E7", 1443, 1415415687, "708543", 1415415687, "708543", "{\n}", "2014-11-07T00:00:00", "31 35 41 65 66", "05", "05" ] -, [ 1445, "BCBA72A1-AF88-480F-9F9B-EAE4D5AFC88F", 1445, 1415804595, "708543", 1415804595, "708543", "{\n}", "2014-11-11T00:00:00", "23 25 28 30 75", "11", "05" ] -, [ 1447, "226C67C8-8DFA-48F7-B743-25EF3F2AAF62", 1447, 1416193460, "708543", 1416193460, "708543", "{\n}", "2014-11-14T00:00:00", "03 49 61 62 68", "15", "05" ] -, [ 1449, "BF321267-5089-4771-B912-00DF34976A87", 1449, 1416452617, "708543", 1416452617, "708543", "{\n}", "2014-11-18T00:00:00", "37 39 53 68 75", "06", "02" ] -, [ 1451, "A79F946A-1E3B-4A8E-BB5E-C0C13C99C5B6", 1451, 1416625290, "708543", 1416625290, "708543", "{\n}", "2014-11-21T00:00:00", "03 12 35 37 63", "15", "02" ] -, [ 1453, "4533C6C0-AB19-4FE3-9CF8-15DA4CC80699", 1453, 1416970890, "708543", 1416970890, "708543", "{\n}", "2014-11-25T00:00:00", "10 11 29 47 56", "04", "02" ] -, [ 1455, "C42CB168-F837-46FE-9253-87B0872F4969", 1455, 1417230091, "708543", 1417230091, "708543", "{\n}", "2014-11-28T00:00:00", "08 26 29 36 47", "10", "03" ] -, [ 1457, "98ACB2EF-CFF0-4F85-89DB-49E3049A1B4E", 1457, 1417575689, "708543", 1417575689, "708543", "{\n}", "2014-12-02T00:00:00", "13 18 22 49 62", "11", "05" ] -, [ 1459, "34E52148-0F7E-4E2F-A184-88DD9FEEC593", 1459, 1417834897, "708543", 1417834897, "708543", "{\n}", "2014-12-05T00:00:00", "04 05 11 51 59", "05", "05" ] -, [ 1461, "5369666F-70AF-42D2-A900-6631404FCFF0", 1461, 1418180484, "708543", 1418180484, "708543", "{\n}", "2014-12-09T00:00:00", "27 45 49 51 52", "14", "05" ] -, [ 1463, "76484243-0CFA-4951-8699-9C0115C85933", 1463, 1418439700, "708543", 1418439700, "708543", "{\n}", "2014-12-12T00:00:00", "02 31 46 58 65", "07", "05" ] -, [ 1465, "7E4E9479-256F-44C8-BBDC-BD0E17AA3501", 1465, 1418785292, "708543", 1418785292, "708543", "{\n}", "2014-12-16T00:00:00", "41 58 68 72 73", "01", "05" ] -, [ 1467, "D2360BBD-56C2-4DD3-B532-91E07CAC7062", 1467, 1419044492, "708543", 1419044492, "708543", "{\n}", "2014-12-19T00:00:00", "14 18 58 59 68", "04", "03" ] -, [ 1469, "BD3EE70B-A135-4BC5-98F5-2C7B1F1AD47D", 1469, 1419390093, "708543", 1419390093, "708543", "{\n}", "2014-12-23T00:00:00", "04 10 31 56 66", "07", "03" ] -, [ 1471, "5787AFFB-6C5A-448E-9525-1A896D8F69C1", 1471, 1419649380, "708543", 1419649380, "708543", "{\n}", "2014-12-26T00:00:00", "02 05 10 20 38", "14", "03" ] -, [ 1473, "720F4D3F-A832-4C4B-A137-5051A202656B", 1473, 1419994895, "708543", 1419994895, "708543", "{\n}", "2014-12-30T00:00:00", "03 07 44 63 67", "12", "04" ] -, [ 1475, "1E9AC8BA-D977-4FED-BB99-2BC5277DD02F", 1475, 1420254092, "708543", 1420254092, "708543", "{\n}", "2015-01-02T00:00:00", "13 15 35 62 74", "12", "04" ] -, [ 1477, "03F23C47-039E-484C-BBC7-60312DF63D12", 1477, 1420599691, "708543", 1420599691, "708543", "{\n}", "2015-01-06T00:00:00", "12 20 27 38 75", "04", "03" ] -, [ 1479, "23409C63-89B9-441B-8CA6-8B9481C7B8DC", 1479, 1420858876, "708543", 1420858876, "708543", "{\n}", "2015-01-09T00:00:00", "37 49 50 56 57", "08", "05" ] -, [ 1481, "7D28878E-B1A6-4068-98A0-E6CF1825A96B", 1481, 1421204593, "708543", 1421204593, "708543", "{\n}", "2015-01-13T00:00:00", "12 20 25 50 51", "07", "05" ] -, [ 1483, "29F7CCC7-0AF3-4814-A461-D31C3AE51815", 1483, 1421463668, "708543", 1421463668, "708543", "{\n}", "2015-01-16T00:00:00", "26 32 44 45 58", "11", "03" ] -, [ 1485, "DCBEEBB5-2F0C-48DD-86C5-C61B20888290", 1485, 1421809296, "708543", 1421809296, "708543", "{\n}", "2015-01-20T00:00:00", "31 35 56 59 63", "06", "05" ] -, [ 1487, "7C1F426A-59E8-4DB5-AB4E-219C5325C340", 1487, 1422068490, "708543", 1422068490, "708543", "{\n}", "2015-01-23T00:00:00", "14 15 32 68 72", "08", "02" ] -, [ 1489, "854D8323-507E-44FC-BF64-90A934F13D29", 1489, 1422414088, "708543", 1422414088, "708543", "{\n}", "2015-01-27T00:00:00", "05 26 27 44 57", "07", "03" ] -, [ 1491, "52F40161-7F01-4506-96F2-5A8A98D4DAC9", 1491, 1422673269, "708543", 1422673269, "708543", "{\n}", "2015-01-30T00:00:00", "18 31 39 45 55", "06", "05" ] -, [ 1493, "6A0CE853-9E0D-4ED5-95A1-4E0F9E374FF0", 1493, 1423018893, "708543", 1423018893, "708543", "{\n}", "2015-02-03T00:00:00", "11 22 25 58 69", "13", "05" ] -, [ 1495, "BC84605C-8B57-4569-97F0-5AE244C67001", 1495, 1423278090, "708543", 1423278090, "708543", "{\n}", "2015-02-06T00:00:00", "05 06 17 33 68", "13", "03" ] -, [ 1497, "8E0F669E-B531-4F3B-B2BF-B2771BD94A74", 1497, 1423623690, "708543", 1423623690, "708543", "{\n}", "2015-02-10T00:00:00", "07 42 53 58 71", "15", "02" ] -, [ 1499, "CE96B160-24FB-402B-AA8F-4936E2D39F81", 1499, 1423882891, "708543", 1423882891, "708543", "{\n}", "2015-02-13T00:00:00", "04 20 44 65 74", "14", "03" ] -, [ 1501, "1488A3D6-7D6E-444A-A4F5-1CDF80F801F7", 1501, 1424228493, "708543", 1424228493, "708543", "{\n}", "2015-02-17T00:00:00", "06 45 50 65 66", "01", "05" ] -, [ 1503, "ECE25E72-E4CA-41C2-8700-DD99960A7BD9", 1503, 1424487687, "708543", 1424487687, "708543", "{\n}", "2015-02-20T00:00:00", "02 06 08 52 66", "13", "03" ] -, [ 1505, "12F983C2-99EA-4616-843D-383B1A3D3B05", 1505, 1424833287, "708543", 1424833287, "708543", "{\n}", "2015-02-24T00:00:00", "15 23 26 45 66", "04", "03" ] -, [ 1507, "76073F80-C906-400E-8D4C-BC2E9FE6DB1B", 1507, 1425092468, "708543", 1425092468, "708543", "{\n}", "2015-02-27T00:00:00", "07 49 53 60 64", "04", "02" ] -, [ 1509, "E0984802-013E-4277-85BF-2D5E8CE49EBA", 1509, 1425438096, "708543", 1425438096, "708543", "{\n}", "2015-03-03T00:00:00", "09 11 42 44 50", "03", "04" ] -, [ 1511, "0A3DAF39-2EB3-4650-A72F-89A45ED5FC5D", 1511, 1425697322, "708543", 1425697322, "708543", "{\n}", "2015-03-06T00:00:00", "30 48 55 68 73", "05", "03" ] -, [ 1513, "D6EB5B00-F0DF-4CD6-AEFB-3833C1087B69", 1513, 1426042905, "708543", 1426042905, "708543", "{\n}", "2015-03-10T00:00:00", "10 14 19 30 73", "14", "05" ] -, [ 1515, "FC3C62B4-CD9E-40CB-AD63-A0920FAA15FE", 1515, 1426302087, "708543", 1426302087, "708543", "{\n}", "2015-03-13T00:00:00", "08 22 30 42 45", "03", "05" ] -, [ 1517, "7691B527-2FDA-4AD5-A180-B935E802D9EF", 1517, 1426647689, "708543", 1426647689, "708543", "{\n}", "2015-03-17T00:00:00", "11 27 44 45 58", "03", "05" ] -, [ 1519, "00FAB518-D2CA-4B7A-89A4-F81F738490DC", 1519, 1426906887, "708543", 1426906887, "708543", "{\n}", "2015-03-20T00:00:00", "07 50 54 61 75", "07", "04" ] -, [ 1521, "606D43E5-EA21-465A-AAC0-2C70C208B935", 1521, 1427252484, "708543", 1427252484, "708543", "{\n}", "2015-03-24T00:00:00", "02 23 32 45 55", "12", "02" ] -, [ 1523, "3BF3F918-FD1B-4762-A373-B5D9EB016FE9", 1523, 1427511687, "708543", 1427511687, "708543", "{\n}", "2015-03-27T00:00:00", "17 21 36 58 70", "03", "05" ] -, [ 1525, "D1FD0F94-BB97-40B6-BD07-14B355F38EDF", 1525, 1427857287, "708543", 1427857287, "708543", "{\n}", "2015-03-31T00:00:00", "08 26 41 61 73", "11", "05" ] -, [ 1527, "75C70A26-B013-47F6-AB17-55C5328B66BC", 1527, 1428116490, "708543", 1428116490, "708543", "{\n}", "2015-04-03T00:00:00", "10 36 47 63 74", "02", "05" ] -, [ 1529, "C0FC19C0-5945-4C1F-A836-CB310E1395C3", 1529, 1428462088, "708543", 1428462088, "708543", "{\n}", "2015-04-07T00:00:00", "05 15 22 26 64", "06", "04" ] -, [ 1531, "BA163D58-47C9-4B0B-B432-3115631C3403", 1531, 1428721288, "708543", 1428721288, "708543", "{\n}", "2015-04-10T00:00:00", "06 11 32 46 68", "09", "02" ] -, [ 1533, "DB69CE29-443B-4F14-B9E5-1CAA95882FD7", 1533, 1429066887, "708543", 1429066887, "708543", "{\n}", "2015-04-14T00:00:00", "03 07 25 68 71", "03", "05" ] -, [ 1535, "EF4A13BC-7E42-411E-B38C-89BA969F85CC", 1535, 1429326089, "708543", 1429326089, "708543", "{\n}", "2015-04-17T00:00:00", "15 18 29 41 50", "05", "02" ] -, [ 1537, "02ECDBF5-B6FD-4A1D-BBF3-61C1F04A3CE2", 1537, 1429671687, "708543", 1429671687, "708543", "{\n}", "2015-04-21T00:00:00", "31 33 35 41 69", "11", "05" ] -, [ 1539, "9A0FE695-8393-4F33-A105-6C1BB5E9EDE9", 1539, 1429930889, "708543", 1429930889, "708543", "{\n}", "2015-04-24T00:00:00", "24 25 29 47 67", "04", "04" ] -, [ 1541, "A1D5F972-6D8C-4B76-A289-69E352E806CD", 1541, 1430276508, "708543", 1430276508, "708543", "{\n}", "2015-04-28T00:00:00", "22 27 55 58 63", "11", "05" ] -, [ 1543, "CB258EDF-076B-4199-8BFF-7E799B635D55", 1543, 1430535711, "708543", 1430535711, "708543", "{\n}", "2015-05-01T00:00:00", "17 18 61 66 74", "03", "03" ] -, [ 1545, "EEB76D4C-E7C1-4C74-BFEC-2296C29AEF0F", 1545, 1430881307, "708543", 1430881307, "708543", "{\n}", "2015-05-05T00:00:00", "11 21 42 62 71", "07", "05" ] -, [ 1547, "4E7287E0-B454-4D0D-B2CD-F7973ED0DD0B", 1547, 1431140494, "708543", 1431140494, "708543", "{\n}", "2015-05-08T00:00:00", "09 21 25 66 72", "07", "03" ] -, [ 1549, "F11F018E-0E2A-4FD7-88E1-C0978A87AAFD", 1549, 1431486108, "708543", 1431486108, "708543", "{\n}", "2015-05-12T00:00:00", "14 30 33 36 44", "02", "05" ] -, [ 1551, "9DC8A2A8-6EEB-4C6F-85D6-2E121BA31891", 1551, 1431745290, "708543", 1431745290, "708543", "{\n}", "2015-05-15T00:00:00", "11 17 21 36 74", "15", "05" ] -, [ 1553, "16A8B73D-D63A-471A-9575-C82B0F79348E", 1553, 1432090927, "708543", 1432090927, "708543", "{\n}", "2015-05-19T00:00:00", "10 12 21 29 65", "10", "05" ] -, [ 1555, "79E08881-8F9F-4152-8A46-6F4740358B15", 1555, 1432350090, "708543", 1432350090, "708543", "{\n}", "2015-05-22T00:00:00", "03 14 15 25 48", "08", "05" ] -, [ 1557, "16AA6E62-2764-4352-8079-E10FD79C6C0A", 1557, 1432695687, "708543", 1432695687, "708543", "{\n}", "2015-05-26T00:00:00", "01 39 52 69 72", "12", "04" ] -, [ 1559, "8291B987-7740-4A35-A8AA-444F1CC1E21B", 1559, 1432954911, "708543", 1432954911, "708543", "{\n}", "2015-05-29T00:00:00", "20 27 38 49 66", "02", "04" ] -, [ 1561, "BB565492-D644-4BD5-8127-C9CC2005DC73", 1561, 1433300489, "708543", 1433300489, "708543", "{\n}", "2015-06-02T00:00:00", "02 09 11 22 23", "12", "04" ] -, [ 1563, "6F42DCC6-0C62-40C6-B530-BE484E52FB3E", 1563, 1433559758, "708543", 1433559758, "708543", "{\n}", "2015-06-05T00:00:00", "07 22 27 41 49", "10", "04" ] -, [ 1565, "A3EE789D-9396-4CDA-8B89-899EFDB844C6", 1565, 1433905222, "708543", 1433905222, "708543", "{\n}", "2015-06-09T00:00:00", "06 16 17 25 36", "07", "05" ] -, [ 1567, "856CE10D-D4B2-4C16-8A18-31DF4766B6A9", 1567, 1434164494, "708543", 1434164494, "708543", "{\n}", "2015-06-12T00:00:00", "01 40 42 56 62", "02", "05" ] -, [ 1569, "422205F9-728E-4DFB-86C2-0CF2A12A9FD4", 1569, 1434510087, "708543", 1434510087, "708543", "{\n}", "2015-06-16T00:00:00", "08 19 26 56 67", "14", "02" ] -, [ 1571, "46AF2341-F648-425D-8343-117626DDD550", 1571, 1434769320, "708543", 1434769320, "708543", "{\n}", "2015-06-19T00:00:00", "04 35 36 52 68", "08", "03" ] -, [ 1573, "4C88ED32-DEA2-4D0D-B0BC-735ECA9A3C83", 1573, 1435114948, "708543", 1435114948, "708543", "{\n}", "2015-06-23T00:00:00", "06 13 38 56 70", "02", "05" ] -, [ 1575, "0FAD5736-617A-4582-A81A-3B61984F2B61", 1575, 1435374132, "708543", 1435374132, "708543", "{\n}", "2015-06-26T00:00:00", "12 23 33 47 50", "03", "05" ] -, [ 1577, "5E53C0D5-0652-4D7F-9F12-E3167CA63C1F", 1577, 1435719666, "708543", 1435719666, "708543", "{\n}", "2015-06-30T00:00:00", "11 17 34 43 50", "15", "04" ] -, [ 1579, "B9EBA90D-732D-4A17-9675-4BE770E869AF", 1579, 1435980252, "708543", 1435980252, "708543", "{\n}", "2015-07-03T00:00:00", "33 50 64 71 72", "09", "04" ] -, [ 1581, "F786B892-2A7D-4C1E-8C50-9044D07A78DB", 1581, 1436324525, "708543", 1436324525, "708543", "{\n}", "2015-07-07T00:00:00", "06 15 16 28 49", "14", "03" ] -, [ 1583, "173F799E-8486-47D5-A2E8-55D828DEDFC1", 1583, 1436583671, "708543", 1436583671, "708543", null, "2015-07-10T00:00:00", "24 27 45 51 54", "08", "03" ] -, [ 1584, "2885C9A3-6363-42C9-BCE8-AD2C652986CB", 1584, 1436929328, "708543", 1436929328, "708543", null, "2015-07-14T00:00:00", "19 24 30 35 72", "05", "03" ] -, [ 1585, "E5F4CC7B-147B-42BA-B75D-2BAE8021C6ED", 1585, 1437188486, "708543", 1437188486, "708543", null, "2015-07-17T00:00:00", "06 17 30 31 41", "15", "03" ] -, [ 1586, "E4A64E1F-7F45-4D23-A5BE-FB8B31FB1BC0", 1586, 1437534086, "708543", 1437534086, "708543", null, "2015-07-21T00:00:00", "20 30 62 65 74", "01", "05" ] -, [ 1587, "B2F7936C-6001-4234-B9B9-681131049B3D", 1587, 1437793264, "708543", 1437793264, "708543", null, "2015-07-24T00:00:00", "10 12 26 60 62", "13", "05" ] -, [ 1588, "CB5C79BF-C111-42EA-B656-345263A124FA", 1588, 1438138886, "708543", 1438138886, "708543", null, "2015-07-28T00:00:00", "08 35 61 68 75", "15", "05" ] -, [ 1589, "DBF152CB-ECCE-40CC-834A-E35E6D3198EA", 1589, 1438398127, "708543", 1438398127, "708543", null, "2015-07-31T00:00:00", "28 32 33 40 46", "10", "04" ] -, [ 1590, "1AAE9761-BA0D-4883-9981-BEB91B225B68", 1590, 1438743707, "708543", 1438743707, "708543", null, "2015-08-04T00:00:00", "02 19 44 51 57", "14", "02" ] -, [ 1591, "C72F41A6-3F86-4EA0-A05B-ECC42BF5068A", 1591, 1439002932, "708543", 1439002932, "708543", null, "2015-08-07T00:00:00", "01 38 53 63 66", "10", "03" ] -, [ 1592, "6FEA722E-6A92-4AAA-A853-9186C57C50F3", 1592, 1439348526, "708543", 1439348526, "708543", null, "2015-08-11T00:00:00", "03 08 29 57 68", "08", "04" ] -, [ 1593, "CFA8B480-20C9-4999-9546-F1A8CB997E35", 1593, 1439607747, "708543", 1439607747, "708543", null, "2015-08-14T00:00:00", "12 15 20 52 71", "03", "04" ] -, [ 1594, "4346D64A-3084-4333-9808-7BEA3322BB67", 1594, 1439953329, "708543", 1439953329, "708543", null, "2015-08-18T00:00:00", "02 07 33 39 53", "09", "03" ] -, [ 1595, "D3193CB6-30E4-4F8C-A26C-B7F0B11FC519", 1595, 1440212561, "708543", 1440212561, "708543", null, "2015-08-21T00:00:00", "13 15 21 41 72", "01", "05" ] -, [ 1596, "4275034A-4B46-439E-B76B-7EAE60AB3B57", 1596, 1440558107, "708543", 1440558107, "708543", null, "2015-08-25T00:00:00", "05 44 54 59 63", "01", "05" ] -, [ 1597, "19875C2F-4710-4402-997B-06277EB1DD3B", 1597, 1440817288, "708543", 1440817288, "708543", null, "2015-08-28T00:00:00", "13 35 40 60 68", "09", "04" ] -, [ 1598, "9E1E52A1-49E3-44F8-8A8B-E0AE76939ED0", 1598, 1441162926, "708543", 1441162926, "708543", null, "2015-09-01T00:00:00", "02 05 35 40 54", "13", "05" ] -, [ 1599, "ABBF4221-3651-4E33-9826-778CDB6160D5", 1599, 1441422137, "708543", 1441422137, "708543", null, "2015-09-04T00:00:00", "17 21 39 52 57", "05", "05" ] -, [ 1600, "F966B71B-2043-42CD-95C3-E1D052D0F5DC", 1600, 1441767706, "708543", 1441767706, "708543", null, "2015-09-08T00:00:00", "19 20 36 41 46", "07", "03" ] -, [ 1601, "6C0212B9-27FE-4779-8E1E-4E978B393488", 1601, 1442026906, "708543", 1442026906, "708543", null, "2015-09-11T00:00:00", "05 11 31 50 67", "14", "02" ] -, [ 1602, "951A886B-09C7-40FE-8D21-65BFE67E0E20", 1602, 1442372505, "708543", 1442372505, "708543", null, "2015-09-15T00:00:00", "07 20 35 49 56", "09", "04" ] -, [ 1603, "8B5F5037-DEB5-44AA-B5DE-D76E18D731DC", 1603, 1442631785, "708543", 1442631785, "708543", null, "2015-09-18T00:00:00", "17 34 35 51 65", "07", "03" ] -, [ 1604, "F7432096-1416-4186-AD4E-A36B61D0FDF3", 1604, 1442977285, "708543", 1442977285, "708543", null, "2015-09-22T00:00:00", "28 30 38 45 51", "08", "05" ] -, [ 1605, "33D70780-01EA-441A-9A4C-990859DC0629", 1605, 1443236506, "708543", 1443236506, "708543", null, "2015-09-25T00:00:00", "03 08 38 51 64", "04", "05" ] -, [ 1606, "C0905F04-1938-4970-AB55-09034B99C92B", 1606, 1443582127, "708543", 1443582127, "708543", null, "2015-09-29T00:00:00", "08 21 30 61 62", "09", "03" ] -, [ 1607, "181D106E-63BE-4A21-8A82-973C9467C233", 1607, 1443841309, "708543", 1443841309, "708543", null, "2015-10-02T00:00:00", "04 14 29 31 47", "09", "02" ] -, [ 1608, "E40045A0-5E29-4C8E-8CB2-6BD75D932427", 1608, 1444186906, "708543", 1444186906, "708543", null, "2015-10-06T00:00:00", "17 58 63 64 66", "13", "03" ] -, [ 1609, "861F130E-42CC-4654-8650-1D386AC20D62", 1609, 1444446107, "708543", 1444446107, "708543", null, "2015-10-09T00:00:00", "08 09 21 63 75", "14", "04" ] -, [ 1610, "ECD5BFB6-8892-41CC-B760-EDD8AAB9B93B", 1610, 1444791707, "708543", 1444791707, "708543", null, "2015-10-13T00:00:00", "07 09 24 38 52", "01", "05" ] -, [ 1611, "8E5AF013-320C-4B04-81E7-18A40F090924", 1611, 1445050907, "708543", 1445050907, "708543", null, "2015-10-16T00:00:00", "02 38 48 61 68", "04", "03" ] -, [ 1612, "3F86F0A3-0657-4C23-964C-B2597E46EED3", 1612, 1445396526, "708543", 1445396526, "708543", null, "2015-10-20T00:00:00", "06 25 35 38 52", "04", "04" ] -, [ 1613, "39DEFA41-D1AF-4254-ACC8-2CF8FB9196EB", 1613, 1445655706, "708543", 1445655706, "708543", null, "2015-10-23T00:00:00", "25 32 37 45 70", "01", "05" ] -, [ 1614, "6CF15757-6420-41C6-977F-DBD65C34F437", 1614, 1446001285, "708543", 1446001285, "708543", null, "2015-10-27T00:00:00", "09 26 27 29 74", "04", "03" ] -, [ 1615, "BF4C8D3B-3CD2-443A-B733-49700D3AF505", 1615, 1446260527, "708543", 1446260527, "708543", null, "2015-10-30T00:00:00", "17 41 51 53 56", "15", "05" ] -, [ 1616, "24AC2580-F864-456E-95BE-C6451E52DAA8", 1616, 1446606108, "708543", 1446606108, "708543", null, "2015-11-03T00:00:00", "16 29 44 69 74", "12", "05" ] -, [ 1617, "AF9AC066-EA3E-4A56-A549-69462973239E", 1617, 1446865313, "708543", 1446865313, "708543", null, "2015-11-06T00:00:00", "10 31 35 50 72", "08", "03" ] -, [ 1618, "5B523B94-4392-493C-8B77-37AAAD523BD0", 1618, 1447210947, "708543", 1447210947, "708543", null, "2015-11-10T00:00:00", "08 17 20 45 71", "04", "04" ] -, [ 1619, "33E35597-2F1E-4EA8-B8AE-B408573042C6", 1619, 1447470107, "708543", 1447470107, "708543", null, "2015-11-13T00:00:00", "17 18 31 35 59", "09", "05" ] -, [ 1620, "012E2E76-2B89-43BE-807D-24F86894DB3F", 1620, 1447815708, "708543", 1447815708, "708543", null, "2015-11-17T00:00:00", "12 14 18 24 61", "10", "03" ] -, [ 1621, "5C3E6FAB-3A63-45F4-BABF-0F2A7B05721A", 1621, 1448074906, "708543", 1448074906, "708543", null, "2015-11-20T00:00:00", "09 12 29 37 67", "15", "02" ] -, [ 1622, "50AB6256-911B-4734-B098-A1C7E029FC50", 1622, 1448420505, "708543", 1448420505, "708543", null, "2015-11-24T00:00:00", "02 19 30 38 70", "08", "04" ] -, [ 1623, "733C5B78-D944-42F9-9D39-206B69395C1C", 1623, 1448679706, "708543", 1448679706, "708543", null, "2015-11-27T00:00:00", "16 20 39 56 59", "12", "03" ] -, [ 1624, "3466B9EB-25AE-493B-9F81-A70C296687D6", 1624, 1449025305, "708543", 1449025305, "708543", null, "2015-12-01T00:00:00", "05 07 25 50 59", "12", "02" ] -, [ 1625, "BFDA9763-E55B-4E68-AC4A-64FC5BEA7290", 1625, 1449284488, "708543", 1449284488, "708543", null, "2015-12-04T00:00:00", "26 42 47 61 73", "06", "05" ] -, [ 1626, "FB3F13D9-F108-4F20-9550-5597912CFBE5", 1626, 1449630108, "708543", 1449630108, "708543", null, "2015-12-08T00:00:00", "07 17 37 49 73", "15", "03" ] -, [ 1627, "9E08A0BF-C5E0-48BE-B88D-D740895745C3", 1627, 1449889348, "708543", 1449889348, "708543", null, "2015-12-11T00:00:00", "14 20 43 54 69", "05", "04" ] -, [ 1628, "B94BCB4B-037B-4CD2-AF74-C91D52F1180F", 1628, 1450234926, "708543", 1450234926, "708543", null, "2015-12-15T00:00:00", "18 25 47 51 61", "05", "05" ] -, [ 1629, "B5B2B02B-14B7-4157-9A7B-EC5F8BFB91EE", 1629, 1450494130, "708543", 1450494130, "708543", null, "2015-12-18T00:00:00", "06 23 24 28 62", "07", "05" ] -, [ 1630, "94CC0B9B-F3D5-4AF1-91EC-2E80DA049A3E", 1630, 1450839805, "708543", 1450839805, "708543", null, "2015-12-22T00:00:00", "11 21 40 50 70", "15", "03" ] -, [ 1631, "7D95C3DB-8346-4A0A-99F9-8388D3455F05", 1631, 1451098926, "708543", 1451098926, "708543", null, "2015-12-25T00:00:00", "15 25 29 44 51", "04", "04" ] -, [ 1632, "2C7475AA-BF40-446B-AF68-4D0F75B8C6F8", 1632, 1451444486, "708543", 1451444486, "708543", null, "2015-12-29T00:00:00", "20 25 55 62 74", "07", "03" ] -, [ 1633, "C76B3278-31E5-4212-9F91-3A9B8FB8FEE7", 1633, 1451703685, "708543", 1451703685, "708543", null, "2016-01-01T00:00:00", "07 18 37 38 39", "09", "05" ] -, [ 1634, "1701538C-706D-4F58-BEAD-E85A125BAA93", 1634, 1452049285, "708543", 1452049285, "708543", null, "2016-01-05T00:00:00", "01 04 36 48 57", "13", "05" ] -, [ 1635, "2DECE042-B1F3-4BAF-92E2-ACC534B62171", 1635, 1452308424, "708543", 1452308424, "708543", null, "2016-01-08T00:00:00", "11 39 51 57 75", "02", "05" ] -, [ 1636, "59AA8588-E389-44D4-898A-B88D215B3180", 1636, 1452654246, "708543", 1452654246, "708543", null, "2016-01-12T00:00:00", "15 27 29 31 48", "15", "04" ] -, [ 1637, "EB18630E-DFCB-4DA9-B3C6-5D017B4CB539", 1637, 1452913329, "708543", 1452913329, "708543", null, "2016-01-15T00:00:00", "29 41 53 54 70", "12", "02" ] -, [ 1638, "6B3ECBDD-C850-4F5E-876A-3DFD62D39CC0", 1638, 1453258928, "708543", 1453258928, "708543", null, "2016-01-19T00:00:00", "02 17 31 39 47", "09", "02" ] -, [ 1639, "6CE292DA-B019-4C72-869B-33F7378737C2", 1639, 1453518148, "708543", 1453518148, "708543", null, "2016-01-22T00:00:00", "21 25 40 46 56", "03", "05" ] -, [ 1640, "941AFB5B-975C-451B-A1D4-9BB39C5CDE3A", 1640, 1453863685, "708543", 1453863685, "708543", null, "2016-01-26T00:00:00", "14 27 39 50 69", "02", "02" ] -, [ 1641, "DC2CFE1D-AF9A-4D71-A64B-7DC7F04F5F97", 1641, 1454122956, "708543", 1454122956, "708543", null, "2016-01-29T00:00:00", "20 28 49 51 52", "06", "02" ] -, [ 1642, "AC5D2A7E-4F80-4BDB-90A6-1D751A93ED93", 1642, 1454468486, "708543", 1454468486, "708543", null, "2016-02-02T00:00:00", "07 13 25 51 70", "09", "04" ] -, [ 1643, "1D000580-A2EF-43DF-9A38-DE8E08AACF5A", 1643, 1454727710, "708543", 1454727710, "708543", null, "2016-02-05T00:00:00", "04 06 23 55 75", "02", "03" ] -, [ 1644, "297A9E01-53D1-492F-8797-B9ED4B59084D", 1644, 1455073306, "708543", 1455073306, "708543", null, "2016-02-09T00:00:00", "03 42 46 56 71", "13", "04" ] -, [ 1645, "3F84D541-E559-42C0-A4CA-E18F9089AA1A", 1645, 1455332486, "708543", 1455332486, "708543", null, "2016-02-12T00:00:00", "01 07 44 68 73", "01", "03" ] -, [ 1646, "58DDCF16-F230-4B9A-BDA6-9FE0DB79CB4F", 1646, 1455678105, "708543", 1455678105, "708543", null, "2016-02-16T00:00:00", "09 31 33 46 64", "04", "03" ] -, [ 1647, "1538C7E2-86A5-4AD3-B5E1-5C3302FE635C", 1647, 1455937343, "708543", 1455937343, "708543", null, "2016-02-19T00:00:00", "02 27 41 50 75", "04", "04" ] -, [ 1648, "BFC5316B-4251-4DB1-8244-C6E36166125B", 1648, 1456282885, "708543", 1456282885, "708543", null, "2016-02-23T00:00:00", "16 32 39 53 57", "10", "05" ] -, [ 1649, "F93DA3B6-AAB1-4515-AAD0-7A6B4C31F7E6", 1649, 1456542125, "708543", 1456542125, "708543", null, "2016-02-26T00:00:00", "03 15 19 62 74", "14", "04" ] -, [ 1650, "DA81E261-D572-4CB3-8049-F9F396136F54", 1650, 1456887623, "708543", 1456887623, "708543", null, "2016-03-01T00:00:00", "01 29 33 34 55", "06", "05" ] -, [ 1651, "9CE887E3-9BF2-47C2-AED3-D6432D439626", 1651, 1457146912, "708543", 1457146912, "708543", null, "2016-03-04T00:00:00", "21 26 33 48 73", "14", "04" ] -, [ 1652, "F4CB0CEF-4734-48B2-BFD3-87C959B4BF60", 1652, 1457492506, "708543", 1457492506, "708543", null, "2016-03-08T00:00:00", "27 37 54 66 69", "05", "05" ] -, [ 1653, "E7EFFA53-90C7-4A52-BC33-A41CC6F35743", 1653, 1457751711, "708543", 1457751711, "708543", null, "2016-03-11T00:00:00", "14 18 48 54 71", "13", "04" ] -, [ 1654, "3B31A0E3-38D3-49F2-86FB-300A875F4FE0", 1654, 1458097306, "708543", 1458097306, "708543", null, "2016-03-15T00:00:00", "18 26 30 44 68", "07", "04" ] -, [ 1655, "7346468C-570F-4959-9C47-D3968389C666", 1655, 1458356507, "708543", 1458356507, "708543", null, "2016-03-18T00:00:00", "05 08 57 59 73", "13", "05" ] -, [ 1656, "F32E462E-EC01-48B3-99F6-AD6656CC8BAB", 1656, 1458702105, "708543", 1458702105, "708543", null, "2016-03-22T00:00:00", "06 19 34 38 70", "05", "05" ] -, [ 1657, "1E34E7D5-CDED-4CC3-907A-DB890B845B3C", 1657, 1458961346, "708543", 1458961346, "708543", null, "2016-03-25T00:00:00", "04 11 12 35 46", "12", "02" ] -, [ 1658, "2472EA19-C13B-4A4C-BB18-2770ED68FEB4", 1658, 1459306927, "708543", 1459306927, "708543", null, "2016-03-29T00:00:00", "33 38 40 46 49", "15", "05" ] -, [ 1659, "5EAA3253-2899-4961-A8AA-3AF3577FFB34", 1659, 1459566137, "708543", 1459566137, "708543", null, "2016-04-01T00:00:00", "25 28 33 41 69", "06", "02" ] -, [ 1660, "730C99CF-8304-4E8E-9DC8-37EDCB468913", 1660, 1459911705, "708543", 1459911705, "708543", null, "2016-04-05T00:00:00", "13 45 52 53 57", "10", "05" ] -, [ 1661, "635A8961-E360-46DC-99F2-82C35E8ADE1B", 1661, 1460170909, "708543", 1460170909, "708543", null, "2016-04-08T00:00:00", "31 38 52 65 71", "15", "03" ] -, [ 1662, "1684546A-9BF3-40A4-BB78-58D7E7C6EA78", 1662, 1460516506, "708543", 1460516506, "708543", null, "2016-04-12T00:00:00", "07 11 59 62 63", "03", "05" ] -, [ 1663, "5FAD000A-6227-42A4-B37B-5C3413481CA5", 1663, 1460775769, "708543", 1460775769, "708543", null, "2016-04-15T00:00:00", "09 10 34 37 73", "09", "05" ] -, [ 1664, "59F5A789-DE19-4648-B46D-196833A64927", 1664, 1461121307, "708543", 1461121307, "708543", null, "2016-04-19T00:00:00", "09 28 40 57 65", "02", "05" ] -, [ 1665, "1EFFFA59-5E1A-4F67-B885-4403A2EEA36B", 1665, 1461380489, "708543", 1461380489, "708543", null, "2016-04-22T00:00:00", "02 19 21 42 60", "13", "05" ] -, [ 1666, "3D1A81F6-FC6D-4A43-ABBD-124B3C6A15CB", 1666, 1461726127, "708543", 1461726127, "708543", null, "2016-04-26T00:00:00", "14 16 17 28 48", "02", "02" ] -, [ 1667, "9F063336-F99B-4B5A-B425-CAC2772F5DC5", 1667, 1461985308, "708543", 1461985308, "708543", null, "2016-04-29T00:00:00", "05 06 37 55 74", "10", "05" ] -, [ 1668, "9CA74EE6-461C-4AE1-96C1-7C9041086E65", 1668, 1462330906, "708543", 1462330906, "708543", null, "2016-05-03T00:00:00", "28 29 33 36 45", "15", "05" ] -, [ 1669, "28B4E2DD-05CD-435F-8144-373554ADCC07", 1669, 1462590107, "708543", 1462590107, "708543", null, "2016-05-06T00:00:00", "14 26 27 32 36", "07", "04" ] -, [ 1670, "E6136A00-E6CD-4564-9BDB-5D8658C1266F", 1670, 1462935706, "708543", 1462935706, "708543", null, "2016-05-10T00:00:00", "12 22 46 56 74", "04", "03" ] -, [ 1671, "144177A9-0D5C-41E0-87AA-B476C6076F11", 1671, 1463194908, "708543", 1463194908, "708543", null, "2016-05-13T00:00:00", "20 21 38 54 66", "07", "04" ] -, [ 1672, "77A58B0B-B6FB-43A3-99D5-C1A8962A3683", 1672, 1463540486, "708543", 1463540486, "708543", null, "2016-05-17T00:00:00", "17 24 27 48 75", "06", "03" ] -, [ 1673, "C90DB1FC-B9F4-44F1-BAE0-56541E75CB7C", 1673, 1463799716, "708543", 1463799716, "708543", null, "2016-05-20T00:00:00", "19 24 26 40 68", "08", "02" ] -, [ 1674, "31AA7AEB-7AFF-4E7C-AB41-1E61FF8D940E", 1674, 1464145306, "708543", 1464145306, "708543", null, "2016-05-24T00:00:00", "11 50 51 70 75", "15", "04" ] -, [ 1675, "4F63AC2C-8696-43A3-95D2-EFDBC8F93FA8", 1675, 1464404510, "708543", 1464404510, "708543", null, "2016-05-27T00:00:00", "18 41 50 68 70", "09", "03" ] -, [ 1676, "CFB15510-5ACA-4A3C-8120-F0B60A465B2D", 1676, 1464750107, "708543", 1464750107, "708543", null, "2016-05-31T00:00:00", "09 31 34 41 49", "08", "05" ] -, [ 1677, "C0EA471B-8C90-446F-948D-E5D2F022020A", 1677, 1465009311, "708543", 1465009311, "708543", null, "2016-06-03T00:00:00", "32 54 65 66 71", "10", "03" ] -, [ 1678, "35E2149B-4F4B-4FA7-8E33-1AFE8AABF057", 1678, 1465375783, "708543", 1465375783, "708543", null, "2016-06-07T00:00:00", "25 48 51 65 72", "04", "04" ] -, [ 1679, "6E874453-0778-4D7F-9713-0A4A3074D7E3", 1679, 1465614107, "708543", 1465614107, "708543", null, "2016-06-10T00:00:00", "34 61 66 67 68", "07", "05" ] -, [ 1680, "B21F8F34-9F29-463F-AC25-79A1FB778512", 1680, 1465959706, "708543", 1465959706, "708543", null, "2016-06-14T00:00:00", "36 37 38 52 62", "06", "05" ] -, [ 1681, "FF41B26A-4D95-46FD-90D6-BE358A9D7FEB", 1681, 1466218908, "708543", 1466218908, "708543", null, "2016-06-17T00:00:00", "20 23 30 44 59", "09", "05" ] -, [ 1682, "093F0CEB-4416-493E-BAC0-DADCBE527A9C", 1682, 1466564486, "708543", 1466564486, "708543", null, "2016-06-21T00:00:00", "06 13 21 49 50", "10", "05" ] -, [ 1683, "0DAE0DED-2901-4FFF-B384-08A5D8C81B7A", 1683, 1466823708, "708543", 1466823708, "708543", null, "2016-06-24T00:00:00", "11 14 54 57 63", "11", "05" ] -, [ 1684, "6C7CBB06-FAA1-480F-BF36-333F4BBD0CF2", 1684, 1467169306, "708543", 1467169306, "708543", null, "2016-06-28T00:00:00", "15 17 20 35 55", "07", "02" ] -, [ 1685, "C9B81A72-3904-4620-8449-41A9290F4FBE", 1685, 1467428490, "708543", 1467428490, "708543", null, "2016-07-01T00:00:00", "20 41 42 45 49", "14", "02" ] -, [ 1686, "D1A987BF-16F8-4ED2-96D9-B3E17B64D960", 1686, 1467774149, "708543", 1467774149, "708543", null, "2016-07-05T00:00:00", "29 46 53 64 73", "10", "05" ] -, [ 1687, "5F960802-C664-4042-9335-123EC20BE436", 1687, 1468033308, "708543", 1468033308, "708543", null, "2016-07-08T00:00:00", "08 19 20 55 73", "05", "02" ] -, [ 1688, "9D920794-C05B-485C-924A-9982FFD79A80", 1688, 1468378905, "708543", 1468378905, "708543", null, "2016-07-12T00:00:00", "06 08 22 46 68", "04", "04" ] -, [ 1689, "2144EBBB-EDA3-4E17-8BCB-A0682E6E2711", 1689, 1468638086, "708543", 1468638086, "708543", null, "2016-07-15T00:00:00", "16 51 52 56 58", "04", "02" ] -, [ 1690, "72A8E501-6FCD-44BE-9F14-D2428CFD296A", 1690, 1468983705, "708543", 1468983705, "708543", null, "2016-07-19T00:00:00", "03 34 54 65 66", "04", "05" ] -, [ 1691, "6C611C43-B591-4FB2-B377-364CC0E42915", 1691, 1469242907, "708543", 1469242907, "708543", null, "2016-07-22T00:00:00", "08 24 25 26 30", "07", "04" ] -, [ 1692, "984FA443-EEBD-4558-B81C-5C3067CB6BED", 1692, 1469588505, "708543", 1469588505, "708543", null, "2016-07-26T00:00:00", "01 04 31 36 54", "09", "03" ] -, [ 1693, "3DF563C7-1EC0-490A-AD2B-F65CC5700B89", 1693, 1469847706, "708543", 1469847706, "708543", null, "2016-07-29T00:00:00", "11 16 19 31 48", "04", "05" ] -, [ 1694, "4D0679B3-5476-40DD-89FE-93378295A073", 1694, 1470193285, "708543", 1470193285, "708543", null, "2016-08-02T00:00:00", "03 12 36 54 70", "12", "05" ] -, [ 1695, "5CB223B1-DD54-4EE5-BA4B-07A736D4DB1E", 1695, 1470452508, "708543", 1470452508, "708543", null, "2016-08-05T00:00:00", "05 18 28 54 74", "06", "04" ] -, [ 1696, "295B3CAA-7AD7-48EA-99C7-B607F0BD93C0", 1696, 1470798106, "708543", 1470798106, "708543", null, "2016-08-09T00:00:00", "12 19 20 44 66", "01", "05" ] -, [ 1697, "2D055176-5D79-486C-8319-DE5093C0C312", 1697, 1471057309, "708543", 1471057309, "708543", null, "2016-08-12T00:00:00", "04 41 44 56 69", "10", "04" ] -, [ 1698, "E3A9ADEA-B623-49E8-ABBB-51BB2E3D316E", 1698, 1471402905, "708543", 1471402905, "708543", null, "2016-08-16T00:00:00", "02 43 52 62 63", "06", "05" ] -, [ 1699, "B905E132-9D91-4425-A6B8-6912D3A5690B", 1699, 1471687310, "708543", 1471687310, "708543", null, "2016-08-19T00:00:00", "22 37 45 65 73", "13", "05" ] -, [ 1700, "DCC4E78B-4BF2-4D5D-8229-BCE9DEEB08C0", 1700, 1472076211, "708543", 1472076211, "708543", null, "2016-08-23T00:00:00", "02 07 46 61 66", "01", "02" ] -, [ 1701, "273F2248-9E79-4C97-B889-CAAD926DFA38", 1701, 1472292089, "708543", 1472292089, "708543", null, "2016-08-26T00:00:00", "10 11 31 41 44", "14", "02" ] -, [ 1702, "8B3C608A-E36D-43C1-9D18-1D403785CFB5", 1702, 1472637685, "708543", 1472637685, "708543", null, "2016-08-30T00:00:00", "28 32 41 51 71", "11", "04" ] -, [ 1703, "8E89CD90-99D4-4B76-9804-BFD0A158ED62", 1703, 1472896890, "708543", 1472896890, "708543", null, "2016-09-02T00:00:00", "22 28 41 46 60", "03", "03" ] -, [ 1704, "7D26FA54-E694-4AEA-95D9-6DEA7A996E01", 1704, 1473268935, "708543", 1473268935, "708543", null, "2016-09-06T00:00:00", "25 37 58 69 75", "08", "03" ] -, [ 1705, "FAF31467-323F-475D-A552-14C8A21B01CB", 1705, 1473501665, "708543", 1473501665, "708543", null, "2016-09-09T00:00:00", "01 34 43 44 63", "11", "04" ] -, [ 1706, "84C31388-A7AA-4E26-9744-E84E09C5552C", 1706, 1473847264, "708543", 1473847264, "708543", null, "2016-09-13T00:00:00", "06 15 17 39 56", "15", "03" ] -, [ 1707, "E6018DA5-15BE-41C0-9D93-531D725B4888", 1707, 1474106467, "708543", 1474106467, "708543", null, "2016-09-16T00:00:00", "13 21 28 34 40", "15", "03" ] -, [ 1708, "387F9D9B-8BC1-4DCA-B7E5-AC82FE71B8E0", 1708, 1474452067, "708543", 1474452067, "708543", null, "2016-09-20T00:00:00", "02 22 34 62 72", "02", "05" ] -, [ 1709, "9FAE3266-01D8-4DBF-9A73-3D8E1EEAC979", 1709, 1474711269, "708543", 1474711269, "708543", null, "2016-09-23T00:00:00", "01 05 08 25 62", "14", "03" ] -, [ 1710, "8B93C93D-B84C-4555-AED4-3D9CB3AA9776", 1710, 1475056863, "708543", 1475056863, "708543", null, "2016-09-27T00:00:00", "14 16 26 53 72", "04", "04" ] -, [ 1711, "4C02FA18-E31D-48D7-9452-7A226FDCB303", 1711, 1475316064, "708543", 1475316064, "708543", null, "2016-09-30T00:00:00", "21 30 47 50 57", "09", "05" ] -, [ 1712, "BF8A02DB-6CB8-4518-9D1A-39EDD6544658", 1712, 1475661663, "708543", 1475661663, "708543", null, "2016-10-04T00:00:00", "18 29 30 54 66", "01", "05" ] -, [ 1713, "1C68ACE2-D84B-455D-8013-D73C46A33B3C", 1713, 1475920864, "708543", 1475920864, "708543", null, "2016-10-07T00:00:00", "24 37 42 50 65", "14", "02" ] -, [ 1714, "F8296378-E773-4580-B6DE-BAFA66825C08", 1714, 1476266463, "708543", 1476266463, "708543", null, "2016-10-11T00:00:00", "36 39 42 45 48", "03", "02" ] -, [ 1715, "1674EA77-1766-4DBD-9B00-65384F2D0B10", 1715, 1476525664, "708543", 1476525664, "708543", null, "2016-10-14T00:00:00", "07 27 60 64 74", "05", "03" ] -, [ 1716, "9596D39E-D8E8-4CAA-B7FF-BA7A0B9849DD", 1716, 1476871264, "708543", 1476871264, "708543", null, "2016-10-18T00:00:00", "07 24 28 65 74", "01", "02" ] -, [ 1717, "00AA4CA5-AE12-4E21-8121-97BE38E6C511", 1717, 1477130472, "708543", 1477130472, "708543", null, "2016-10-21T00:00:00", "12 43 44 48 66", "03", "04" ] -, [ 1718, "0A85CFA3-AE43-4729-8311-BFBA0AADE5D4", 1718, 1477476148, "708543", 1477476148, "708543", null, "2016-10-25T00:00:00", "08 09 24 49 67", "13", "03" ] -, [ 1719, "9219598E-02DA-4CF5-854C-93EB269927DF", 1719, 1477735313, "708543", 1477735313, "708543", null, "2016-10-28T00:00:00", "07 38 46 57 66", "02", "05" ] -, [ 1720, "32C5372F-AFE4-4A21-A2C0-4476B4136338", 1720, 1478080862, "708543", 1478080862, "708543", null, "2016-11-01T00:00:00", "19 24 31 39 45", "13", "02" ] -, [ 1721, "E0DAAFDE-7446-4E41-8D60-38D73DF49F0E", 1721, 1478340064, "708543", 1478340064, "708543", null, "2016-11-04T00:00:00", "10 29 32 44 46", "10", "03" ] -, [ 1722, "0344AAB0-8B3C-43C2-9C70-9009F8E9FBA5", 1722, 1478689263, "708543", 1478689263, "708543", null, "2016-11-08T00:00:00", "46 48 53 61 74", "12", "04" ] -, [ 1723, "F348889E-FDF7-4DB6-8492-E44FD7807A44", 1723, 1478948463, "708543", 1478948463, "708543", null, "2016-11-11T00:00:00", "16 40 47 53 59", "11", "05" ] -, [ 1724, "45E178E8-1A5D-4C5C-A8CD-491DC5B192D7", 1724, 1479294062, "708543", 1479294062, "708543", null, "2016-11-15T00:00:00", "09 17 23 57 71", "06", "03" ] -, [ 1725, "6FF8AD19-266E-47BE-8DDC-0604876C3BAD", 1725, 1479553263, "708543", 1479553263, "708543", null, "2016-11-18T00:00:00", "31 32 49 55 58", "15", "05" ] -, [ 1726, "A78E2756-66C5-442A-AABD-F2EDC0E468EE", 1726, 1479899137, "708543", 1479899137, "708543", null, "2016-11-22T00:00:00", "01 43 45 66 69", "07", "05" ] -, [ 1727, "EFC65225-EFB0-4CDC-8EFF-626C6B56421E", 1727, 1480158306, "708543", 1480158306, "708543", null, "2016-11-25T00:00:00", "44 47 49 69 75", "10", "03" ] -, [ 1728, "60D9C9FE-16A3-4665-8B22-562BC0455695", 1728, 1480503662, "708543", 1480503662, "708543", null, "2016-11-29T00:00:00", "22 33 49 51 59", "08", "04" ] -, [ 1729, "4E86685E-363A-43CE-A927-4E327A8E0796", 1729, 1480762864, "708543", 1480762864, "708543", null, "2016-12-02T00:00:00", "03 33 35 49 51", "01", "02" ] -, [ 1730, "053614AB-69B8-4A4E-9309-3EAED9879AC4", 1730, 1481108463, "708543", 1481108463, "708543", null, "2016-12-06T00:00:00", "13 34 48 53 63", "12", "04" ] -, [ 1731, "DA02B9B1-5288-4D72-B13D-DAA2D3848E1D", 1731, 1481454064, "708543", 1481454064, "708543", null, "2016-12-09T00:00:00", "19 27 47 67 68", "01", "05" ] -, [ 1732, "3AD77F5E-F385-4384-8D55-6E0537C8371D", 1732, 1481713263, "708543", 1481713263, "708543", null, "2016-12-13T00:00:00", "02 15 26 34 41", "14", "05" ] -, [ 1733, "45ADFFB5-0863-456E-BBDA-A17A74B1B3FC", 1733, 1481972465, "708543", 1481972465, "708543", null, "2016-12-16T00:00:00", "01 08 15 36 43", "06", "05" ] -, [ 1734, "77491A99-CD4A-406E-9794-2EB82DEDB58D", 1734, 1482318191, "708543", 1482318191, "708543", null, "2016-12-20T00:00:00", "01 12 14 48 65", "02", "05" ] -, [ 1735, "714943E2-57A3-4101-8ED2-F4FC7530E30B", 1735, 1482577541, "708543", 1482577541, "708543", null, "2016-12-23T00:00:00", "21 30 39 60 69", "15", "05" ] -, [ 1736, "9283006E-6539-4923-B806-004B27DCFE8C", 1736, 1482922987, "708543", 1482922987, "708543", null, "2016-12-27T00:00:00", "02 28 30 38 39", "11", "04" ] -, [ 1737, "AE2B492D-A47C-482A-AD4D-10D664C3BA67", 1737, 1483182148, "708543", 1483182148, "708543", null, "2016-12-30T00:00:00", "06 21 33 39 43", "02", "02" ] -, [ 1738, "5D46057F-9D99-4702-81CC-4F49A38D643F", 1738, 1483527775, "708543", 1483527775, "708543", null, "2017-01-03T00:00:00", "14 16 23 49 53", "12", "02" ] -, [ 1739, "2D5234E0-E230-4272-91E3-8416C6B75BF6", 1739, 1483786929, "708543", 1483786929, "708543", null, "2017-01-06T00:00:00", "06 10 44 47 54", "06", "05" ] -, [ 1740, "3DC94C0A-7A60-45E1-A0E9-24383610F930", 1740, 1484132463, "708543", 1484132463, "708543", null, "2017-01-10T00:00:00", "11 20 40 41 59", "15", "05" ] -, [ 1741, "0301A455-E49F-4073-8F9D-503176FAC83E", 1741, 1484391663, "708543", 1484391663, "708543", null, "2017-01-13T00:00:00", "10 44 58 74 75", "11", "03" ] -, [ 1742, "F4F58F62-5E75-4002-BDEF-D80122F8413D", 1742, 1484737264, "708543", 1484737264, "708543", null, "2017-01-17T00:00:00", "20 31 54 56 59", "03", "05" ] -, [ 1744, "0B9EA1DD-8367-47A3-940D-66AB052177C6", 1744, 1485342205, "708543", 1485342205, "708543", null, "2017-01-20T00:00:00", "07 09 24 41 53", "14", "03" ] -, [ 1745, "63C31E5D-BA55-43C2-9E9B-9B4BA7DB0B74", 1745, 1485342246, "708543", 1485342246, "708543", null, "2017-01-24T00:00:00", "08 42 54 63 67", "11", "04" ] -, [ 1746, "759F3C65-541D-49FF-BE9A-28D067247072", 1746, 1485601284, "708543", 1485601284, "708543", null, "2017-01-27T00:00:00", "17 37 53 54 61", "08", "03" ] -, [ 1747, "E68E6833-8A5D-471C-854A-A8951B2FEC47", 1747, 1485946975, "708543", 1485946975, "708543", null, "2017-01-31T00:00:00", "03 14 27 62 72", "04", "03" ] -, [ 1748, "40A6F426-B63F-4829-813E-B85B848156A9", 1748, 1486206064, "708543", 1486206064, "708543", null, "2017-02-03T00:00:00", "03 06 29 30 64", "03", "05" ] -, [ 1749, "C6F73F48-40BF-485D-A2CD-473041C2F024", 1749, 1486551663, "708543", 1486551663, "708543", null, "2017-02-07T00:00:00", "23 28 37 56 71", "12", "05" ] -, [ 1750, "38FEE57B-E1E5-484E-923E-967FA6B59C7B", 1750, 1486810865, "708543", 1486810865, "708543", null, "2017-02-10T00:00:00", "32 39 51 62 75", "14", "05" ] -, [ 1751, "1ED88425-BBBE-481E-B401-8FB56251794C", 1751, 1487156483, "708543", 1487156483, "708543", null, "2017-02-14T00:00:00", "07 11 33 60 68", "15", "05" ] -, [ 1752, "50DC084A-AB4F-4CF9-9431-1242348550D7", 1752, 1487415663, "708543", 1487415663, "708543", null, "2017-02-17T00:00:00", "04 56 58 67 75", "08", "05" ] -, [ 1753, "3657D265-4C07-4890-BFA3-C188C1846DAF", 1753, 1487761263, "708543", 1487761263, "708543", null, "2017-02-21T00:00:00", "09 21 30 32 75", "09", "05" ] -, [ 1754, "D41829B2-3AA3-4663-9BAE-B7F2E91290E7", 1754, 1488020464, "708543", 1488020464, "708543", null, "2017-02-24T00:00:00", "12 29 33 42 68", "14", "03" ] -, [ 1755, "B0F99384-F7AE-402A-BACC-F6F317DC6DED", 1755, 1488366063, "708543", 1488366063, "708543", null, "2017-02-28T00:00:00", "20 33 45 58 69", "04", "02" ] -, [ 1756, "F8753135-AD9D-4059-9862-C4AA0AAB259C", 1756, 1488625264, "708543", 1488625264, "708543", null, "2017-03-03T00:00:00", "14 26 39 48 51", "09", "05" ] -, [ 1757, "D4F83543-9B57-40C6-A9DE-FCEE3E05B3CE", 1757, 1488970863, "708543", 1488970863, "708543", null, "2017-03-07T00:00:00", "03 30 45 53 68", "11", "03" ] -, [ 1758, "A4282612-1A7F-461F-81C4-DB4E6EEACD96", 1758, 1489230064, "708543", 1489230064, "708543", null, "2017-03-10T00:00:00", "26 38 42 58 70", "05", "05" ] -, [ 1759, "CE0B76F1-7657-4984-A22F-874F6106E232", 1759, 1489572063, "708543", 1489572063, "708543", null, "2017-03-14T00:00:00", "16 23 28 33 59", "13", "03" ] -, [ 1760, "0638F069-9AFE-4471-A553-D074B4574341", 1760, 1489831264, "708543", 1489831264, "708543", null, "2017-03-17T00:00:00", "11 27 31 58 60", "10", "04" ] -, [ 1761, "22420896-3EE1-4690-BFFF-564A46D017D7", 1761, 1490176862, "708543", 1490176862, "708543", null, "2017-03-21T00:00:00", "04 45 53 73 75", "07", "03" ] -, [ 1762, "DB64A17B-1CDD-4077-944B-CD8A6DCE8E76", 1762, 1490436062, "708543", 1490436062, "708543", null, "2017-03-24T00:00:00", "05 28 37 61 69", "01", "05" ] -, [ 1763, "3EA50957-B887-4FB0-AB54-70F5A9ED385C", 1763, 1490781664, "708543", 1490781664, "708543", null, "2017-03-28T00:00:00", "30 33 35 37 46", "10", "05" ] -, [ 1764, "9893AE26-8C83-4E1A-A74F-3563F9C980AE", 1764, 1491040863, "708543", 1491040863, "708543", null, "2017-03-31T00:00:00", "17 24 27 32 58", "10", "03" ] -, [ 1765, "B935B56A-C478-43EF-AF02-AC85613DF286", 1765, 1491386467, "708543", 1491386467, "708543", null, "2017-04-04T00:00:00", "13 24 34 35 55", "09", "05" ] -, [ 1766, "ED3D7FE2-51BC-4055-ADF6-05FDD98A75AE", 1766, 1491645663, "708543", 1491645663, "708543", null, "2017-04-07T00:00:00", "30 33 43 47 69", "15", "05" ] -, [ 1767, "EFA3E720-B90F-42BF-AAB4-7815B320B313", 1767, 1491991262, "708543", 1491991262, "708543", null, "2017-04-11T00:00:00", "19 34 35 38 49", "08", "05" ] -, [ 1768, "10D0ECDB-2152-4073-840D-78AE2A4085BD", 1768, 1492250463, "708543", 1492250463, "708543", null, "2017-04-14T00:00:00", "05 10 55 60 73", "12", "05" ] -, [ 1769, "AE102C01-DAE4-461A-9CC1-23B5B9694881", 1769, 1492596083, "708543", 1492596083, "708543", null, "2017-04-18T00:00:00", "08 29 30 43 64", "06", "03" ] -, [ 1770, "A6AD1EA5-6800-451A-ACDE-1187FAD9B566", 1770, 1492855281, "708543", 1492855281, "708543", null, "2017-04-21T00:00:00", "01 12 13 32 34", "10", "02" ] -, [ 1771, "17BE4C71-7B00-47D6-B4CE-1EFC7E3A2916", 1771, 1493200863, "708543", 1493200863, "708543", null, "2017-04-25T00:00:00", "03 13 33 40 50", "02", "04" ] -, [ 1772, "A020B997-F086-4F1B-99E8-36C46069D873", 1772, 1493460064, "708543", 1493460064, "708543", null, "2017-04-28T00:00:00", "06 13 18 20 31", "13", "04" ] -, [ 1773, "1727AFF8-9F51-4634-8E03-C5CF20E45000", 1773, 1493805664, "708543", 1493805664, "708543", null, "2017-05-02T00:00:00", "05 14 42 43 58", "01", "04" ] -, [ 1774, "30DFFCED-2E18-4FB6-BD33-62FD300F0E44", 1774, 1494064867, "708543", 1494064867, "708543", null, "2017-05-05T00:00:00", "04 23 33 47 53", "07", "04" ] -, [ 1775, "5976EE30-2E10-4BF9-BD9D-AD1C8E1EEFC1", 1775, 1494410464, "708543", 1494410464, "708543", null, "2017-05-09T00:00:00", "06 29 45 69 73", "11", "05" ] -, [ 1776, "6F450884-CDD9-4523-9265-FA369DD13916", 1776, 1494669666, "708543", 1494669666, "708543", null, "2017-05-12T00:00:00", "28 34 41 42 47", "13", "04" ] -, [ 1777, "E31793AD-5A3D-46D6-92CD-F913A92498CF", 1777, 1495015264, "708543", 1495015264, "708543", null, "2017-05-16T00:00:00", "04 35 39 56 72", "11", "05" ] -, [ 1778, "A2D9FAC3-749D-48A9-B5F4-CBE7C647FDE6", 1778, 1495274464, "708543", 1495274464, "708543", null, "2017-05-19T00:00:00", "01 04 05 24 30", "01", "03" ] -, [ 1779, "2C2AD6B7-7EFC-44E7-B605-9056848A94F8", 1779, 1495620065, "708543", 1495620065, "708543", null, "2017-05-23T00:00:00", "06 13 17 33 60", "14", "02" ] -, [ 1780, "05675B2E-FE56-4DC0-81FA-A8AB14DD214D", 1780, 1495879264, "708543", 1495879264, "708543", null, "2017-05-26T00:00:00", "25 26 28 37 56", "05", "03" ] -, [ 1781, "346129F8-E92D-43DF-91DE-B694AB06BF04", 1781, 1496224863, "708543", 1496224863, "708543", null, "2017-05-30T00:00:00", "05 20 32 37 67", "05", "05" ] -, [ 1782, "72417B49-381B-4F9A-BFE5-AC92EFF700DF", 1782, 1496484066, "708543", 1496484066, "708543", null, "2017-06-02T00:00:00", "07 42 57 69 72", "10", "03" ] -, [ 1783, "417815C8-6350-42FE-9DA2-BDA965D13F75", 1783, 1496829663, "708543", 1496829663, "708543", null, "2017-06-06T00:00:00", "03 05 16 49 75", "05", "03" ] -, [ 1784, "11947D29-85FA-4288-B16A-7673C450B25C", 1784, 1497088864, "708543", 1497088864, "708543", null, "2017-06-09T00:00:00", "03 16 28 33 37", "09", "05" ] -, [ 1785, "BA728323-F4EB-4037-AE22-37CA3D6FF2AE", 1785, 1497434463, "708543", 1497434463, "708543", null, "2017-06-13T00:00:00", "27 51 62 68 75", "08", "03" ] -, [ 1786, "D5161AD7-1ED0-45A6-803D-24D27B3B72AD", 1786, 1497693665, "708543", 1497693665, "708543", null, "2017-06-16T00:00:00", "18 22 26 30 44", "09", "05" ] -, [ 1787, "E58ABE14-127D-49FF-8B96-F3A43551985D", 1787, 1498039264, "708543", 1498039264, "708543", null, "2017-06-20T00:00:00", "02 15 41 49 63", "03", "03" ] -, [ 1788, "E0AB73AA-FB82-4D5A-BBE6-3C8C7F4C35E2", 1788, 1498298464, "708543", 1498298464, "708543", null, "2017-06-23T00:00:00", "12 20 53 66 74", "11", "02" ] -, [ 1789, "317B88B2-1E7B-4988-8E08-DB2D6B93FDB5", 1789, 1498644063, "708543", 1498644063, "708543", null, "2017-06-27T00:00:00", "04 21 45 52 57", "14", "04" ] -, [ 1790, "704B021F-90F0-430C-827F-344C6716B574", 1790, 1498903263, "708543", 1498903263, "708543", null, "2017-06-30T00:00:00", "10 38 51 55 64", "06", "05" ] -, [ 1791, "77AE800A-DB56-460A-968D-FC03DCDA98FC", 1791, 1499248863, "708543", 1499248863, "708543", null, "2017-07-04T00:00:00", "16 39 47 53 71", "15", "04" ] -, [ 1792, "B699871F-3188-410B-BD10-CF831C3ED41D", 1792, 1499508064, "708543", 1499508064, "708543", null, "2017-07-07T00:00:00", "02 09 11 28 60", "10", "05" ] -, [ 1793, "DB8207CA-BD86-4ABB-B937-8FB0177A4AE9", 1793, 1499853662, "708543", 1499853662, "708543", null, "2017-07-11T00:00:00", "07 18 24 55 74", "10", "02" ] -, [ 1794, "7E9FDDE3-A7BC-436C-9A65-D81EE060EAD0", 1794, 1500112863, "708543", 1500112863, "708543", null, "2017-07-14T00:00:00", "11 12 24 32 73", "01", "04" ] -, [ 1795, "1212E8CB-D109-45ED-90A6-C568D2E40C2E", 1795, 1500458464, "708543", 1500458464, "708543", null, "2017-07-18T00:00:00", "08 12 23 51 73", "06", "04" ] -, [ 1796, "FD732321-5433-49B1-AC3E-22D79F295C62", 1796, 1500717663, "708543", 1500717663, "708543", null, "2017-07-21T00:00:00", "18 31 36 50 74", "10", "04" ] -, [ 1797, "63EA61AF-4FF9-404F-B971-DB540DBFE9D5", 1797, 1501063263, "708543", 1501063263, "708543", null, "2017-07-25T00:00:00", "02 05 26 58 60", "06", "03" ] -, [ 1798, "DC590A73-39DE-4FCC-93B3-07241059B1E0", 1798, 1501322464, "708543", 1501322464, "708543", null, "2017-07-28T00:00:00", "04 06 31 49 52", "11", "03" ] - ] -} \ No newline at end of file + }, + "data": [ + [ + 1, + "DD63E09E-4222-4E85-B209-4ECB6FEB8B9D", + 1, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-05-17T00:00:00Z", + "15 18 25 33 47", + "30", + null + ], + [ + 2, + "CDB0B5A7-F4E1-4D26-97E2-C0643DF22F9C", + 2, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-05-21T00:00:00Z", + "04 28 39 41 44", + "09", + null + ], + [ + 3, + "2E7BD2A6-7685-4C03-9DA2-F23490539D0A", + 3, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-05-24T00:00:00Z", + "02 04 32 44 52", + "36", + null + ], + [ + 4, + "5A8BEB43-7731-4019-87CA-5674C82123F7", + 4, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-05-28T00:00:00Z", + "06 21 22 29 32", + "24", + null + ], + [ + 5, + "AA15F9F3-C9B9-413D-84AA-915039E534D4", + 5, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-05-31T00:00:00Z", + "12 28 45 46 52", + "47", + null + ], + [ + 6, + "E322CD76-D127-4524-97D7-073B62D1E2CE", + 6, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-04T00:00:00Z", + "03 25 29 30 48", + "48", + null + ], + [ + 7, + "6D9D2AF9-D5C9-486A-B522-0F00B9DE27F4", + 7, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-07T00:00:00Z", + "14 22 27 28 42", + "13", + null + ], + [ + 8, + "D5C31C03-3C01-4089-83ED-D286EC8EB4E0", + 8, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-11T00:00:00Z", + "05 06 09 33 44", + "52", + null + ], + [ + 9, + "D195047D-520E-43B4-AB07-62468B5F0D7D", + 9, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-14T00:00:00Z", + "04 08 32 37 43", + "02", + null + ], + [ + 10, + "B70FC384-3AB2-4374-BE6B-19FE0B1B5E60", + 10, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-18T00:00:00Z", + "06 13 18 27 45", + "18", + null + ], + [ + 11, + "604A874F-7DA9-4CD2-90EB-E6AC68736016", + 11, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-21T00:00:00Z", + "13 18 32 39 49", + "06", + null + ], + [ + 12, + "BB41E518-5BAD-4AE3-90C3-2BFCB25FA9AF", + 12, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-25T00:00:00Z", + "04 18 21 27 41", + "50", + null + ], + [ + 13, + "E927B1DB-EE55-4BD2-AD76-23F93A0151AC", + 13, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-06-28T00:00:00Z", + "18 31 49 50 51", + "04", + null + ], + [ + 14, + "B676A329-65DC-4084-AABE-6A25C83EFAB3", + 14, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-02T00:00:00Z", + "14 22 32 35 44", + "06", + null + ], + [ + 15, + "776E4AE3-82C8-48CF-930B-C92A1F571516", + 15, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-05T00:00:00Z", + "11 20 26 29 41", + "41", + null + ], + [ + 16, + "DD63071A-8491-4ED3-A3AC-18352FA79BED", + 16, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-09T00:00:00Z", + "26 29 31 44 48", + "40", + null + ], + [ + 17, + "3BD81BA2-8C8F-4A58-AAC2-22D96A0672B7", + 17, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-12T00:00:00Z", + "13 19 23 38 47", + "15", + null + ], + [ + 18, + "46D285E0-FE04-43C5-A848-B9846D038F5B", + 18, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-16T00:00:00Z", + "10 24 35 49 52", + "47", + null + ], + [ + 19, + "470FA664-DEB5-49C3-9D6F-A3C187FA6FDF", + 19, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-19T00:00:00Z", + "07 15 24 37 46", + "09", + null + ], + [ + 20, + "4F3CA620-EA20-4576-B91B-44A4A8C38B1C", + 20, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-23T00:00:00Z", + "10 12 29 32 38", + "07", + null + ], + [ + 21, + "7326095E-618A-4DD2-8949-BC6BE5358158", + 21, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-26T00:00:00Z", + "20 27 28 37 49", + "32", + null + ], + [ + 22, + "CFAC1CDB-7D92-4432-97D7-83E5FBDB3D8A", + 22, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-07-30T00:00:00Z", + "02 06 22 27 44", + "01", + null + ], + [ + 23, + "A2F33330-714C-4D90-93AF-E003BFDE8459", + 23, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-02T00:00:00Z", + "10 16 23 28 31", + "07", + null + ], + [ + 24, + "69C74D9F-48C8-4A14-9A1D-BF41DE0AFB20", + 24, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-06T00:00:00Z", + "02 06 38 40 50", + "14", + null + ], + [ + 25, + "0FB58BD0-9EE5-4018-BE99-65A943A57052", + 25, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-09T00:00:00Z", + "07 17 23 43 44", + "26", + null + ], + [ + 26, + "F90BA0BD-C520-44C5-B511-6A12634A3CE3", + 26, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-13T00:00:00Z", + "03 10 15 18 25", + "52", + null + ], + [ + 27, + "A22129D4-F083-4E99-97C7-15E807B2053E", + 27, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-16T00:00:00Z", + "22 31 33 44 52", + "43", + null + ], + [ + 28, + "0B145B86-D93E-4729-B31F-102C9BA6E2F5", + 28, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-20T00:00:00Z", + "02 13 20 23 43", + "06", + null + ], + [ + 29, + "E813DDA1-E3CA-4B4D-9FE2-290318C777DA", + 29, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-23T00:00:00Z", + "05 19 20 45 48", + "44", + null + ], + [ + 30, + "6292DFE4-D4A5-484A-9E52-8D2CDD57346E", + 30, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-27T00:00:00Z", + "02 05 11 18 45", + "22", + null + ], + [ + 31, + "5F8C47D5-94BF-4744-879A-879576D98824", + 31, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-08-30T00:00:00Z", + "06 31 32 42 51", + "42", + null + ], + [ + 32, + "0B608831-82DE-4A5D-B1B5-175B0386B92C", + 32, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-03T00:00:00Z", + "08 23 36 49 51", + "10", + null + ], + [ + 33, + "0729E99F-EDF4-4CF8-9C7D-538F359A43D6", + 33, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-06T00:00:00Z", + "31 39 42 49 51", + "35", + null + ], + [ + 34, + "480239A2-53C4-49F8-9B38-0C50CEA74DAA", + 34, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-10T00:00:00Z", + "04 06 10 21 25", + "21", + null + ], + [ + 35, + "2A460703-1EE5-4863-AD16-AB89FEE47E3C", + 35, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-13T00:00:00Z", + "24 32 37 40 51", + "12", + null + ], + [ + 36, + "FE0F5025-940B-4B6A-8748-078CE383248C", + 36, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-17T00:00:00Z", + "07 10 19 26 44", + "05", + null + ], + [ + 37, + "F8B8EB29-240C-4EDD-8D83-767A7144D889", + 37, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-20T00:00:00Z", + "01 02 04 05 46", + "08", + null + ], + [ + 38, + "B16F1457-6AE7-4F6E-9CD4-2D2A45FAC9AE", + 38, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-24T00:00:00Z", + "08 32 34 42 50", + "21", + null + ], + [ + 39, + "5B3358D5-CEC6-40A2-B805-27C3C0CEFC46", + 39, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-09-27T00:00:00Z", + "23 27 30 33 36", + "05", + null + ], + [ + 40, + "F4B78AC5-E425-4199-8847-378923739E98", + 40, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-01T00:00:00Z", + "07 21 30 32 37", + "15", + null + ], + [ + 41, + "E38867F4-3486-42B1-BB61-C62BFB44E0DC", + 41, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-04T00:00:00Z", + "10 42 43 45 51", + "01", + null + ], + [ + 42, + "807547BC-EE1A-4B65-84AD-3CE1E854FC35", + 42, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-08T00:00:00Z", + "18 34 43 47 50", + "25", + null + ], + [ + 43, + "AC63F7BD-012F-4C12-8661-D4E4117368C1", + 43, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-11T00:00:00Z", + "09 11 17 26 41", + "29", + null + ], + [ + 44, + "A3E5E55D-900C-494F-9E9F-09406CF28772", + 44, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-15T00:00:00Z", + "06 20 27 34 51", + "22", + null + ], + [ + 45, + "76FE6E0D-849C-4876-9B35-79B6945D12B9", + 45, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-18T00:00:00Z", + "10 31 40 48 51", + "38", + null + ], + [ + 46, + "0247E8D6-04A3-4975-BB28-9E5ED39E7013", + 46, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-22T00:00:00Z", + "16 20 26 36 48", + "32", + null + ], + [ + 47, + "203F46F2-9559-4634-B419-0CF89FC181B5", + 47, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-25T00:00:00Z", + "08 15 34 39 47", + "04", + null + ], + [ + 48, + "A6901E49-98E3-4C6E-8315-0266D96AEB91", + 48, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-10-29T00:00:00Z", + "09 10 14 41 49", + "35", + null + ], + [ + 49, + "DE30E918-423E-42EB-BA73-F657ABCFD8FE", + 49, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-01T00:00:00Z", + "05 10 22 23 43", + "37", + null + ], + [ + 50, + "6A5EF20C-5F46-4DB1-B77E-01E1D55D805F", + 50, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-05T00:00:00Z", + "02 07 16 28 36", + "47", + null + ], + [ + 51, + "0DDE170F-9285-4B87-B30A-AD3C7F643585", + 51, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-08T00:00:00Z", + "17 19 37 47 48", + "14", + null + ], + [ + 52, + "DB2E5ECC-86E3-49E6-BE8D-B36C8B860FAE", + 52, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-12T00:00:00Z", + "03 28 45 48 50", + "24", + null + ], + [ + 53, + "C9E90F12-A9A5-4650-A6F3-D5D7D0A7ED1C", + 53, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-15T00:00:00Z", + "06 17 44 49 51", + "39", + null + ], + [ + 54, + "E7969201-469E-43CD-9B96-5B4D9B5535A1", + 54, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-19T00:00:00Z", + "07 16 20 40 52", + "08", + null + ], + [ + 55, + "270528C5-6420-4FE3-AAA1-8D19B8AFB6E2", + 55, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-22T00:00:00Z", + "11 16 19 22 46", + "05", + null + ], + [ + 56, + "C15AD01F-1345-43D5-B0AB-769467A17A9B", + 56, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-26T00:00:00Z", + "03 21 27 31 43", + "34", + null + ], + [ + 57, + "32E2EF7A-2D3B-4AB7-883D-78E2E55D037E", + 57, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-11-29T00:00:00Z", + "08 25 33 42 49", + "40", + null + ], + [ + 58, + "2B065668-6258-414B-92E3-4C992B783DDD", + 58, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-03T00:00:00Z", + "01 15 19 40 51", + "26", + null + ], + [ + 59, + "3974C6B7-6B78-4503-8DD4-7AF43B9D83C6", + 59, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-06T00:00:00Z", + "04 08 30 36 52", + "48", + null + ], + [ + 60, + "2B12B387-2C45-4544-B2C5-509EC3EF25EA", + 60, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-10T00:00:00Z", + "03 05 09 16 31", + "28", + null + ], + [ + 61, + "B82357E8-CA56-4079-9CF8-7D4801ECD65B", + 61, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-13T00:00:00Z", + "02 13 14 24 46", + "34", + null + ], + [ + 62, + "13CB91BC-2F31-42F1-8107-89B322AFE86F", + 62, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-17T00:00:00Z", + "03 07 21 29 49", + "46", + null + ], + [ + 63, + "22F91DAE-F451-4527-8222-987F1A38D258", + 63, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-20T00:00:00Z", + "10 14 41 46 49", + "52", + null + ], + [ + 64, + "BD3EC7D2-2C57-4E83-AF26-17710AD6A208", + 64, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-24T00:00:00Z", + "08 24 39 43 52", + "43", + null + ], + [ + 65, + "D5CCC43B-959F-44B1-B13D-A7E410E4E761", + 65, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-27T00:00:00Z", + "11 14 26 30 39", + "03", + null + ], + [ + 66, + "E285D142-DA61-4320-A64B-0460BC9AD06E", + 66, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2002-12-31T00:00:00Z", + "08 21 29 42 51", + "34", + null + ], + [ + 67, + "98E41CD9-7A07-4777-99C4-7A3FF99E1843", + 67, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-03T00:00:00Z", + "06 14 28 37 46", + "03", + null + ], + [ + 68, + "AEEA3F05-8610-47C6-A1DD-8A179E989AE2", + 68, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-07T00:00:00Z", + "15 16 28 34 51", + "33", + null + ], + [ + 69, + "4E06CBF1-A178-49DD-8633-0BC1B37DA970", + 69, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-10T00:00:00Z", + "07 17 18 34 50", + "18", + null + ], + [ + 70, + "C0AA6972-7E61-44F6-AB49-00E2F277C475", + 70, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-14T00:00:00Z", + "30 39 41 47 52", + "27", + null + ], + [ + 71, + "628A1E63-1D14-49BB-AD14-242855DA8215", + 71, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-17T00:00:00Z", + "25 26 38 42 46", + "27", + null + ], + [ + 72, + "08C611B7-7BF9-4151-BF2F-7813FD7B1CF8", + 72, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-21T00:00:00Z", + "04 41 48 50 51", + "23", + null + ], + [ + 73, + "46A0C177-42F3-40FD-A28F-1039BA0F4CEF", + 73, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-24T00:00:00Z", + "16 31 37 40 41", + "05", + null + ], + [ + 74, + "E45F2A0A-C3CB-4F40-9975-154ACD72FA7F", + 74, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-28T00:00:00Z", + "13 24 26 32 47", + "34", + null + ], + [ + 75, + "3BC338E9-A5E7-4BE9-BBB8-F2BF9D15CEE4", + 75, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-01-31T00:00:00Z", + "01 08 09 19 22", + "21", + null + ], + [ + 76, + "A4515DBC-FFBA-409E-8BE8-CF303205D017", + 76, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-04T00:00:00Z", + "05 12 16 22 24", + "48", + null + ], + [ + 77, + "1522A885-5C53-4246-988D-05F89AA7D40B", + 77, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-07T00:00:00Z", + "03 09 20 26 27", + "50", + null + ], + [ + 78, + "90677E80-B1E2-4F1F-AA35-AF8916FBBF9F", + 78, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-11T00:00:00Z", + "18 20 23 48 49", + "10", + null + ], + [ + 79, + "7707C582-F232-41DB-B2AD-482FF443C9E8", + 79, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-14T00:00:00Z", + "11 13 19 32 47", + "21", + null + ], + [ + 80, + "3F14C37A-54D4-4DCD-B83A-3A7F267441DE", + 80, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-18T00:00:00Z", + "12 22 29 42 50", + "11", + null + ], + [ + 81, + "5823D1CA-DABD-4A60-980E-83739E6F1CA2", + 81, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-21T00:00:00Z", + "21 28 29 40 51", + "20", + null + ], + [ + 82, + "FFB2EDFC-6008-43C7-B085-802A10E87EB1", + 82, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-25T00:00:00Z", + "02 04 06 37 47", + "38", + null + ], + [ + 83, + "0A9ABE29-045E-4F63-9078-BAC824AB6704", + 83, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-02-28T00:00:00Z", + "11 16 26 48 49", + "13", + null + ], + [ + 84, + "4EE62AB5-8FA2-4D3A-B4B5-69A1C3EA158A", + 84, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-04T00:00:00Z", + "02 26 36 37 41", + "22", + null + ], + [ + 85, + "C2E50A67-D861-4786-A68D-C6A44BE85409", + 85, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-07T00:00:00Z", + "07 10 32 36 41", + "33", + null + ], + [ + 86, + "26C6335D-FB4B-45B0-BE37-E1D1C7775527", + 86, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-11T00:00:00Z", + "10 15 26 28 39", + "10", + null + ], + [ + 87, + "EE125C30-5C1A-4655-A8EB-2B1CC440DB50", + 87, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-14T00:00:00Z", + "03 06 14 31 33", + "08", + null + ], + [ + 88, + "E14A17CA-D479-4C2C-8128-464926CBD322", + 88, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-18T00:00:00Z", + "13 14 16 29 49", + "29", + null + ], + [ + 89, + "D137FA48-2A58-4107-911F-D8DB91D708EA", + 89, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-21T00:00:00Z", + "06 17 18 40 50", + "08", + null + ], + [ + 90, + "ADE703B0-44B8-4EF3-9251-743D5A9EC566", + 90, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-25T00:00:00Z", + "15 21 37 40 42", + "07", + null + ], + [ + 91, + "AB8E0352-1F85-4DCE-A9F0-D14E4536B079", + 91, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-03-28T00:00:00Z", + "08 12 21 27 29", + "15", + null + ], + [ + 92, + "09359168-05CA-40CC-A9DA-CDEF43B38B53", + 92, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-01T00:00:00Z", + "07 12 26 45 47", + "36", + null + ], + [ + 93, + "3BE7FEFD-6E77-4543-AED2-C671DFF538B2", + 93, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-04T00:00:00Z", + "06 22 28 31 40", + "18", + null + ], + [ + 94, + "31DE14F3-C5F3-4570-95E5-BDD9CF730DCF", + 94, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-08T00:00:00Z", + "08 10 24 38 45", + "06", + null + ], + [ + 95, + "5D649EB0-C1CA-4816-B26B-2B0167EA660F", + 95, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-11T00:00:00Z", + "15 26 27 38 39", + "46", + null + ], + [ + 96, + "D3506FF7-DF54-441A-8CE5-83F036B839DA", + 96, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-15T00:00:00Z", + "16 29 31 39 52", + "21", + null + ], + [ + 97, + "E46D4DDD-F39E-483B-9039-5861A76A47F2", + 97, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-18T00:00:00Z", + "05 15 24 50 52", + "03", + null + ], + [ + 98, + "7E8146F7-D852-40DE-8C52-43BE45BE562E", + 98, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-22T00:00:00Z", + "03 09 15 28 52", + "07", + null + ], + [ + 99, + "BA9B9A00-E659-425F-9D67-A92211D08CBE", + 99, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-25T00:00:00Z", + "01 12 32 48 51", + "29", + null + ], + [ + 100, + "58C1D225-815B-4DB8-B948-35A652949308", + 100, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-04-29T00:00:00Z", + "06 08 09 33 35", + "32", + null + ], + [ + 101, + "1754387A-A0DF-4168-918F-8168243D07A8", + 101, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-02T00:00:00Z", + "02 05 19 32 34", + "52", + null + ], + [ + 102, + "9D5762AF-6758-46C0-9171-827486835D08", + 102, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-06T00:00:00Z", + "05 14 32 44 52", + "24", + null + ], + [ + 103, + "454BC472-EEFE-4ACF-B4F9-168839FD8665", + 103, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-09T00:00:00Z", + "01 10 20 22 28", + "39", + null + ], + [ + 104, + "A8D661D0-3B6B-440D-B4E0-CD61055A1FD4", + 104, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-13T00:00:00Z", + "17 20 47 49 50", + "34", + null + ], + [ + 105, + "B7EC9B0F-9AFE-45FD-93B2-7FFCA2ED8EDA", + 105, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-16T00:00:00Z", + "05 10 16 26 39", + "52", + null + ], + [ + 106, + "1CF96B88-1B48-488A-BD4E-DB23E455812F", + 106, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-20T00:00:00Z", + "02 16 36 44 49", + "03", + null + ], + [ + 107, + "96DDFF18-6B91-4025-BD0A-8E7BFB8F145C", + 107, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-23T00:00:00Z", + "12 20 31 33 50", + "17", + null + ], + [ + 108, + "B9DB7AEF-4963-490A-9021-D3F9DF7E44CA", + 108, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-27T00:00:00Z", + "10 11 17 20 26", + "03", + null + ], + [ + 109, + "FAD4EBFE-8EA9-440F-A64A-6EAA0751142A", + 109, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-05-30T00:00:00Z", + "01 21 28 33 51", + "03", + null + ], + [ + 110, + "49420CC9-2969-499C-9682-0922078F53C7", + 110, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-03T00:00:00Z", + "04 20 25 29 32", + "20", + null + ], + [ + 111, + "DE8AF8DE-54CC-47F3-B3BB-05471B80C030", + 111, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-06T00:00:00Z", + "10 14 28 39 40", + "35", + null + ], + [ + 112, + "7AEC15E5-8753-42DA-8D8B-D44AE2936037", + 112, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-10T00:00:00Z", + "14 15 23 32 52", + "37", + null + ], + [ + 113, + "3744E2FD-4467-473F-AD08-615DABDF4BF9", + 113, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-13T00:00:00Z", + "12 15 16 20 51", + "33", + null + ], + [ + 114, + "4204CF2D-6A71-49DB-A1CC-EC65C7F337DF", + 114, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-17T00:00:00Z", + "27 31 34 40 52", + "01", + null + ], + [ + 115, + "D1D590C1-A5BC-462B-9004-A666D7301BCD", + 115, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-20T00:00:00Z", + "01 02 03 12 37", + "35", + null + ], + [ + 116, + "4975BB43-7289-4C7B-8A35-FAF5F1B2DCB5", + 116, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-24T00:00:00Z", + "02 26 43 44 47", + "31", + null + ], + [ + 117, + "C02F25C6-38D1-4DF6-B6A1-FBFFD94BD95F", + 117, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-06-27T00:00:00Z", + "01 14 20 31 40", + "43", + null + ], + [ + 118, + "B417F0A8-9D77-4C4D-9AAC-CCD1CFBDE184", + 118, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-01T00:00:00Z", + "28 32 39 45 48", + "31", + null + ], + [ + 119, + "AB2B5C72-8FE3-4793-853E-1AE475BB514D", + 119, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-04T00:00:00Z", + "06 07 22 37 46", + "08", + null + ], + [ + 120, + "142013F7-D91E-44AC-95CC-8DE4C4FB06FC", + 120, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-08T00:00:00Z", + "02 09 27 29 35", + "18", + null + ], + [ + 121, + "5EC16F46-F61F-438D-9158-380060242B6E", + 121, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-11T00:00:00Z", + "01 04 10 16 18", + "10", + null + ], + [ + 122, + "10344C0E-E9A9-4272-A637-331A9CE4C387", + 122, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-15T00:00:00Z", + "01 26 33 43 48", + "22", + null + ], + [ + 123, + "F56CED15-FCFF-4517-A2C8-7304D1539E69", + 123, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-18T00:00:00Z", + "29 30 34 38 44", + "39", + null + ], + [ + 124, + "26143402-87D4-49D1-88EF-E33AFDC3508E", + 124, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-22T00:00:00Z", + "01 05 31 38 47", + "03", + null + ], + [ + 125, + "5B59CCDB-E5F1-4AEE-B128-3E8CF145939D", + 125, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-25T00:00:00Z", + "33 46 47 50 51", + "30", + null + ], + [ + 126, + "AFC67E7B-C793-46F7-9EF1-1C52AA2E94EE", + 126, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-07-29T00:00:00Z", + "01 17 19 32 42", + "33", + null + ], + [ + 127, + "E1C1FA86-E45D-4A8E-82F7-9A5BD5C8485C", + 127, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-01T00:00:00Z", + "02 11 27 30 33", + "46", + null + ], + [ + 128, + "BE4D241F-D6A3-42D5-B82D-C7C5F548BAA7", + 128, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-05T00:00:00Z", + "07 32 34 38 44", + "49", + null + ], + [ + 129, + "34419EB4-F8CE-4979-BF7A-022B83FE4119", + 129, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-08T00:00:00Z", + "06 09 35 40 43", + "42", + null + ], + [ + 130, + "D97F5B99-5715-41DB-989F-EE646D0885CE", + 130, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-12T00:00:00Z", + "08 11 18 35 51", + "26", + null + ], + [ + 131, + "54DD969F-9ADB-409E-8C07-FD104FF3214E", + 131, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-15T00:00:00Z", + "01 16 20 41 52", + "13", + null + ], + [ + 132, + "C45D583E-DBF7-419A-AC90-92366F3BEC38", + 132, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-19T00:00:00Z", + "07 11 24 28 52", + "16", + null + ], + [ + 133, + "FB0467F9-610B-4187-B189-A1679E990D91", + 133, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-22T00:00:00Z", + "04 19 31 32 51", + "31", + null + ], + [ + 134, + "E3BF4E12-0FBC-4324-9FE1-6DA035540AEA", + 134, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-26T00:00:00Z", + "09 28 42 44 49", + "47", + null + ], + [ + 135, + "4367D263-7EB2-4860-AB00-CEEE46595568", + 135, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-08-29T00:00:00Z", + "08 11 17 42 52", + "10", + null + ], + [ + 136, + "703C475D-9209-4E84-B245-E167C7CF15CB", + 136, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-02T00:00:00Z", + "22 26 27 32 39", + "14", + null + ], + [ + 137, + "87F8EC61-3E18-42A4-9DFD-F0C83B86394D", + 137, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-05T00:00:00Z", + "07 09 28 41 42", + "19", + null + ], + [ + 138, + "2F14383B-8605-4624-8AD2-5A0FBB27AFB8", + 138, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-09T00:00:00Z", + "14 15 30 39 46", + "30", + null + ], + [ + 139, + "7EE72B00-2CE6-4041-B9C6-D3E5A30B58CD", + 139, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-12T00:00:00Z", + "16 22 23 38 46", + "45", + null + ], + [ + 140, + "A9512471-39BE-4381-81A2-16D003C63F06", + 140, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-16T00:00:00Z", + "15 20 24 30 46", + "42", + null + ], + [ + 141, + "C33B630E-4AEF-471A-B115-ACE4C7ABB4C9", + 141, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-19T00:00:00Z", + "13 14 24 34 47", + "13", + null + ], + [ + 142, + "90AECD1E-D7A1-4C0C-B40A-A6FEE8C89582", + 142, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-23T00:00:00Z", + "05 16 24 49 51", + "28", + null + ], + [ + 143, + "10BE1B47-B8F8-4C5D-B864-161897D232A4", + 143, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-26T00:00:00Z", + "05 29 32 45 52", + "29", + null + ], + [ + 144, + "456D7CA6-FEE6-4DA7-81CA-2DCA2E97A114", + 144, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-09-30T00:00:00Z", + "02 26 37 40 46", + "49", + null + ], + [ + 145, + "58CBE626-2263-4622-83A1-172520060895", + 145, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-03T00:00:00Z", + "19 21 30 31 52", + "51", + null + ], + [ + 146, + "DEBA65E1-7811-402B-B00F-BA8FF5397918", + 146, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-07T00:00:00Z", + "01 02 22 40 41", + "43", + null + ], + [ + 147, + "6EBA14B3-3CB0-451D-8E30-F8C1478D229C", + 147, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-10T00:00:00Z", + "04 19 36 42 48", + "13", + null + ], + [ + 148, + "60C042BD-AA8F-438F-BAC3-DA0659C4AAE5", + 148, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-14T00:00:00Z", + "18 19 21 33 40", + "29", + null + ], + [ + 149, + "E3056AF1-D254-4FF8-AD9E-B519592CD15C", + 149, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-17T00:00:00Z", + "14 20 31 46 48", + "18", + null + ], + [ + 150, + "3F10D07A-00CD-4903-B1CF-9AE1CDCE0BE9", + 150, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-21T00:00:00Z", + "18 34 46 51 52", + "38", + null + ], + [ + 151, + "286A4F08-E3C6-43AA-9218-5DE78829445C", + 151, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-24T00:00:00Z", + "08 09 16 30 31", + "15", + null + ], + [ + 152, + "96DA12DE-9616-409F-9B97-D0EF9B2361F0", + 152, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-28T00:00:00Z", + "06 09 20 40 47", + "26", + null + ], + [ + 153, + "CF8AF49F-06AB-467D-9465-ECC72ED4FBEB", + 153, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-10-31T00:00:00Z", + "06 12 13 36 46", + "03", + null + ], + [ + 154, + "660B8C66-B5F5-43F2-8B48-1D1BD288F397", + 154, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-04T00:00:00Z", + "16 24 43 44 45", + "22", + null + ], + [ + 155, + "12930383-A5F6-4021-864F-6E6613EFCC02", + 155, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-07T00:00:00Z", + "06 18 23 26 30", + "31", + null + ], + [ + 156, + "55ACF0F2-4E61-4DD1-9AD0-121B04E8E2D8", + 156, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-11T00:00:00Z", + "02 05 17 21 22", + "43", + null + ], + [ + 157, + "AFFE3574-5A71-449A-A5A9-89A02CC63B46", + 157, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-14T00:00:00Z", + "03 13 31 41 42", + "52", + null + ], + [ + 158, + "53838D7A-3459-4B07-A5EA-62D93F98F5A0", + 158, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-18T00:00:00Z", + "04 11 25 30 52", + "36", + null + ], + [ + 159, + "028A208C-371B-4F58-B771-ADDDE67122A1", + 159, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-21T00:00:00Z", + "14 26 28 36 42", + "14", + null + ], + [ + 160, + "89F065A8-44C0-4FB4-B16E-A67EE3D12895", + 160, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-25T00:00:00Z", + "22 32 37 40 41", + "52", + null + ], + [ + 161, + "9328CDE3-5932-40FC-8D93-F4D5F75D4900", + 161, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-11-28T00:00:00Z", + "19 26 31 44 50", + "19", + null + ], + [ + 162, + "6EC846B7-104F-4C4A-B8E0-8BF46EA0E67F", + 162, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-02T00:00:00Z", + "10 13 24 34 49", + "04", + null + ], + [ + 163, + "A3AA23AD-8665-4F09-BADB-96C5D5C54D3A", + 163, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-05T00:00:00Z", + "01 12 15 18 44", + "42", + null + ], + [ + 164, + "181538CE-E898-498C-897E-13CEF30A9A24", + 164, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-09T00:00:00Z", + "04 14 15 24 48", + "41", + null + ], + [ + 165, + "19102899-F12B-405C-A594-F212042C01CB", + 165, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-12T00:00:00Z", + "09 16 32 45 46", + "26", + null + ], + [ + 166, + "00A140E6-B878-453E-9C36-31A84EE9EB95", + 166, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-16T00:00:00Z", + "16 24 31 46 47", + "47", + null + ], + [ + 167, + "736F2B3D-93B7-4DAE-B6AF-C4C9BF2EE8EE", + 167, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-19T00:00:00Z", + "05 10 17 35 39", + "38", + null + ], + [ + 168, + "8CA935B2-B5C0-419D-87EF-26F64B6EC006", + 168, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-23T00:00:00Z", + "02 13 21 22 49", + "52", + null + ], + [ + 169, + "F7C96926-4484-494B-A7C9-676DCA6F1729", + 169, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-26T00:00:00Z", + "01 10 17 20 29", + "36", + null + ], + [ + 170, + "16F8399E-7FE4-401B-B800-FA7BB56A97DD", + 170, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2003-12-30T00:00:00Z", + "12 18 21 32 46", + "49", + null + ], + [ + 171, + "9ED8E78A-62FB-41C1-870E-8CDFC91C74D6", + 171, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-02T00:00:00Z", + "07 08 36 44 48", + "09", + null + ], + [ + 172, + "3CF133FE-1FA3-47DD-897C-60481ED06E88", + 172, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-06T00:00:00Z", + "07 13 15 25 32", + "09", + null + ], + [ + 173, + "22948242-9DDD-43CB-BF72-CF93BD75566E", + 173, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-09T00:00:00Z", + "24 32 38 47 49", + "12", + null + ], + [ + 174, + "35461A28-871A-479F-953A-E06F8CB4384F", + 174, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-13T00:00:00Z", + "03 17 18 21 45", + "21", + null + ], + [ + 175, + "7DABD050-F49B-41BF-A9BA-656346A9F38C", + 175, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-16T00:00:00Z", + "12 26 41 44 49", + "44", + null + ], + [ + 176, + "90A89117-6F30-49F5-A23C-8333F74EAA1E", + 176, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-20T00:00:00Z", + "05 07 14 21 45", + "36", + null + ], + [ + 177, + "80664E0D-B4D2-49F0-9959-C9AB17CF93AE", + 177, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-23T00:00:00Z", + "10 18 33 46 51", + "13", + null + ], + [ + 178, + "D0CE2C24-B101-4185-B19B-D158FB47ED3E", + 178, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-27T00:00:00Z", + "06 10 20 38 50", + "27", + null + ], + [ + 179, + "F01C707E-9960-4E43-A81E-1782647082A3", + 179, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-01-30T00:00:00Z", + "17 28 30 40 51", + "44", + null + ], + [ + 180, + "677A8C08-956F-46C4-B6A3-F651B929C471", + 180, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-03T00:00:00Z", + "09 21 26 35 41", + "17", + null + ], + [ + 181, + "1AC95439-5800-4931-80E8-F93513E15EFA", + 181, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-06T00:00:00Z", + "01 06 16 30 49", + "13", + null + ], + [ + 182, + "DDE9D7CC-A931-4103-AB9A-DC3DDF728EB5", + 182, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-10T00:00:00Z", + "03 07 10 22 32", + "23", + null + ], + [ + 183, + "166A3441-00D2-4FEC-BF3B-631E835EA49C", + 183, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-13T00:00:00Z", + "14 30 42 43 45", + "30", + null + ], + [ + 184, + "1BDB7F1B-A39A-4115-B172-3303380E1DF3", + 184, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-17T00:00:00Z", + "02 08 34 36 52", + "21", + null + ], + [ + 185, + "E355CFD8-D090-41B8-8811-028D99AB8DA8", + 185, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-20T00:00:00Z", + "01 13 20 21 30", + "24", + null + ], + [ + 186, + "B999148E-D11E-440B-81DA-789CB7E68DBB", + 186, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-24T00:00:00Z", + "06 11 43 49 52", + "21", + null + ], + [ + 187, + "1F1CC98F-6F31-4BF7-9145-56C2FF15E6FD", + 187, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-02-27T00:00:00Z", + "02 09 24 36 52", + "44", + null + ], + [ + 188, + "A78AF303-06C3-4C18-8CD0-491D985D7A43", + 188, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-02T00:00:00Z", + "25 30 35 40 50", + "04", + null + ], + [ + 189, + "5D0C62A6-844E-4C80-8981-1EC4862B165A", + 189, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-05T00:00:00Z", + "30 40 47 49 52", + "03", + null + ], + [ + 190, + "DF590B22-E81F-41A7-9ED0-B792C9CE5249", + 190, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-09T00:00:00Z", + "16 23 29 36 51", + "49", + null + ], + [ + 191, + "DD89D574-8A08-41C4-A5EE-4E4A5AA07163", + 191, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-12T00:00:00Z", + "04 29 32 35 36", + "11", + null + ], + [ + 192, + "9F301819-E19D-4D62-8128-AE50FC932F93", + 192, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-16T00:00:00Z", + "03 28 45 49 51", + "52", + null + ], + [ + 193, + "287B8DFB-0016-4750-86CA-425DB92CA791", + 193, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-19T00:00:00Z", + "06 09 14 32 50", + "04", + null + ], + [ + 194, + "30AC2580-A52B-4268-A81C-BF18BE48945D", + 194, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-23T00:00:00Z", + "12 22 35 39 46", + "32", + null + ], + [ + 195, + "151FEC11-E77A-43D6-B5F5-E0B0A884017B", + 195, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-26T00:00:00Z", + "08 10 17 37 49", + "20", + null + ], + [ + 196, + "F7C95B95-0C63-4A37-AA6B-EA02803C0F1E", + 196, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-03-30T00:00:00Z", + "03 27 31 41 45", + "33", + null + ], + [ + 197, + "37183BCC-D528-4EFF-8337-4329057BB4E6", + 197, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-02T00:00:00Z", + "08 17 25 46 47", + "13", + null + ], + [ + 198, + "D0B36FC0-DF03-4360-8B25-4346181571B2", + 198, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-06T00:00:00Z", + "08 17 29 32 39", + "49", + null + ], + [ + 199, + "4401F17E-E367-440B-99FB-688A755EA807", + 199, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-09T00:00:00Z", + "02 08 10 11 23", + "40", + null + ], + [ + 200, + "64E8D621-CD53-43AA-A99E-9469BF1CF78D", + 200, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-13T00:00:00Z", + "13 36 39 50 51", + "34", + null + ], + [ + 201, + "530AD7EA-F834-4223-8EB1-35148E1329A8", + 201, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-16T00:00:00Z", + "06 24 29 42 51", + "41", + null + ], + [ + 202, + "CE4121AF-B677-4B9B-9061-E3BC4CCE3CF4", + 202, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-20T00:00:00Z", + "12 22 37 46 48", + "49", + null + ], + [ + 203, + "D89990AD-D822-43B2-9D98-B4DB4D36BD27", + 203, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-23T00:00:00Z", + "08 22 25 47 48", + "27", + null + ], + [ + 204, + "8F52A470-2731-451C-A0E9-652338AC2AE5", + 204, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-27T00:00:00Z", + "01 10 17 23 35", + "45", + null + ], + [ + 205, + "EEEDFFAB-7B51-4B47-9167-604CD2BBCEDC", + 205, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-04-30T00:00:00Z", + "15 21 32 39 50", + "34", + null + ], + [ + 206, + "4281178C-8AE5-4EDB-AE19-FFCE603ED9F8", + 206, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-04T00:00:00Z", + "03 15 29 37 39", + "40", + null + ], + [ + 207, + "FA75A85C-0A84-44B0-BD03-3F6BB05FDE6D", + 207, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-07T00:00:00Z", + "14 17 19 44 50", + "17", + null + ], + [ + 208, + "3FAD2848-7B00-4795-AAD7-B595FE15B0F2", + 208, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-11T00:00:00Z", + "09 25 30 34 37", + "30", + null + ], + [ + 209, + "EDE45563-04A9-452C-950C-F90D50C60B7F", + 209, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-14T00:00:00Z", + "10 19 32 36 46", + "06", + null + ], + [ + 210, + "2CA731BD-CD0F-4CAA-A73D-952783FB2963", + 210, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-18T00:00:00Z", + "02 36 44 46 51", + "45", + null + ], + [ + 211, + "AB2A1494-C7CD-406A-869E-E91C3B1F9BDB", + 211, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-21T00:00:00Z", + "04 20 27 38 49", + "31", + null + ], + [ + 212, + "C1BA08C1-1F30-487B-9E16-4E11970807DA", + 212, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-25T00:00:00Z", + "05 18 34 36 39", + "43", + null + ], + [ + 213, + "7883E5E8-E510-4E95-B2AE-1B3E6322025A", + 213, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-05-28T00:00:00Z", + "13 27 36 39 51", + "33", + null + ], + [ + 214, + "BE1D586A-3362-4D15-B51F-52F8B09B3BC7", + 214, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-01T00:00:00Z", + "07 16 17 26 48", + "15", + null + ], + [ + 215, + "4C803D13-0DF9-4B75-AB36-BFA811A6A44B", + 215, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-04T00:00:00Z", + "04 16 18 41 47", + "46", + null + ], + [ + 216, + "90CECF2B-081E-46D8-ADF3-DE9AF9FFA85D", + 216, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-08T00:00:00Z", + "17 24 29 37 45", + "43", + null + ], + [ + 217, + "23D2B616-7C32-44DE-BF92-F965349CD096", + 217, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-11T00:00:00Z", + "12 28 36 39 52", + "36", + null + ], + [ + 218, + "74430CB6-1A79-4878-963D-E5DFF95B7882", + 218, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-15T00:00:00Z", + "18 23 27 29 44", + "24", + null + ], + [ + 219, + "3CFF8EC5-D00F-4EBC-8E08-DA91AECA3A61", + 219, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-18T00:00:00Z", + "07 10 11 15 51", + "23", + null + ], + [ + 220, + "D13D362C-47B9-44A7-948D-2377519ACDAB", + 220, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-22T00:00:00Z", + "09 10 17 41 52", + "19", + null + ], + [ + 221, + "1B04F369-0AA5-4EC1-9ACE-1B1B1A29949B", + 221, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-25T00:00:00Z", + "18 19 29 32 42", + "32", + null + ], + [ + 222, + "A4EB48A6-5B93-4F87-937D-3FA8D3D9B13A", + 222, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-06-29T00:00:00Z", + "10 13 19 28 38", + "01", + null + ], + [ + 223, + "C973AB92-79E2-4F3B-9532-29B1EF730C15", + 223, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-02T00:00:00Z", + "10 25 38 39 50", + "12", + null + ], + [ + 224, + "2A8B3B87-C571-44C5-8B72-4D5FC07E3C4E", + 224, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-06T00:00:00Z", + "06 07 08 31 48", + "19", + null + ], + [ + 225, + "0CB0EEF7-3E07-47C2-834A-CCC22BD96076", + 225, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-09T00:00:00Z", + "11 23 25 29 45", + "16", + null + ], + [ + 226, + "FFB87A81-D21E-4374-AB89-D0E77B35C578", + 226, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-13T00:00:00Z", + "13 31 37 39 52", + "38", + null + ], + [ + 227, + "11FB4729-5353-4468-8630-1404816AE321", + 227, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-16T00:00:00Z", + "03 21 22 35 44", + "07", + null + ], + [ + 228, + "9C3F4245-A499-4EBC-BF96-C29B635CA561", + 228, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-20T00:00:00Z", + "06 15 21 32 44", + "13", + null + ], + [ + 229, + "C09247AD-299E-4A91-A8CF-C3A0179AB270", + 229, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-23T00:00:00Z", + "05 12 25 35 37", + "12", + null + ], + [ + 230, + "DA4F201D-2A37-4504-9947-14F8542402D5", + 230, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-27T00:00:00Z", + "08 10 11 13 24", + "46", + null + ], + [ + 231, + "169DA2A4-95D6-4BCC-AEFD-46C5FA9370B2", + 231, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-07-30T00:00:00Z", + "16 19 21 34 35", + "22", + null + ], + [ + 232, + "025397EA-5654-411F-880E-EB525C9D29B9", + 232, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-03T00:00:00Z", + "01 02 13 16 22", + "31", + null + ], + [ + 233, + "B45BCE14-9723-436A-B1D2-A98665679467", + 233, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-06T00:00:00Z", + "04 23 33 38 49", + "07", + null + ], + [ + 234, + "9DA11ECD-BC04-4EE6-890B-3B22B141D912", + 234, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-10T00:00:00Z", + "18 25 29 31 44", + "33", + null + ], + [ + 235, + "29B3B61A-07FB-45E4-8E2B-42BADD6E2B13", + 235, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-13T00:00:00Z", + "14 31 41 45 48", + "20", + null + ], + [ + 236, + "4D1C8130-8D61-4BE8-820C-335E37212DDC", + 236, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-17T00:00:00Z", + "22 23 26 28 36", + "10", + null + ], + [ + 237, + "0E60BFAF-3237-4A2F-9EC4-25458A705F26", + 237, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-20T00:00:00Z", + "12 17 34 37 39", + "34", + null + ], + [ + 238, + "79D77C70-4484-4795-A6B0-D5F87F1C2E74", + 238, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-24T00:00:00Z", + "02 05 21 47 50", + "46", + null + ], + [ + 239, + "ABB0385F-D6B3-4ED7-A7BE-75C967EFF5F3", + 239, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-27T00:00:00Z", + "05 25 38 46 47", + "14", + null + ], + [ + 240, + "825BC9DA-7E28-48DF-B5DC-DB33D1F598E8", + 240, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-08-31T00:00:00Z", + "14 15 25 42 44", + "03", + null + ], + [ + 241, + "64C6A60E-3E95-495C-BC4A-44C53814E058", + 241, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-03T00:00:00Z", + "04 14 34 38 44", + "10", + null + ], + [ + 242, + "E6ADBDFD-2F6B-4726-A525-746186368933", + 242, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-07T00:00:00Z", + "13 30 36 38 51", + "35", + null + ], + [ + 243, + "2F5EDD22-FB98-43CC-811B-9877253B4F8A", + 243, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-10T00:00:00Z", + "11 17 27 45 52", + "05", + null + ], + [ + 244, + "BCD22E2B-7328-49C3-8CC3-FC63B9A344D7", + 244, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-14T00:00:00Z", + "12 35 37 38 50", + "49", + null + ], + [ + 245, + "5835A221-CB4A-4785-B15B-84FF74486672", + 245, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-17T00:00:00Z", + "03 16 25 38 49", + "04", + null + ], + [ + 246, + "1D628B4B-456A-430D-96D3-6F4DE602BCFA", + 246, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-21T00:00:00Z", + "01 03 15 19 29", + "39", + null + ], + [ + 247, + "22DAACA0-0D4E-4874-A27D-60C726301E87", + 247, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-24T00:00:00Z", + "11 26 30 49 50", + "52", + null + ], + [ + 248, + "DB3BC6FA-6BD3-48AC-8B65-65B6A9681BE6", + 248, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-09-28T00:00:00Z", + "01 18 39 42 50", + "35", + null + ], + [ + 249, + "F9C7E41D-9C9B-49D1-A4E3-15FC77F7F86F", + 249, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-01T00:00:00Z", + "08 10 17 24 39", + "52", + null + ], + [ + 250, + "52BE51BE-708D-4321-8C26-DE6165AFE04E", + 250, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-05T00:00:00Z", + "08 34 39 48 49", + "47", + null + ], + [ + 251, + "B4000AC5-B2AE-4BA0-94A2-E044745964AC", + 251, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-08T00:00:00Z", + "16 17 21 33 41", + "06", + null + ], + [ + 252, + "D191CC09-A515-4BF6-B819-1FE3B2CA14B3", + 252, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-12T00:00:00Z", + "04 18 19 39 51", + "13", + null + ], + [ + 253, + "A162D2E1-642C-49E6-992A-BB972253B641", + 253, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-15T00:00:00Z", + "04 08 24 30 36", + "25", + null + ], + [ + 254, + "50754DC2-AFD6-4809-ACFD-2853213FE3DC", + 254, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-19T00:00:00Z", + "06 13 19 34 50", + "33", + null + ], + [ + 255, + "6BBC3098-B05C-482D-934B-6BF8C7930F01", + 255, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-22T00:00:00Z", + "03 07 20 24 43", + "36", + null + ], + [ + 256, + "F2BC443C-393C-42AC-97CD-03845FA2AF4B", + 256, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-26T00:00:00Z", + "14 25 39 43 49", + "27", + null + ], + [ + 257, + "FD20CDD7-751B-45E2-A189-6F06336E4662", + 257, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-10-29T00:00:00Z", + "10 18 26 31 41", + "48", + null + ], + [ + 258, + "78F4866D-7BBE-4981-AF76-82B4B1FF4A2E", + 258, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-02T00:00:00Z", + "24 32 42 49 50", + "03", + null + ], + [ + 259, + "0F1336CF-A403-4F6D-9FE9-6A54EF4F7707", + 259, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-05T00:00:00Z", + "03 29 30 41 43", + "01", + null + ], + [ + 260, + "F081994F-6D07-4891-BFAF-1AFF8C14CFD4", + 260, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-09T00:00:00Z", + "11 20 26 28 52", + "07", + null + ], + [ + 261, + "2BD8589C-58C2-4EB1-9AC2-9D7680A25908", + 261, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-12T00:00:00Z", + "05 31 33 35 51", + "01", + null + ], + [ + 262, + "CEF71225-C2BF-4B92-B680-278C358B7720", + 262, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-16T00:00:00Z", + "09 10 27 28 30", + "18", + null + ], + [ + 263, + "66BA5BBF-68B0-4AFA-8271-418B80BC6718", + 263, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-19T00:00:00Z", + "01 12 24 36 51", + "38", + null + ], + [ + 264, + "8509E8A0-2D85-4259-92F6-29B471E9AC37", + 264, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-23T00:00:00Z", + "08 30 32 35 51", + "17", + null + ], + [ + 265, + "E28F4368-1712-48D1-91F6-26904326CF2D", + 265, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-26T00:00:00Z", + "07 09 18 37 43", + "34", + null + ], + [ + 266, + "74CF5561-90C2-45C1-979E-F07822F35FC2", + 266, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-11-30T00:00:00Z", + "10 20 22 28 52", + "04", + null + ], + [ + 267, + "B41849CC-89C1-483B-949C-6F6A87CD73A0", + 267, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-03T00:00:00Z", + "12 32 37 41 52", + "13", + null + ], + [ + 268, + "579AAC40-3B30-4E09-87DD-B5A87C2D92A5", + 268, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-07T00:00:00Z", + "01 19 22 32 49", + "29", + null + ], + [ + 269, + "A3A9B945-6C27-48B4-AC62-8EE5F1FD0A30", + 269, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-10T00:00:00Z", + "22 23 37 42 47", + "15", + null + ], + [ + 270, + "8926C688-28B7-4534-AFE5-51FE044A3927", + 270, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-14T00:00:00Z", + "14 27 32 34 40", + "02", + null + ], + [ + 271, + "22DBCDF8-AEB6-4F84-865A-E25E670EE8A6", + 271, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-17T00:00:00Z", + "16 34 38 42 47", + "01", + null + ], + [ + 272, + "3F07DD76-991F-49F8-BE80-C9D05D80F060", + 272, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-21T00:00:00Z", + "07 22 27 31 38", + "12", + null + ], + [ + 273, + "41AC3E8D-EC34-4E08-AA87-5918880FE818", + 273, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-24T00:00:00Z", + "09 20 22 41 42", + "10", + null + ], + [ + 274, + "65F331BB-6BD2-495C-8FCB-E0460922F04E", + 274, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-28T00:00:00Z", + "18 29 32 38 43", + "50", + null + ], + [ + 275, + "588CD7B2-93DC-4A0F-9437-36D0C339AA9C", + 275, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2004-12-31T00:00:00Z", + "10 14 45 47 51", + "20", + null + ], + [ + 276, + "93825C54-2A7A-434A-AC7B-D60BEA85F53D", + 276, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-04T00:00:00Z", + "03 06 07 12 32", + "30", + null + ], + [ + 277, + "F4313158-89FD-4820-A8A7-36C5C88ED660", + 277, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-07T00:00:00Z", + "02 08 14 15 51", + "38", + null + ], + [ + 278, + "E8206E3B-51A1-4B45-A90E-CA2419422CA5", + 278, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-11T00:00:00Z", + "02 23 24 35 45", + "18", + null + ], + [ + 279, + "D3C97927-9FD1-4A11-BC1F-258ED901202F", + 279, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-14T00:00:00Z", + "15 19 24 40 47", + "50", + null + ], + [ + 280, + "B76A1E6C-C254-4CB3-AA0B-9E3D49472813", + 280, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-18T00:00:00Z", + "10 23 28 39 51", + "05", + null + ], + [ + 281, + "AF46D29A-1B37-4EEC-B4A5-E3B21DB5673A", + 281, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-21T00:00:00Z", + "17 27 39 40 41", + "21", + null + ], + [ + 282, + "929C4BC0-B7DC-458C-9230-1D510E57F709", + 282, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-25T00:00:00Z", + "02 10 21 25 45", + "22", + null + ], + [ + 283, + "AAF2C647-D464-4385-B732-B49913AF69CB", + 283, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-01-28T00:00:00Z", + "25 31 39 47 52", + "43", + null + ], + [ + 284, + "F1AF9F93-409C-4418-BCD8-390EA73B9336", + 284, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-01T00:00:00Z", + "03 17 21 42 44", + "35", + null + ], + [ + 285, + "DED59622-8D29-4664-8398-9FE120A46A87", + 285, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-04T00:00:00Z", + "03 12 14 30 52", + "34", + null + ], + [ + 286, + "6301C513-1F63-465C-9077-8FB388B4CEB4", + 286, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-08T00:00:00Z", + "08 11 14 23 25", + "21", + null + ], + [ + 287, + "B2F3018C-414F-4556-8635-405C6ADA0F10", + 287, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-11T00:00:00Z", + "06 14 21 24 50", + "28", + null + ], + [ + 288, + "12E0E1A8-1F85-4A57-B608-AD5AB2420CBF", + 288, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-15T00:00:00Z", + "03 16 20 21 38", + "10", + null + ], + [ + 289, + "82FC585B-BAAD-4725-A657-9646108D5DC4", + 289, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-18T00:00:00Z", + "01 19 31 35 42", + "34", + null + ], + [ + 290, + "5C140B83-2CEA-4985-B28B-663F7B5BABF3", + 290, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-22T00:00:00Z", + "15 18 28 41 45", + "27", + null + ], + [ + 291, + "4ADFED3A-9CF7-4D7B-A2CC-5A8F2053B472", + 291, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-02-25T00:00:00Z", + "04 13 37 38 50", + "24", + null + ], + [ + 292, + "1D4741B1-E68A-413C-B3BB-C403DB0C17DE", + 292, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-01T00:00:00Z", + "01 08 18 39 48", + "01", + null + ], + [ + 293, + "74C81011-F2BF-4720-B210-7743B22FBE8D", + 293, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-04T00:00:00Z", + "07 10 13 35 39", + "21", + null + ], + [ + 294, + "9B80E24B-1B29-406D-B39D-92CE0D9D84F3", + 294, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-08T00:00:00Z", + "08 14 15 22 31", + "13", + null + ], + [ + 295, + "31DF6251-BA07-45B6-A2F6-2C697D00C48E", + 295, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-11T00:00:00Z", + "18 19 31 35 36", + "17", + null + ], + [ + 296, + "708C6B64-35A2-42C9-8647-351C4BD30FDC", + 296, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-15T00:00:00Z", + "14 26 27 34 44", + "27", + null + ], + [ + 297, + "38357837-482D-41DD-AFD4-4AE48DF385CC", + 297, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-18T00:00:00Z", + "02 09 28 29 48", + "33", + null + ], + [ + 298, + "A7FA5D10-0B55-4947-B720-7C94D3610337", + 298, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-22T00:00:00Z", + "06 11 27 37 43", + "34", + null + ], + [ + 299, + "434ED7A8-6257-46F4-BBCC-D8A674C356F8", + 299, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-25T00:00:00Z", + "11 18 19 45 49", + "02", + null + ], + [ + 300, + "6CD696BD-A80A-44B1-B77D-FA1FF25E0F08", + 300, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-03-29T00:00:00Z", + "07 17 18 30 42", + "38", + null + ], + [ + 301, + "8CF288D1-0C69-4693-BE90-551A8127B384", + 301, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-01T00:00:00Z", + "11 19 28 32 45", + "10", + null + ], + [ + 302, + "8012F879-2E18-42E2-8711-19BE5F70B358", + 302, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-05T00:00:00Z", + "04 19 45 51 52", + "22", + null + ], + [ + 303, + "9B2671A2-C2BB-4A10-8205-F717FE4F741D", + 303, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-08T00:00:00Z", + "05 13 17 33 35", + "35", + null + ], + [ + 304, + "EDFB6722-641F-4EEC-B91C-EE7FE6E42B8F", + 304, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-12T00:00:00Z", + "15 20 43 47 50", + "24", + null + ], + [ + 305, + "37447A5F-204E-4912-9E95-5F017C168136", + 305, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-15T00:00:00Z", + "25 26 37 39 49", + "29", + null + ], + [ + 306, + "8E386A7C-E59E-42AA-B564-ECB8A4C383AA", + 306, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-19T00:00:00Z", + "05 06 14 42 47", + "03", + null + ], + [ + 307, + "0838C56E-BD1F-4819-9E52-2B4BFFDFDF66", + 307, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-22T00:00:00Z", + "23 25 43 46 49", + "26", + null + ], + [ + 308, + "559B2A64-C329-4BA1-9EE3-5B56BD11C81F", + 308, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-26T00:00:00Z", + "18 22 33 34 42", + "16", + null + ], + [ + 309, + "FE0AA6EB-B376-44B9-AB47-E2BA73934853", + 309, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-04-29T00:00:00Z", + "02 05 07 28 46", + "21", + null + ], + [ + 310, + "DC01C25F-6D99-46FE-A4A6-860DED5F011C", + 310, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-03T00:00:00Z", + "07 17 42 46 52", + "47", + null + ], + [ + 311, + "AA1EB43B-E2E0-403D-9D39-6B236AC3DE50", + 311, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-06T00:00:00Z", + "07 12 25 50 51", + "19", + null + ], + [ + 312, + "54907768-39E9-493F-B79D-54DD04E476F2", + 312, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-10T00:00:00Z", + "11 25 38 40 42", + "40", + null + ], + [ + 313, + "2EACE389-A6DB-459C-ADC5-AF98F96E5DC3", + 313, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-13T00:00:00Z", + "21 23 27 33 39", + "08", + null + ], + [ + 314, + "D0011038-F7E8-4ED5-A95E-EB30C075C01F", + 314, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-17T00:00:00Z", + "07 09 10 29 44", + "17", + null + ], + [ + 315, + "0695D550-C28B-4362-B428-CF02186E3AC6", + 315, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-20T00:00:00Z", + "03 06 27 40 44", + "09", + null + ], + [ + 316, + "F317FFE5-E091-476C-9ABA-DF9FF531C6D3", + 316, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-24T00:00:00Z", + "09 28 39 40 45", + "24", + null + ], + [ + 317, + "2CE91E33-2D19-4741-B712-B5A37A853E80", + 317, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-27T00:00:00Z", + "07 17 22 34 50", + "24", + null + ], + [ + 318, + "272EB917-BC29-44A6-B42F-2B1234927DB8", + 318, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-05-31T00:00:00Z", + "05 13 22 37 38", + "11", + null + ], + [ + 319, + "2C09A590-CE5E-4B0E-A216-49D6C1E2ED31", + 319, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-03T00:00:00Z", + "04 06 14 28 47", + "42", + null + ], + [ + 320, + "13B8AB19-B7DA-4DE8-B1FA-2F7B5C73B852", + 320, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-07T00:00:00Z", + "07 14 28 46 47", + "25", + null + ], + [ + 321, + "DE848D9F-40C5-4491-AFC6-66337901C5E2", + 321, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-10T00:00:00Z", + "14 29 31 37 50", + "34", + null + ], + [ + 322, + "B5DDE7DA-82E4-452E-AD3C-D0133EBC32E0", + 322, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-14T00:00:00Z", + "01 10 29 48 49", + "36", + null + ], + [ + 323, + "2B861970-45DA-4DD9-82B1-35FE957B34DE", + 323, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-17T00:00:00Z", + "16 35 40 49 50", + "34", + null + ], + [ + 324, + "B3FED69E-5468-4985-B4DC-89D71F6C06B0", + 324, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-21T00:00:00Z", + "09 13 40 46 50", + "30", + null + ], + [ + 325, + "033A0BD1-1324-4D5D-8409-6EE08E820D5E", + 325, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-24T00:00:00Z", + "14 43 44 50 56", + "07", + null + ], + [ + 326, + "83865852-9E82-454A-8334-B8E457FD5564", + 326, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-06-28T00:00:00Z", + "02 20 37 43 46", + "04", + null + ], + [ + 327, + "9AE7DD16-ABF4-4A5C-B036-1E3767164646", + 327, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-01T00:00:00Z", + "14 25 41 42 50", + "40", + null + ], + [ + 328, + "FAFFAC8C-2539-4ABC-AC83-F31E4745CD88", + 328, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-05T00:00:00Z", + "22 38 48 50 55", + "29", + null + ], + [ + 329, + "D031E86C-7BFC-46B8-8434-5ED4A422E3D5", + 329, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-08T00:00:00Z", + "09 23 45 48 50", + "03", + null + ], + [ + 330, + "A0C46007-15B5-428F-B3F9-65FE8F129069", + 330, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-12T00:00:00Z", + "05 17 32 39 53", + "36", + null + ], + [ + 331, + "F7E1B862-C554-4C22-BAA4-ACDDAC559AD7", + 331, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-15T00:00:00Z", + "09 13 25 36 48", + "02", + null + ], + [ + 332, + "C050912D-7E3B-4F8F-9317-51BDD65FE247", + 332, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-19T00:00:00Z", + "07 13 48 51 54", + "11", + null + ], + [ + 333, + "4DA6DF81-0826-413E-A33B-B149B510AA59", + 333, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-22T00:00:00Z", + "07 18 27 35 54", + "34", + null + ], + [ + 334, + "C43C9B1C-17E5-4148-BA4B-E5CEB3525941", + 334, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-26T00:00:00Z", + "01 10 18 29 55", + "08", + null + ], + [ + 335, + "561F43EE-FD24-4908-8042-F110C9D7FC98", + 335, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-07-29T00:00:00Z", + "04 16 23 25 40", + "22", + null + ], + [ + 336, + "13D5FF40-2E43-4A28-9FD9-E95FB19FE2AC", + 336, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-02T00:00:00Z", + "17 22 39 50 52", + "46", + null + ], + [ + 337, + "8B10E7B4-B3C5-4BCF-A62D-5B8BA3DE8355", + 337, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-05T00:00:00Z", + "03 05 48 50 53", + "04", + null + ], + [ + 338, + "E035770B-AAC3-40BC-AD66-E0D9E64372BC", + 338, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-09T00:00:00Z", + "13 35 36 43 52", + "05", + null + ], + [ + 339, + "0BC13F6C-2DF9-4834-B3D4-34F4E52DB6A0", + 339, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-12T00:00:00Z", + "08 37 38 45 54", + "21", + null + ], + [ + 340, + "40D316EA-945A-4584-A463-B7220694F598", + 340, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-16T00:00:00Z", + "09 15 20 24 55", + "03", + null + ], + [ + 341, + "2ECD8059-BFAD-4A9B-971E-C276188878C7", + 341, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-19T00:00:00Z", + "02 13 18 36 46", + "36", + null + ], + [ + 342, + "09F9240B-DF24-4C16-B8CB-813998920F64", + 342, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-23T00:00:00Z", + "06 07 08 13 40", + "12", + null + ], + [ + 343, + "08DC3E31-889F-4A80-9874-1A4FE05CFBF8", + 343, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-26T00:00:00Z", + "05 20 38 47 54", + "35", + null + ], + [ + 344, + "DFD70689-7341-47CD-B95F-BFE2D51D32C2", + 344, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-08-30T00:00:00Z", + "19 32 42 49 56", + "29", + null + ], + [ + 345, + "E5B9F273-A709-4583-8047-6FD74DE24846", + 345, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-02T00:00:00Z", + "01 04 14 45 53", + "33", + null + ], + [ + 346, + "ACC92702-99C0-4E8D-9C4D-5AF531E3E469", + 346, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-06T00:00:00Z", + "01 08 27 31 50", + "40", + null + ], + [ + 347, + "FC9EB200-2DF5-41F0-ABA3-AE199C366FF6", + 347, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-09T00:00:00Z", + "15 28 43 51 52", + "11", + null + ], + [ + 348, + "747A6C12-78D5-4FEF-8B8A-EF0FA8A3BC02", + 348, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-13T00:00:00Z", + "13 24 44 48 52", + "30", + null + ], + [ + 349, + "E81382F7-026A-4F8A-B94F-A37CCC4DCCD3", + 349, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-16T00:00:00Z", + "05 16 41 46 50", + "01", + null + ], + [ + 350, + "7ED2D57E-9121-440C-AA0F-C6B024E372EE", + 350, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-20T00:00:00Z", + "35 36 40 42 52", + "45", + null + ], + [ + 351, + "7328006D-B455-4A06-B68A-89FC788CBAFD", + 351, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-23T00:00:00Z", + "06 07 20 41 51", + "38", + null + ], + [ + 352, + "A9052160-FF2E-4C2F-8B1F-BFE55B0BD024", + 352, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-27T00:00:00Z", + "14 17 26 27 28", + "05", + null + ], + [ + 353, + "5A153CDF-3CB1-47D0-8242-899326BD456C", + 353, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-09-30T00:00:00Z", + "01 03 14 30 52", + "10", + null + ], + [ + 354, + "FE7185D0-A535-45CB-A6CC-01A0B09D6346", + 354, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-04T00:00:00Z", + "12 24 28 29 36", + "41", + null + ], + [ + 355, + "0ACAA2C4-D8AD-489E-8969-41FD4F1DA446", + 355, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-07T00:00:00Z", + "02 04 23 27 36", + "37", + null + ], + [ + 356, + "125F6530-E5F5-46C0-AEAA-67800AB47EBA", + 356, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-11T00:00:00Z", + "24 30 42 53 54", + "20", + null + ], + [ + 357, + "8AEE764F-10C9-4487-A4A7-BCC7B7432F4D", + 357, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-14T00:00:00Z", + "06 20 24 25 34", + "44", + null + ], + [ + 358, + "D1B8530E-5CE8-4CF8-9D8A-3E78F6D9711D", + 358, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-18T00:00:00Z", + "03 12 16 32 33", + "15", + null + ], + [ + 359, + "7FB69C53-5BCC-4612-963F-22A0FBE0D366", + 359, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-21T00:00:00Z", + "11 17 28 29 36", + "42", + null + ], + [ + 360, + "099CE0AD-F072-4A7F-9E16-24F9E265983B", + 360, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-25T00:00:00Z", + "07 12 18 31 55", + "30", + null + ], + [ + 361, + "82BD5396-346A-4808-8568-6DF24372709F", + 361, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-10-28T00:00:00Z", + "08 17 25 28 53", + "01", + null + ], + [ + 362, + "163D026B-60CB-4B09-B6C4-A7488308DD8E", + 362, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-01T00:00:00Z", + "05 18 21 28 36", + "20", + null + ], + [ + 363, + "2E75AF04-00FF-4E0E-BF24-395B9FB275E3", + 363, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-04T00:00:00Z", + "07 09 41 53 54", + "38", + null + ], + [ + 364, + "FC2FA6E3-E70C-4A4B-9F64-0FC75AC6BECF", + 364, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-08T00:00:00Z", + "08 16 21 25 27", + "16", + null + ], + [ + 365, + "B05C3588-63F4-4918-9A0B-22DC5BF62C32", + 365, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-11T00:00:00Z", + "09 14 34 50 51", + "40", + null + ], + [ + 366, + "97A88400-902F-44B4-A497-38AAAB38B7C5", + 366, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-15T00:00:00Z", + "02 04 05 40 48", + "07", + null + ], + [ + 367, + "2D471B32-ABF6-47E8-9B85-DE9BA6052D75", + 367, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-18T00:00:00Z", + "08 18 21 42 46", + "11", + null + ], + [ + 368, + "E21BBAC7-6A3A-411D-8328-9A3DAC360F70", + 368, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-22T00:00:00Z", + "09 22 37 41 43", + "30", + null + ], + [ + 369, + "F2DA346E-8664-43BC-8067-BF6F81FD71AD", + 369, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-25T00:00:00Z", + "05 25 31 33 34", + "41", + null + ], + [ + 370, + "3D150C47-1D71-4F59-9FAB-950EE578B141", + 370, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-11-29T00:00:00Z", + "07 08 47 51 52", + "05", + null + ], + [ + 371, + "D6D3E5D9-0AB1-41DD-88B8-70586D133D1E", + 371, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-02T00:00:00Z", + "03 12 21 38 44", + "45", + null + ], + [ + 372, + "C5BB8996-A321-4F80-BC0D-C2D880384DF1", + 372, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-06T00:00:00Z", + "06 10 26 30 33", + "16", + null + ], + [ + 373, + "F7F985C7-C509-4D77-B34A-FE8512F24EB3", + 373, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-09T00:00:00Z", + "14 15 31 32 43", + "20", + null + ], + [ + 374, + "90F85C5C-CDB9-42BE-AC2B-A7ADC515BAB2", + 374, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-13T00:00:00Z", + "09 10 12 22 41", + "04", + null + ], + [ + 375, + "F2ED349C-1FE5-4F23-BF41-D9D0CF91D948", + 375, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-16T00:00:00Z", + "14 25 26 31 56", + "17", + null + ], + [ + 376, + "156ED523-B9AE-4F78-9EA6-8AB545668B5C", + 376, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-20T00:00:00Z", + "06 20 23 40 56", + "36", + null + ], + [ + 377, + "16299179-341A-48BF-B14D-4F78593B59CA", + 377, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-23T00:00:00Z", + "10 37 39 49 54", + "08", + null + ], + [ + 378, + "F3F9CA26-835C-4F9F-AE53-9870DF0E82CB", + 378, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-27T00:00:00Z", + "11 24 27 49 55", + "23", + null + ], + [ + 379, + "E3B45416-2CE2-4FB7-9226-339ABDCF13D3", + 379, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2005-12-30T00:00:00Z", + "14 20 25 40 44", + "37", + null + ], + [ + 380, + "29E99521-1745-4BEA-8379-32E8A3B4EB71", + 380, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-03T00:00:00Z", + "15 19 20 32 38", + "21", + null + ], + [ + 381, + "23A4CE2F-D83A-4A90-9099-B224EDFCBD09", + 381, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-06T00:00:00Z", + "08 11 28 37 53", + "12", + null + ], + [ + 382, + "0BDE11E7-43EB-45A4-A01C-D8E922694253", + 382, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-10T00:00:00Z", + "07 27 32 37 38", + "30", + null + ], + [ + 383, + "167D5629-9E1C-4611-B2AE-2315FA48DCE5", + 383, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-13T00:00:00Z", + "05 21 27 44 53", + "36", + null + ], + [ + 384, + "0CA5B072-5559-4DA7-854A-560FAB3A1F9A", + 384, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-17T00:00:00Z", + "24 32 37 39 40", + "44", + null + ], + [ + 385, + "0359B182-D50B-48FF-A09F-D183DFD79088", + 385, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-20T00:00:00Z", + "18 22 28 44 53", + "46", + null + ], + [ + 386, + "D67E15A1-07AA-4C5F-83D3-E48B6CD1036C", + 386, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-24T00:00:00Z", + "31 34 36 51 55", + "04", + null + ], + [ + 387, + "CBE69F65-752B-4F95-A6E0-3D352BD3D73F", + 387, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-27T00:00:00Z", + "02 07 08 18 29", + "46", + null + ], + [ + 388, + "D9F7E97F-227D-443B-8981-FA36E63E6BE4", + 388, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-01-31T00:00:00Z", + "01 35 53 54 56", + "44", + null + ], + [ + 389, + "1064AE8D-A39B-4902-B11F-DA839EE81966", + 389, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-03T00:00:00Z", + "29 31 32 41 52", + "42", + null + ], + [ + 390, + "5C5F012B-1868-4006-BDF1-0C77C004B068", + 390, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-07T00:00:00Z", + "02 16 25 30 48", + "26", + null + ], + [ + 391, + "C8BCF21E-FA5E-46D6-9D6D-47E33673FD84", + 391, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-10T00:00:00Z", + "24 39 40 43 46", + "02", + null + ], + [ + 392, + "7B16B91E-5DAD-429E-B56A-308A7CC4F3C2", + 392, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-14T00:00:00Z", + "27 36 43 49 54", + "33", + null + ], + [ + 393, + "2C55BB3E-91D2-4E1A-90F9-99DBF303C292", + 393, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-17T00:00:00Z", + "16 25 31 43 46", + "28", + null + ], + [ + 394, + "DFF595AC-6BA2-400E-AFEA-684B14DB0ED7", + 394, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-21T00:00:00Z", + "14 23 27 36 45", + "36", + null + ], + [ + 395, + "D26EBE63-5EF4-428D-A3B9-E899335A7BF8", + 395, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-24T00:00:00Z", + "03 05 12 16 34", + "27", + null + ], + [ + 396, + "B75EBDD7-F67B-43ED-A426-204C3005ACBB", + 396, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-02-28T00:00:00Z", + "02 04 35 36 48", + "22", + null + ], + [ + 397, + "813AA2A0-653B-4DEA-95BC-842A99C81DE7", + 397, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-03T00:00:00Z", + "25 29 38 39 46", + "04", + null + ], + [ + 398, + "527704D6-2E02-457B-8149-F47FC0C8EB5E", + 398, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-07T00:00:00Z", + "15 27 36 38 42", + "32", + null + ], + [ + 399, + "2A55196C-4775-443A-B52F-48221944909B", + 399, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-10T00:00:00Z", + "04 17 18 51 54", + "31", + null + ], + [ + 400, + "DB2E7BA4-1A59-4A27-969E-2177D00567A7", + 400, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-14T00:00:00Z", + "27 28 30 42 50", + "22", + null + ], + [ + 401, + "7D7FB09E-BFED-4940-BE40-800C9B8E72DA", + 401, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-17T00:00:00Z", + "08 11 23 48 52", + "05", + null + ], + [ + 402, + "3CE93466-1F2F-4464-AD81-EA76817D9D1E", + 402, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-21T00:00:00Z", + "04 16 17 28 31", + "08", + null + ], + [ + 403, + "0A400896-D7C6-4572-96D9-81D24A122EA5", + 403, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-24T00:00:00Z", + "01 02 17 47 49", + "19", + null + ], + [ + 404, + "94CA0CC7-8204-4018-B709-397559907294", + 404, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-28T00:00:00Z", + "14 18 35 39 49", + "14", + null + ], + [ + 405, + "F745FFDD-883A-4C3D-9360-71F3A83E00FD", + 405, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-03-31T00:00:00Z", + "04 07 19 50 52", + "15", + null + ], + [ + 406, + "29EAB288-7556-4FCF-8189-080D1B2A59C0", + 406, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-04T00:00:00Z", + "09 25 48 51 56", + "07", + null + ], + [ + 407, + "CD488BBE-ACB3-40B0-BB7E-271B098F29DA", + 407, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-07T00:00:00Z", + "01 18 31 46 52", + "37", + null + ], + [ + 408, + "1DA1A60A-B1C2-426E-8852-9D39DBAEA790", + 408, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-11T00:00:00Z", + "02 12 45 46 56", + "20", + null + ], + [ + 409, + "93D317B3-E6EC-42D8-81AF-F2647E15F1C5", + 409, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-14T00:00:00Z", + "08 10 18 29 33", + "10", + null + ], + [ + 410, + "BA283EA9-2AD9-4E97-BB8A-3AC557F746DA", + 410, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-18T00:00:00Z", + "13 14 25 34 50", + "06", + null + ], + [ + 411, + "F3E9328B-F020-4C2E-AA17-08D20F513104", + 411, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-21T00:00:00Z", + "02 04 07 27 41", + "04", + null + ], + [ + 412, + "40BCF77C-5836-4312-A4DB-B307424B6DDE", + 412, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-25T00:00:00Z", + "01 20 32 37 39", + "09", + null + ], + [ + 413, + "25AEE37E-66F3-4507-86CB-1A787D01CD22", + 413, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-04-28T00:00:00Z", + "16 29 32 36 55", + "12", + null + ], + [ + 414, + "0D65468E-A001-4953-B9D7-3673D895BA94", + 414, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-02T00:00:00Z", + "07 11 22 27 31", + "33", + null + ], + [ + 415, + "3E43C068-9C2A-4A98-BD64-67B25F5385E9", + 415, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-05T00:00:00Z", + "08 20 39 53 55", + "10", + null + ], + [ + 416, + "196933EB-DC89-4F74-9489-4ADB3F0CB2D1", + 416, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-09T00:00:00Z", + "07 15 24 43 44", + "22", + null + ], + [ + 417, + "88B1ECC7-7F6D-46B3-B60A-8B2FE334AC29", + 417, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-12T00:00:00Z", + "06 36 39 45 52", + "45", + null + ], + [ + 418, + "69578B1A-F682-478A-B16F-786D601FB0D1", + 418, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-16T00:00:00Z", + "07 24 40 48 50", + "15", + null + ], + [ + 419, + "BA8F27F9-D6C8-4965-AFC6-C307D9377569", + 419, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-19T00:00:00Z", + "05 12 31 51 56", + "01", + null + ], + [ + 420, + "FDCA3825-57D6-4B86-8BFB-65FF69D2F961", + 420, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-23T00:00:00Z", + "17 21 28 48 54", + "01", + null + ], + [ + 421, + "DD8D9CD4-0283-4839-87A0-D018E4E994AE", + 421, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-26T00:00:00Z", + "12 14 20 47 48", + "24", + null + ], + [ + 422, + "287A016B-D049-48B5-AA90-BD3215D46D66", + 422, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-05-30T00:00:00Z", + "02 13 28 34 45", + "36", + null + ], + [ + 423, + "8FF174E9-FC60-48BE-832B-F1C2F283EC7D", + 423, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-02T00:00:00Z", + "03 10 18 36 38", + "41", + null + ], + [ + 424, + "74BD27FB-1F58-4935-9B0F-201B7394009D", + 424, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-06T00:00:00Z", + "05 29 35 52 53", + "09", + null + ], + [ + 425, + "9E40B131-700A-4BF5-924D-372AA99C2EEC", + 425, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-09T00:00:00Z", + "08 17 18 26 47", + "37", + null + ], + [ + 426, + "91BC5C38-BEFD-450E-B343-CF9C22ED4D37", + 426, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-13T00:00:00Z", + "01 20 23 24 33", + "29", + null + ], + [ + 427, + "26FA79C8-F2D2-4D0E-B2B8-592180AD8EA6", + 427, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-16T00:00:00Z", + "27 30 36 38 45", + "13", + null + ], + [ + 428, + "4C517676-2FE5-4574-8D14-60D2A7A470EA", + 428, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-20T00:00:00Z", + "11 21 37 53 54", + "12", + null + ], + [ + 429, + "137CCAD7-CCDD-47CF-8526-99BF3D6E13B6", + 429, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-23T00:00:00Z", + "13 17 24 34 56", + "24", + null + ], + [ + 430, + "3172D8F0-00D6-41EC-A33C-39DFACD85C54", + 430, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-27T00:00:00Z", + "02 14 20 29 44", + "32", + null + ], + [ + 431, + "721F7AD5-4110-4BA1-A481-4B872481540C", + 431, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-06-30T00:00:00Z", + "20 40 46 48 54", + "27", + null + ], + [ + 432, + "A3BCAF71-6B04-46AB-9DAF-C6F2AFCDDB22", + 432, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-04T00:00:00Z", + "09 15 31 42 45", + "41", + null + ], + [ + 433, + "3F716DED-DCC8-4F23-8654-A4AA0CE1F7BB", + 433, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-07T00:00:00Z", + "07 15 27 46 56", + "39", + null + ], + [ + 434, + "69D46A31-8B5E-46F0-BCFC-64804619BB0D", + 434, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-11T00:00:00Z", + "05 14 34 36 52", + "42", + null + ], + [ + 435, + "B0FC844B-8408-4DE9-8B9D-036CEA4A52D6", + 435, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-14T00:00:00Z", + "13 25 26 28 56", + "39", + null + ], + [ + 436, + "B9632DEA-2612-48E7-BFFF-59CCF6D7B195", + 436, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-18T00:00:00Z", + "12 13 29 49 52", + "20", + null + ], + [ + 437, + "AA05FDD3-F33B-445C-81D0-417531FFCAEE", + 437, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-21T00:00:00Z", + "18 26 35 36 43", + "24", + null + ], + [ + 438, + "B95A74B3-8357-48CA-81A6-08378A45C791", + 438, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-25T00:00:00Z", + "07 21 24 41 51", + "10", + null + ], + [ + 439, + "000D3A35-CA16-49E7-9989-E533E90F9B86", + 439, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-07-28T00:00:00Z", + "02 13 23 32 35", + "04", + null + ], + [ + 440, + "8BE39A1F-6479-4904-94C5-17761E012833", + 440, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-01T00:00:00Z", + "14 29 32 43 49", + "14", + null + ], + [ + 441, + "5D1B112D-E76B-4363-84E3-8F30AB59A225", + 441, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-04T00:00:00Z", + "02 24 31 50 55", + "44", + null + ], + [ + 442, + "FF4C81A1-0886-492A-A7E6-7E811B7618BE", + 442, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-08T00:00:00Z", + "01 05 13 18 33", + "30", + null + ], + [ + 443, + "6914B454-3487-4CF9-A7B3-E71B73DFC240", + 443, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-11T00:00:00Z", + "14 16 38 40 49", + "29", + null + ], + [ + 444, + "FD7B124A-D7D9-4769-8293-EE137100046F", + 444, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-15T00:00:00Z", + "10 12 22 44 48", + "16", + null + ], + [ + 445, + "1310D87A-CE78-4DEF-8C82-7D5C4F107A78", + 445, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-18T00:00:00Z", + "05 12 13 46 50", + "10", + null + ], + [ + 446, + "64AF74E8-B273-406F-A65B-21FF45A6EE97", + 446, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-22T00:00:00Z", + "03 04 05 07 36", + "16", + null + ], + [ + 447, + "FD99C149-C6DF-4716-9303-6CAE04DBC69B", + 447, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-25T00:00:00Z", + "17 24 35 46 54", + "33", + null + ], + [ + 448, + "4828E912-24A4-4EE2-A1EC-F4DD9C4D34F4", + 448, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-08-29T00:00:00Z", + "15 25 37 38 52", + "04", + null + ], + [ + 449, + "876BD770-0F17-4A55-9D1D-859ED0E71E43", + 449, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-01T00:00:00Z", + "05 06 51 53 55", + "12", + null + ], + [ + 450, + "3B501C09-05A2-4D12-988F-89CB2F762C24", + 450, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-05T00:00:00Z", + "01 32 36 42 53", + "04", + null + ], + [ + 451, + "81E6F31E-DF5C-43F6-A728-05585313E815", + 451, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-08T00:00:00Z", + "09 17 34 52 53", + "02", + null + ], + [ + 452, + "6EA79B46-5FC5-4A69-9233-944BAD07ADD7", + 452, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-12T00:00:00Z", + "03 16 25 30 44", + "42", + null + ], + [ + 453, + "009A90F0-5559-4268-987F-F6B82ECE62E8", + 453, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-15T00:00:00Z", + "06 26 33 39 55", + "01", + null + ], + [ + 454, + "E4BE828E-96E8-49C9-8CD3-22D163F8CA95", + 454, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-19T00:00:00Z", + "02 19 44 45 56", + "43", + null + ], + [ + 455, + "64115699-83B2-4A2F-AFCD-DB780FBF6EA4", + 455, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-22T00:00:00Z", + "07 12 17 22 43", + "16", + null + ], + [ + 456, + "F292063C-3138-4F0F-89CB-46D26C3A0458", + 456, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-26T00:00:00Z", + "03 06 38 42 45", + "30", + null + ], + [ + 457, + "012D91E0-729E-4072-B587-0BE7EAE01E69", + 457, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-09-29T00:00:00Z", + "03 25 43 45 55", + "40", + null + ], + [ + 458, + "6118DFB2-98F1-4083-917F-BEAB59C88D79", + 458, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-03T00:00:00Z", + "06 19 32 33 40", + "39", + null + ], + [ + 459, + "FEC3AA53-F3BC-4C7E-BFFD-094D134652ED", + 459, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-06T00:00:00Z", + "01 11 20 21 46", + "18", + null + ], + [ + 460, + "F59A1C13-3CA5-494D-92DE-A0D739B44578", + 460, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-10T00:00:00Z", + "14 30 35 40 43", + "02", + null + ], + [ + 461, + "261C39D5-E5FD-4454-A417-242D7D090B55", + 461, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-13T00:00:00Z", + "24 27 42 47 50", + "08", + null + ], + [ + 462, + "B36A2C2B-9501-4AF9-9754-8CE90B5BB31D", + 462, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-17T00:00:00Z", + "06 18 20 28 38", + "37", + null + ], + [ + 463, + "A7753123-848A-4066-A8AA-074FED6A5805", + 463, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-20T00:00:00Z", + "09 13 23 29 54", + "34", + null + ], + [ + 464, + "92DBCCC3-793A-427F-98BA-BBFECD7D078F", + 464, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-24T00:00:00Z", + "05 25 41 48 51", + "35", + null + ], + [ + 465, + "C5C9129D-0DDD-493C-BF76-FA9FF1B6918E", + 465, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-27T00:00:00Z", + "15 22 26 30 32", + "31", + null + ], + [ + 466, + "57CBB0CC-1645-46DB-9309-CC7BADDA9930", + 466, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-10-31T00:00:00Z", + "05 34 40 45 46", + "21", + null + ], + [ + 467, + "E35554AE-5653-4D27-949A-AEC4E3F061C9", + 467, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-03T00:00:00Z", + "08 10 22 25 55", + "22", + null + ], + [ + 468, + "2BEDBC19-AD7E-4DB0-806E-DFC3AC9695E5", + 468, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-07T00:00:00Z", + "13 22 33 51 52", + "42", + null + ], + [ + 469, + "A314EFBF-2B15-4FE9-B159-6AFAFE253953", + 469, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-10T00:00:00Z", + "11 42 52 53 55", + "28", + null + ], + [ + 470, + "3FE5905D-6A77-4DA2-BD41-97A8C35EA4A1", + 470, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-14T00:00:00Z", + "09 20 24 25 36", + "23", + null + ], + [ + 471, + "659F5995-2816-4F6D-B416-CA6202070B2F", + 471, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-17T00:00:00Z", + "05 19 25 30 50", + "42", + null + ], + [ + 472, + "596964AA-A8EC-4EF1-ABE1-88CEB210AC0F", + 472, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-21T00:00:00Z", + "07 13 20 42 47", + "09", + null + ], + [ + 473, + "65E180A1-4FDA-45E5-8527-D9CB3B9E06E9", + 473, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-24T00:00:00Z", + "14 35 40 47 48", + "35", + null + ], + [ + 474, + "5C995EB5-EDEA-4321-A9C3-56800D99F0BB", + 474, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-11-28T00:00:00Z", + "07 14 24 41 56", + "07", + null + ], + [ + 475, + "D130CD7B-53CD-472A-96DD-4D212DA0A53C", + 475, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-01T00:00:00Z", + "16 22 23 37 53", + "35", + null + ], + [ + 476, + "12FF9A05-37ED-4075-9439-04420AB4FCAB", + 476, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-05T00:00:00Z", + "06 09 13 43 46", + "45", + null + ], + [ + 477, + "2B26456D-4358-48A2-9B1B-DAEF68AB717B", + 477, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-08T00:00:00Z", + "01 15 29 32 45", + "08", + null + ], + [ + 478, + "1E3EDF59-31DC-4911-BB35-7D976DD611A9", + 478, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-12T00:00:00Z", + "20 30 31 35 49", + "23", + null + ], + [ + 479, + "C61F4D38-2EDD-4B77-9E83-2D02D4832CF7", + 479, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-15T00:00:00Z", + "06 07 17 28 40", + "39", + null + ], + [ + 480, + "E396FD08-5E4E-4150-BF25-753BF3B5338A", + 480, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-19T00:00:00Z", + "09 32 37 42 48", + "07", + null + ], + [ + 481, + "63BBEEBB-8051-4F72-AF25-8082D26CE558", + 481, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-22T00:00:00Z", + "05 12 15 25 34", + "43", + null + ], + [ + 482, + "0BDAA512-21EC-4665-8093-EF7813E19536", + 482, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-26T00:00:00Z", + "07 12 25 44 53", + "03", + null + ], + [ + 483, + "A2C16873-A6C5-4DD5-BED8-0774D4C51A6E", + 483, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2006-12-29T00:00:00Z", + "03 04 10 39 50", + "29", + null + ], + [ + 484, + "80DFE370-F29E-4FC6-ADD9-D2E1C6F285DF", + 484, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-02T00:00:00Z", + "09 10 38 51 53", + "01", + null + ], + [ + 485, + "1F4F9085-9D5D-4154-A7C9-07CC14B1360F", + 485, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-05T00:00:00Z", + "02 12 44 46 51", + "06", + null + ], + [ + 486, + "1C804255-DD48-459F-80B2-9A2A51F000E2", + 486, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-09T00:00:00Z", + "07 11 26 38 54", + "13", + null + ], + [ + 487, + "F2168D7F-692D-49E8-9BBD-9BAF919A429C", + 487, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-12T00:00:00Z", + "12 14 26 40 42", + "22", + null + ], + [ + 488, + "82A04EF2-AFDB-43AB-9AD5-35B5A52B0C7C", + 488, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-16T00:00:00Z", + "04 08 15 33 52", + "10", + null + ], + [ + 489, + "87CD8B58-A34F-447F-B738-338FAEA4ADA6", + 489, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-19T00:00:00Z", + "04 28 30 31 35", + "17", + null + ], + [ + 490, + "DFC10A63-3A94-4758-B7AE-72783F703352", + 490, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-23T00:00:00Z", + "03 05 15 26 53", + "35", + null + ], + [ + 491, + "A70BB32D-39D8-4140-8388-8FA026770676", + 491, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-26T00:00:00Z", + "16 17 36 49 54", + "14", + null + ], + [ + 492, + "63210A51-5D26-4FC2-BEFB-C39A41B76188", + 492, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-01-30T00:00:00Z", + "14 18 44 52 56", + "25", + null + ], + [ + 493, + "357413EB-414B-45C1-BE01-6C7811EFD331", + 493, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-02T00:00:00Z", + "22 33 35 40 53", + "15", + null + ], + [ + 494, + "B0C7B36A-3BC6-4A2D-B61B-CF6D59A2DE5D", + 494, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-06T00:00:00Z", + "16 21 35 36 46", + "38", + null + ], + [ + 495, + "44CD2B3C-DD2A-497D-9878-F4B724DF0C4F", + 495, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-09T00:00:00Z", + "32 39 46 48 49", + "41", + null + ], + [ + 496, + "7AE39468-C494-4058-BA75-4DC65DD0B14C", + 496, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-13T00:00:00Z", + "03 09 24 29 41", + "41", + null + ], + [ + 497, + "87D2E024-815A-486D-854E-3AE38F88E25B", + 497, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-16T00:00:00Z", + "17 35 40 46 48", + "41", + null + ], + [ + 498, + "29043663-7DA3-4E24-B131-FFD830CB4559", + 498, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-20T00:00:00Z", + "01 09 26 46 51", + "11", + null + ], + [ + 499, + "F1966050-1B54-4E51-BA1D-01D4885FF55A", + 499, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-23T00:00:00Z", + "03 18 21 38 50", + "43", + null + ], + [ + 500, + "CDC0E58D-A787-443D-B091-4C7B526B428E", + 500, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-02-27T00:00:00Z", + "18 31 44 45 48", + "18", + null + ], + [ + 501, + "027B2C00-9225-4D2C-BD32-40D24F18857C", + 501, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-02T00:00:00Z", + "14 21 33 35 51", + "43", + null + ], + [ + 502, + "3CCD3436-51C5-4009-8F83-0B6E1A2D9621", + 502, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-06T00:00:00Z", + "16 22 29 39 42", + "20", + null + ], + [ + 503, + "7EA1C45C-B586-4EE4-B220-2148621ABDF8", + 503, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-09T00:00:00Z", + "10 13 25 42 43", + "30", + null + ], + [ + 504, + "A328A035-D9CF-4A90-95F9-9E2B40EBA016", + 504, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-13T00:00:00Z", + "07 11 16 38 49", + "35", + null + ], + [ + 505, + "33DCB90F-A257-49AE-9BB5-C856E3519522", + 505, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-16T00:00:00Z", + "17 25 36 40 43", + "09", + null + ], + [ + 506, + "21F3B240-0B45-4F71-9511-B94C977B4A21", + 506, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-20T00:00:00Z", + "07 21 46 49 55", + "15", + null + ], + [ + 507, + "11C3082B-C804-4EB8-9B39-67548771671E", + 507, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-23T00:00:00Z", + "18 21 35 51 53", + "36", + null + ], + [ + 508, + "32E540A6-D425-404E-B2AD-0FEEC35D2F91", + 508, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-27T00:00:00Z", + "18 25 34 35 42", + "06", + null + ], + [ + 509, + "E6A20F49-B5F1-472B-BB7D-B06DD124AEFA", + 509, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-03-30T00:00:00Z", + "15 23 37 48 53", + "22", + null + ], + [ + 510, + "625A06C6-8963-4251-A51B-3229701ED972", + 510, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-03T00:00:00Z", + "16 26 33 34 46", + "38", + null + ], + [ + 511, + "CCDC57D2-0595-410A-8F16-5658A0715D7C", + 511, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-06T00:00:00Z", + "24 32 34 36 39", + "06", + null + ], + [ + 512, + "533647E4-C13D-4E9B-BAD2-3A3884B4BBC1", + 512, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-10T00:00:00Z", + "07 15 16 19 28", + "10", + null + ], + [ + 513, + "00A3835B-5630-4CE3-884E-8A721832B485", + 513, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-13T00:00:00Z", + "11 14 21 25 26", + "33", + null + ], + [ + 514, + "B05BDA43-8F9E-4780-A687-31592ADF193C", + 514, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-17T00:00:00Z", + "01 04 11 31 47", + "37", + null + ], + [ + 515, + "B0D1A237-A2D2-49DB-942F-04CF6403DDAF", + 515, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-20T00:00:00Z", + "01 09 10 23 53", + "40", + null + ], + [ + 516, + "CF0C9918-32B2-43E0-B1AA-BC8836DD8AAF", + 516, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-24T00:00:00Z", + "08 10 35 36 43", + "14", + null + ], + [ + 517, + "4860C387-45D4-43C8-9513-AA13684C6E55", + 517, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-04-27T00:00:00Z", + "05 07 26 38 56", + "15", + null + ], + [ + 518, + "8BBFFBDD-860A-46F4-9E37-899211A77BDE", + 518, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-01T00:00:00Z", + "11 16 31 52 53", + "42", + null + ], + [ + 519, + "9AA8796F-0E60-41D3-BEA8-DC65B72C0F9F", + 519, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-04T00:00:00Z", + "04 09 20 45 55", + "34", + null + ], + [ + 520, + "327324DA-C32B-4FC1-A2C8-83442FC0B4DC", + 520, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-08T00:00:00Z", + "16 24 41 43 54", + "36", + null + ], + [ + 521, + "590CB81B-44B8-4275-BCE8-18C4D8F912BF", + 521, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-11T00:00:00Z", + "28 30 33 48 54", + "25", + null + ], + [ + 522, + "CB538DA0-BE56-4F97-8806-353E9E13934C", + 522, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-15T00:00:00Z", + "06 13 42 46 56", + "42", + null + ], + [ + 523, + "71BCFD52-BC6E-4E35-ACA1-8F10909971D4", + 523, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-18T00:00:00Z", + "13 23 24 30 44", + "05", + null + ], + [ + 524, + "919DB6FB-31C9-4682-878E-13CA05A4655B", + 524, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-22T00:00:00Z", + "02 07 11 22 36", + "35", + null + ], + [ + 525, + "305E9588-E64D-4C2D-A4EF-E5B78518793B", + 525, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-25T00:00:00Z", + "10 14 22 42 43", + "01", + null + ], + [ + 526, + "4719B10B-AD10-4D50-8D46-A0CAE5F605C8", + 526, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-05-29T00:00:00Z", + "02 24 44 51 54", + "07", + null + ], + [ + 527, + "1A71051C-3A19-4D8C-9385-479010DB22F9", + 527, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-01T00:00:00Z", + "12 19 29 32 48", + "09", + null + ], + [ + 528, + "F9374DC6-B1DD-46B1-85FC-D5CB57642F63", + 528, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-05T00:00:00Z", + "27 35 38 49 56", + "15", + null + ], + [ + 529, + "D7CA0C49-B9CB-4112-B9EB-7F8FCFAB6D3D", + 529, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-08T00:00:00Z", + "06 26 29 31 39", + "31", + null + ], + [ + 530, + "0227FE28-D804-4BD3-A030-4BB9FE984784", + 530, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-12T00:00:00Z", + "03 13 19 31 50", + "21", + null + ], + [ + 531, + "21A96721-FEC2-4209-A12E-58DEB0C25565", + 531, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-15T00:00:00Z", + "01 05 16 26 30", + "21", + null + ], + [ + 532, + "8B7CDDBD-DE8F-43C1-8432-4749207D9C90", + 532, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-19T00:00:00Z", + "05 16 31 49 54", + "19", + null + ], + [ + 533, + "40A021A2-FB3D-4F3E-8B75-53906F89BE63", + 533, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-22T00:00:00Z", + "11 14 21 24 31", + "23", + null + ], + [ + 534, + "219E423B-F4F8-4FED-8F15-DB0BAFF558B6", + 534, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-26T00:00:00Z", + "04 10 20 29 45", + "21", + null + ], + [ + 535, + "17E57B87-08C2-4C62-BDFD-23B8EA26B4D8", + 535, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-06-29T00:00:00Z", + "01 17 40 51 52", + "07", + null + ], + [ + 536, + "32A17E56-EBE7-4251-BD2A-D19BE4CB117D", + 536, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-03T00:00:00Z", + "21 35 37 39 40", + "35", + null + ], + [ + 537, + "E8DD110B-0D8B-408D-A8EA-7ACA299EA6C5", + 537, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-06T00:00:00Z", + "03 09 12 25 47", + "37", + null + ], + [ + 538, + "E251BA7F-0AFF-4C05-A888-BE5DB36870C8", + 538, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-10T00:00:00Z", + "19 24 30 34 56", + "19", + null + ], + [ + 539, + "8693C58E-FFB4-4391-89A4-CA39898C188B", + 539, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-13T00:00:00Z", + "07 39 41 48 53", + "21", + null + ], + [ + 540, + "FCA45A5C-8B1B-48AD-A423-9E6ACBD9FA39", + 540, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-17T00:00:00Z", + "16 30 38 46 51", + "05", + null + ], + [ + 541, + "6F819E39-2FC5-47B6-81BB-C07A9EE6AD78", + 541, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-20T00:00:00Z", + "06 13 30 41 52", + "26", + null + ], + [ + 542, + "935E5F56-B297-4BEF-AF4E-798BD16FB200", + 542, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-24T00:00:00Z", + "08 17 20 23 50", + "17", + null + ], + [ + 543, + "DCCBD8F4-950D-4DD4-8625-8CD371BF0537", + 543, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-27T00:00:00Z", + "07 12 35 54 55", + "02", + null + ], + [ + 544, + "C7946459-75F4-4873-B7A9-4B2D4117C172", + 544, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-07-31T00:00:00Z", + "05 18 37 39 43", + "42", + null + ], + [ + 545, + "5A5EC1A5-F598-49F8-B294-B0742BAB9FE8", + 545, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-03T00:00:00Z", + "16 29 42 46 51", + "40", + null + ], + [ + 546, + "733BBBEB-B041-4E3C-AC7F-B061D9FDC2E2", + 546, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-07T00:00:00Z", + "36 41 50 55 56", + "09", + null + ], + [ + 547, + "8CF32173-2825-4083-94EC-3CA62231EB32", + 547, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-10T00:00:00Z", + "10 20 32 33 54", + "39", + null + ], + [ + 548, + "71255C58-16DF-464C-9910-B7C5E9368B80", + 548, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-14T00:00:00Z", + "05 08 09 24 34", + "17", + null + ], + [ + 549, + "29B14293-5FF6-4A9B-8A6D-9F4979AC2A3C", + 549, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-17T00:00:00Z", + "02 08 33 38 53", + "12", + null + ], + [ + 550, + "DBCFD864-00A3-4C73-B98E-168D7C7A7298", + 550, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-21T00:00:00Z", + "08 38 54 55 56", + "02", + null + ], + [ + 551, + "71581616-86DC-43A6-8E97-EB71AC7EAF9E", + 551, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-24T00:00:00Z", + "04 21 46 51 53", + "05", + null + ], + [ + 552, + "395D50C8-FFDC-4EB7-9BED-D46B60EF4A4F", + 552, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-28T00:00:00Z", + "37 40 48 53 56", + "44", + null + ], + [ + 553, + "024142D8-A96F-48DB-A5CE-BD82D129A146", + 553, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-08-31T00:00:00Z", + "08 18 22 40 44", + "11", + null + ], + [ + 554, + "7C7DA9A9-8A93-4DEC-A838-25ADA4688FB0", + 554, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-04T00:00:00Z", + "03 06 11 42 46", + "38", + null + ], + [ + 555, + "0579315D-E2CF-49AF-885E-71B088019AF1", + 555, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-07T00:00:00Z", + "14 19 27 34 48", + "03", + null + ], + [ + 556, + "971171AF-EFBA-4484-A414-5B01B9452D5F", + 556, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-11T00:00:00Z", + "09 10 17 21 35", + "06", + null + ], + [ + 557, + "28285D15-4A1A-44D3-9333-8239592BDE99", + 557, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-14T00:00:00Z", + "05 09 12 33 40", + "27", + null + ], + [ + 558, + "94B57E37-496D-4389-ADE3-55BC6C5D2BC5", + 558, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-18T00:00:00Z", + "20 24 31 34 49", + "08", + null + ], + [ + 559, + "5BEA0A7E-308C-4AB5-9EB3-E7829A54DE9A", + 559, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-21T00:00:00Z", + "05 21 23 33 45", + "43", + null + ], + [ + 560, + "2E981127-7486-4C6B-A8B5-97AC12022114", + 560, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-25T00:00:00Z", + "02 19 23 47 54", + "16", + null + ], + [ + 561, + "5105617C-AB05-4AB1-8AF0-51695E69D2C2", + 561, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-09-28T00:00:00Z", + "04 13 20 25 33", + "42", + null + ], + [ + 562, + "2437D531-AB19-4459-A67A-121972794A47", + 562, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-02T00:00:00Z", + "28 37 40 43 44", + "20", + null + ], + [ + 563, + "27284339-0E47-4BA9-A613-AA77CDC172FB", + 563, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-05T00:00:00Z", + "10 19 37 40 48", + "01", + null + ], + [ + 564, + "E0DD475C-1A32-4FD7-931A-1ED646B58376", + 564, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-09T00:00:00Z", + "01 10 17 32 51", + "44", + null + ], + [ + 565, + "6EFE62AE-AE28-44F7-AA85-286B4D0C9282", + 565, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-12T00:00:00Z", + "21 26 34 44 54", + "23", + null + ], + [ + 566, + "D5D353C1-8580-4064-8E83-78A727163693", + 566, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-16T00:00:00Z", + "01 02 05 41 44", + "25", + null + ], + [ + 567, + "8A6A4478-06D9-4120-9D60-736EC2D928F4", + 567, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-19T00:00:00Z", + "05 15 18 23 46", + "14", + null + ], + [ + 568, + "89ED8174-0D4D-4DBB-BFA0-EEE2ED2A191A", + 568, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-23T00:00:00Z", + "02 07 45 52 53", + "18", + null + ], + [ + 569, + "A4FD154B-73D1-4BDB-ADE9-1DA2FC880D58", + 569, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-26T00:00:00Z", + "12 20 24 38 51", + "03", + null + ], + [ + 570, + "27BFB91C-1B21-42B2-B974-7BBF668A0B96", + 570, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-10-30T00:00:00Z", + "02 08 44 46 51", + "22", + null + ], + [ + 571, + "583F59AF-3EC3-4912-B2B2-456D72F114E0", + 571, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-02T00:00:00Z", + "01 03 34 49 52", + "19", + null + ], + [ + 572, + "5EF7A2A3-960B-42CA-8D65-8607614DF1CC", + 572, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-06T00:00:00Z", + "03 17 43 46 47", + "02", + null + ], + [ + 573, + "3847BF2B-6773-4D29-938F-3806665D4FC1", + 573, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-09T00:00:00Z", + "11 33 41 42 46", + "21", + null + ], + [ + 574, + "FA9EA266-45A8-42C8-8D47-1D8BEB542211", + 574, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-13T00:00:00Z", + "15 26 36 39 40", + "45", + null + ], + [ + 575, + "50D7079B-6127-44CC-A4E0-263E7D452B52", + 575, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-16T00:00:00Z", + "12 13 30 31 39", + "29", + null + ], + [ + 576, + "56852C92-2149-4F4A-A660-59F939102925", + 576, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-20T00:00:00Z", + "14 20 23 42 43", + "06", + null + ], + [ + 577, + "39B6B3A1-52EE-4AC4-9676-DC4AE52237E8", + 577, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-23T00:00:00Z", + "18 21 33 42 56", + "11", + null + ], + [ + 578, + "D4194C06-722A-4E27-8F44-3D0C22B6A3DF", + 578, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-27T00:00:00Z", + "09 10 26 29 39", + "10", + null + ], + [ + 579, + "3932D673-921C-49E3-9291-BE717E702397", + 579, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-11-30T00:00:00Z", + "05 06 12 26 51", + "07", + null + ], + [ + 580, + "85FB5051-629B-436F-A43D-4C016A1DF93E", + 580, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-04T00:00:00Z", + "16 27 30 45 53", + "43", + null + ], + [ + 581, + "CF8D92A3-D767-42DA-B2F7-C8E790ECB065", + 581, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-07T00:00:00Z", + "12 18 26 28 51", + "35", + null + ], + [ + 582, + "8114AD78-1E0C-4F9C-AADB-508EDF06E336", + 582, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-11T00:00:00Z", + "06 25 27 30 45", + "46", + null + ], + [ + 583, + "43ACA759-99D1-4D7A-9089-6E639ADDFEDE", + 583, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-14T00:00:00Z", + "04 07 12 17 30", + "44", + null + ], + [ + 584, + "F2CAB9C2-553C-488A-9E30-CFA7DC65F412", + 584, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-18T00:00:00Z", + "03 23 46 48 49", + "02", + null + ], + [ + 585, + "9B44D4A4-0F8E-4213-A25F-E6BD1069DF0F", + 585, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-21T00:00:00Z", + "14 19 20 43 53", + "07", + null + ], + [ + 586, + "3E2922D0-284D-4614-8272-F83BBA38DDF5", + 586, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2007-12-28T00:00:00Z", + "02 19 22 28 54", + "25", + null + ], + [ + 587, + "04551495-BED3-4C37-9648-2FFA8347B05B", + 587, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-01T00:00:00Z", + "13 16 25 30 54", + "11", + null + ], + [ + 588, + "43BA977B-D380-48A8-85D9-EAF2A7A3AFA0", + 588, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-04T00:00:00Z", + "24 31 39 40 56", + "32", + null + ], + [ + 589, + "BA466130-57DE-4D6D-9FCD-C95831A4200D", + 589, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-08T00:00:00Z", + "10 29 45 52 54", + "10", + null + ], + [ + 590, + "AFF26B6A-34B8-4F89-8A85-88ED3C831D30", + 590, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-11T00:00:00Z", + "22 36 42 45 55", + "42", + null + ], + [ + 591, + "5DD841B2-F85D-493D-AFA2-F8164983D88B", + 591, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-15T00:00:00Z", + "21 30 42 44 50", + "06", + null + ], + [ + 592, + "CE5E4BA5-75FA-45B6-8C3E-F6EE890F8BAD", + 592, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-18T00:00:00Z", + "12 22 33 43 44", + "15", + null + ], + [ + 593, + "54B02ECF-BAC1-4940-BF9D-6D1DDD8561BB", + 593, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-22T00:00:00Z", + "12 15 22 25 33", + "02", + null + ], + [ + 594, + "B59B30E0-5386-455D-94D1-2EFBC646D36C", + 594, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-25T00:00:00Z", + "05 12 22 38 56", + "22", + null + ], + [ + 595, + "F99E577B-F55E-45E1-93D2-5832E92A52B8", + 595, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-01-29T00:00:00Z", + "08 23 39 40 42", + "24", + null + ], + [ + 596, + "4B67172C-E66E-4497-AE02-779DFC91A478", + 596, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-01T00:00:00Z", + "03 14 30 44 56", + "05", + null + ], + [ + 597, + "E604D301-A1AB-4D1F-BC23-70A17775C9F7", + 597, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-05T00:00:00Z", + "04 05 17 40 51", + "38", + null + ], + [ + 598, + "7EE23997-BF93-4901-8DBE-C4E394C1D211", + 598, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-08T00:00:00Z", + "21 30 43 46 50", + "18", + null + ], + [ + 599, + "D44E343F-CBED-4A68-98BC-92A0B0BF5920", + 599, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-12T00:00:00Z", + "14 27 39 47 50", + "12", + null + ], + [ + 600, + "52AAF078-59D5-4833-BA90-49B772ECAD50", + 600, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-15T00:00:00Z", + "07 11 26 30 53", + "14", + null + ], + [ + 601, + "2331FF0B-08D0-44C4-87C2-4841BB08040C", + 601, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-19T00:00:00Z", + "01 38 42 55 56", + "34", + null + ], + [ + 602, + "8EFEACF5-1F4F-4F67-8299-A13BC7B83C97", + 602, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-22T00:00:00Z", + "07 12 13 19 22", + "10", + null + ], + [ + 603, + "2D979590-2BF1-4EA5-A0D2-810843EDD84A", + 603, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-26T00:00:00Z", + "09 12 30 36 55", + "15", + null + ], + [ + 604, + "EF8F8EF7-18A9-4416-9A40-8B537E58D37A", + 604, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-02-29T00:00:00Z", + "05 17 22 26 55", + "38", + null + ], + [ + 605, + "AFD6E03E-C539-47CB-9BE2-6AA2E7CACBDB", + 605, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-04T00:00:00Z", + "07 15 30 33 56", + "22", + null + ], + [ + 606, + "54BC1E13-8915-40A8-88DA-15614181D8C4", + 606, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-07T00:00:00Z", + "19 32 33 41 48", + "12", + null + ], + [ + 607, + "511B590A-2D57-4C79-8F52-35E42CC64ED5", + 607, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-11T00:00:00Z", + "04 13 35 41 47", + "44", + null + ], + [ + 608, + "D62F24D8-6136-41FB-A019-03C0E9CC9406", + 608, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-14T00:00:00Z", + "03 12 18 25 52", + "21", + null + ], + [ + 609, + "B9FA4CFD-CD64-44C2-95A9-2BD4D042A75F", + 609, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-18T00:00:00Z", + "13 15 20 25 44", + "37", + null + ], + [ + 610, + "EA5686F4-4CB3-4DFF-816A-C1D94A1B1F48", + 610, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-21T00:00:00Z", + "05 08 17 19 41", + "21", + null + ], + [ + 611, + "AC709B10-C196-4023-AB43-7E95A7CC950D", + 611, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-25T00:00:00Z", + "38 42 43 48 53", + "12", + null + ], + [ + 612, + "6DF05F03-4E2F-49A0-9413-01B84EEAD863", + 612, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-03-28T00:00:00Z", + "07 26 27 40 43", + "10", + null + ], + [ + 613, + "1A9F5D9F-4E82-4903-B7AF-E391E31213F2", + 613, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-01T00:00:00Z", + "04 17 26 46 56", + "25", + null + ], + [ + 614, + "CB9B12F8-FBAC-41F2-A914-AF6455F0FF01", + 614, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-04T00:00:00Z", + "03 05 40 45 49", + "17", + null + ], + [ + 615, + "C20A8974-D7CF-424B-A508-C18AA16EF0BF", + 615, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-08T00:00:00Z", + "08 09 31 37 44", + "38", + null + ], + [ + 616, + "DD901315-2325-4C18-8319-81B01B0DFE1D", + 616, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-11T00:00:00Z", + "14 18 27 31 42", + "07", + null + ], + [ + 617, + "7D3AC251-031A-4D46-B6E3-D57950F6CB58", + 617, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-15T00:00:00Z", + "12 13 27 48 50", + "30", + null + ], + [ + 618, + "72EDF49D-BC25-4A23-956A-57D27374E917", + 618, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-18T00:00:00Z", + "24 28 36 50 53", + "29", + null + ], + [ + 619, + "BBC81A36-EBE1-4963-99CF-0FF40F70EC1F", + 619, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-22T00:00:00Z", + "03 22 31 48 54", + "09", + null + ], + [ + 620, + "A7BFDD05-2042-47C7-B393-067E4B9008A5", + 620, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-25T00:00:00Z", + "19 32 37 45 52", + "41", + null + ], + [ + 621, + "D766A4DB-4E03-4DD3-9141-2DEACE174839", + 621, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-04-29T00:00:00Z", + "19 24 35 44 51", + "26", + null + ], + [ + 622, + "39338F15-1D3D-4B25-8E41-A47775643753", + 622, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-02T00:00:00Z", + "08 28 37 53 55", + "26", + null + ], + [ + 623, + "61E2B968-18EA-4661-97D8-1557EA46EF07", + 623, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-06T00:00:00Z", + "04 21 46 53 54", + "26", + null + ], + [ + 624, + "858831D9-54C7-4330-BDB5-5B034C4BE4E4", + 624, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-09T00:00:00Z", + "16 31 43 46 56", + "22", + null + ], + [ + 625, + "D0CEF627-5AF9-42F9-AA58-4686413929C9", + 625, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-13T00:00:00Z", + "20 24 27 31 47", + "15", + null + ], + [ + 626, + "9009BD57-C8CE-4668-9CE0-F5D59CA5F172", + 626, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-16T00:00:00Z", + "06 11 39 46 47", + "26", + null + ], + [ + 627, + "A991C2F5-559D-44FE-8C0D-9BCAA3E344A5", + 627, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-20T00:00:00Z", + "02 14 26 32 41", + "32", + null + ], + [ + 628, + "91E9434A-7FBF-444A-B4B1-613B961F2A48", + 628, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-23T00:00:00Z", + "04 08 11 22 30", + "04", + null + ], + [ + 629, + "DC5EED77-8143-4F86-97DE-13972F2B2AFC", + 629, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-27T00:00:00Z", + "14 24 32 45 49", + "17", + null + ], + [ + 630, + "97097C20-BC7D-43E1-AAC5-F48B2F638E45", + 630, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-05-30T00:00:00Z", + "39 40 47 53 55", + "32", + null + ], + [ + 631, + "1BF2908A-5A66-4E7D-9F48-A22B94C280F0", + 631, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-03T00:00:00Z", + "04 19 24 32 54", + "05", + null + ], + [ + 632, + "79E09164-E650-489E-9641-DC52D4203F50", + 632, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-06T00:00:00Z", + "08 09 43 44 54", + "27", + null + ], + [ + 633, + "F2AF63EE-E3A5-4D2C-90C7-0D4B0003792D", + 633, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-10T00:00:00Z", + "03 05 15 43 51", + "11", + null + ], + [ + 634, + "7A95EAC2-EB23-4F35-BB91-7B291DC85943", + 634, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-13T00:00:00Z", + "08 09 14 38 44", + "36", + null + ], + [ + 635, + "BA5F710C-0B05-4FEB-9DB9-DE4E80C23089", + 635, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-17T00:00:00Z", + "05 14 25 47 49", + "36", + null + ], + [ + 636, + "07ABF657-5309-4D77-9BE4-716F3E48BE4E", + 636, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-20T00:00:00Z", + "11 17 25 36 42", + "13", + null + ], + [ + 637, + "441E43A9-2BFE-4EDD-86A5-7D0237E40AD9", + 637, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-24T00:00:00Z", + "10 22 36 50 53", + "39", + null + ], + [ + 638, + "B7473E75-6067-4E58-B934-81512155CC22", + 638, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-06-27T00:00:00Z", + "08 14 22 39 50", + "44", + null + ], + [ + 639, + "E498C1F6-8191-4DCF-97D5-B4838C72B27E", + 639, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-01T00:00:00Z", + "01 22 33 43 52", + "36", + null + ], + [ + 640, + "E6F1EB36-9C3D-432B-955A-5A87B91CF56A", + 640, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-04T00:00:00Z", + "01 03 12 19 20", + "28", + null + ], + [ + 641, + "7B9F9687-FA7C-4C35-9CD0-C75C24F6B843", + 641, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-08T00:00:00Z", + "01 20 22 29 41", + "35", + null + ], + [ + 642, + "DF85FE52-BB4B-42DC-B762-FFE86C7287FF", + 642, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-11T00:00:00Z", + "05 14 16 39 51", + "34", + null + ], + [ + 643, + "C2952461-9560-42BF-89D7-A128C11664A2", + 643, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-15T00:00:00Z", + "19 24 34 45 51", + "40", + null + ], + [ + 644, + "61469DD6-B4E4-4BCC-90AB-A71BAC7567CE", + 644, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-18T00:00:00Z", + "17 29 36 53 55", + "26", + null + ], + [ + 645, + "536EA679-7D1A-4740-8B02-EE9C33B203E7", + 645, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-22T00:00:00Z", + "02 16 23 29 32", + "46", + null + ], + [ + 646, + "95937200-82F3-402E-8248-B8951D1C1873", + 646, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-25T00:00:00Z", + "02 16 19 35 52", + "17", + null + ], + [ + 647, + "05997811-B217-45CA-9EAB-3126E3C649CD", + 647, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-07-29T00:00:00Z", + "11 13 20 30 42", + "03", + null + ], + [ + 648, + "FAF32B79-7770-4454-B053-47F6965910B8", + 648, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-01T00:00:00Z", + "09 13 17 18 56", + "02", + null + ], + [ + 649, + "BB9F5AC4-4B54-4EFC-B40E-28A4ABD26D63", + 649, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-05T00:00:00Z", + "09 21 36 38 55", + "13", + null + ], + [ + 650, + "809C3172-9F6E-4E8A-9EB5-CC9D1EBD7FDB", + 650, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-08T00:00:00Z", + "11 17 28 32 50", + "33", + null + ], + [ + 651, + "04182DD5-998D-44E2-B594-64556A39C8CD", + 651, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-12T00:00:00Z", + "02 07 23 38 40", + "40", + null + ], + [ + 652, + "8381CACD-0581-40DE-9D78-1402384FAE15", + 652, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-15T00:00:00Z", + "08 23 29 30 53", + "07", + null + ], + [ + 653, + "1B4D963D-ADAB-4871-B192-4B985AC36F31", + 653, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-19T00:00:00Z", + "09 18 19 26 40", + "38", + null + ], + [ + 654, + "C4183FB9-A12F-4E51-8630-6D4C4FF6236E", + 654, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-22T00:00:00Z", + "12 13 15 41 42", + "37", + null + ], + [ + 655, + "B5863FA9-E005-4C28-BB32-9132851D9C19", + 655, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-26T00:00:00Z", + "06 16 24 34 36", + "30", + null + ], + [ + 656, + "3BF0DDAC-D674-4055-9A4B-DA9AC99E0D82", + 656, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-08-29T00:00:00Z", + "21 25 26 50 51", + "22", + null + ], + [ + 657, + "19B8A21B-A93F-42E5-B8A2-B65B17C03CBC", + 657, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-02T00:00:00Z", + "14 23 43 44 54", + "39", + null + ], + [ + 658, + "0B7BF62B-A20B-4B31-AD56-A24C98307C57", + 658, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-05T00:00:00Z", + "01 06 15 27 46", + "39", + null + ], + [ + 659, + "6292265B-0462-4FAE-A4BE-CF94C20DB96F", + 659, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-09T00:00:00Z", + "22 23 28 49 52", + "02", + null + ], + [ + 660, + "948DD599-9C55-40F8-89FD-8D67E835938C", + 660, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-12T00:00:00Z", + "01 12 14 25 35", + "38", + null + ], + [ + 661, + "EBAB9596-15F7-4E80-9AE5-B2614299CD35", + 661, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-16T00:00:00Z", + "13 24 39 51 52", + "44", + null + ], + [ + 662, + "32E7961A-6226-4037-9A77-D7B26D188DC2", + 662, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-19T00:00:00Z", + "02 09 41 48 51", + "37", + null + ], + [ + 663, + "EE6BA26A-7962-4738-AD11-1ABDF472E47D", + 663, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-23T00:00:00Z", + "09 32 34 43 52", + "04", + null + ], + [ + 664, + "67930A86-D27C-4F43-81D8-1B04573D642F", + 664, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-26T00:00:00Z", + "06 13 14 31 36", + "36", + null + ], + [ + 665, + "90B63F14-6644-42AF-9827-4DAE75D83F76", + 665, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-09-30T00:00:00Z", + "09 30 35 39 49", + "36", + null + ], + [ + 666, + "E4AB005C-DE82-4FF3-B929-59933A564E52", + 666, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-03T00:00:00Z", + "13 28 32 41 52", + "16", + null + ], + [ + 667, + "8306F542-EDF9-4ABE-ABEA-BE7FF13F5F45", + 667, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-07T00:00:00Z", + "02 25 35 38 42", + "34", + null + ], + [ + 668, + "E60DF50F-8CE6-4B60-AA78-F7BD1CB2E8E6", + 668, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-10T00:00:00Z", + "14 15 43 46 48", + "21", + null + ], + [ + 669, + "217D2DF3-97B0-48EF-9F35-01FCFB97B83F", + 669, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-14T00:00:00Z", + "14 35 41 42 51", + "23", + null + ], + [ + 670, + "DD45E22D-72A2-4052-838A-7E236925AFAB", + 670, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-17T00:00:00Z", + "07 15 27 28 31", + "35", + null + ], + [ + 671, + "FC5BB8FE-AFD6-4784-A950-25D21B85493F", + 671, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-21T00:00:00Z", + "16 19 39 42 44", + "38", + null + ], + [ + 672, + "0CD5FC5D-4989-496C-B575-11EAAAD6115C", + 672, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-24T00:00:00Z", + "05 33 34 47 52", + "18", + null + ], + [ + 673, + "3F9A2F2B-919D-4F31-B636-52862546E3BB", + 673, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-28T00:00:00Z", + "06 39 45 46 48", + "36", + null + ], + [ + 674, + "E02FF34D-3A58-42C9-8722-0347598852F7", + 674, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-10-31T00:00:00Z", + "02 07 17 29 47", + "40", + null + ], + [ + 675, + "6DF2E2C0-A871-4AFE-9E12-738CBE7AF05D", + 675, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-04T00:00:00Z", + "10 21 23 41 55", + "09", + null + ], + [ + 676, + "7B508DB8-75A8-4C05-BB9A-63697C7A0A4D", + 676, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-07T00:00:00Z", + "14 24 32 43 44", + "21", + null + ], + [ + 677, + "808AB5CA-F5CA-47B7-8F73-1517D8892037", + 677, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-11T00:00:00Z", + "05 27 38 42 55", + "41", + null + ], + [ + 678, + "B0536821-95CC-4733-84C7-F4F052327A8E", + 678, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-14T00:00:00Z", + "03 18 19 30 34", + "03", + null + ], + [ + 679, + "74023E2B-EEB5-44BF-9694-3E044C8C83F5", + 679, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-18T00:00:00Z", + "10 15 22 52 53", + "12", + null + ], + [ + 680, + "4C086620-5B40-41D6-B9B4-F79479D5F2ED", + 680, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-21T00:00:00Z", + "01 22 52 53 56", + "45", + null + ], + [ + 681, + "57EEB3E2-33B7-4FF1-BB90-8A6005FA79DE", + 681, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-25T00:00:00Z", + "02 11 22 51 52", + "46", + null + ], + [ + 682, + "CBBEE8D1-B7C9-40B4-A622-D061805B9B7D", + 682, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-11-28T00:00:00Z", + "10 30 44 46 48", + "44", + null + ], + [ + 683, + "F5376D25-5DF8-42C3-B344-AA5CE2F413D7", + 683, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-02T00:00:00Z", + "02 17 22 32 51", + "35", + null + ], + [ + 684, + "52198556-DA62-4169-AA41-D92046DD93FD", + 684, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-05T00:00:00Z", + "21 27 46 52 55", + "14", + null + ], + [ + 685, + "6DDE7205-0EB7-46EB-8F9B-B2FF0B217AC8", + 685, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-09T00:00:00Z", + "11 12 26 31 33", + "27", + null + ], + [ + 686, + "2BE6965D-BF8A-4145-8C6B-094C377A8BEA", + 686, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-12T00:00:00Z", + "10 16 19 27 48", + "25", + null + ], + [ + 687, + "8483A370-5A9E-4C91-BC8B-AD11582907D3", + 687, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-16T00:00:00Z", + "10 14 16 29 40", + "06", + null + ], + [ + 688, + "EDBFF068-2C35-433F-882A-D56A37C36747", + 688, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-19T00:00:00Z", + "03 13 16 39 54", + "32", + null + ], + [ + 689, + "85088580-AC76-4A88-9A43-CA57062D3991", + 689, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-23T00:00:00Z", + "01 08 13 27 41", + "45", + null + ], + [ + 690, + "41BB763A-B7EE-4B77-B46C-35B2D4D11397", + 690, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-26T00:00:00Z", + "06 19 29 33 37", + "31", + null + ], + [ + 691, + "F45C1691-4DCA-4754-ACDC-370D4D1BD7C0", + 691, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2008-12-30T00:00:00Z", + "01 22 29 44 52", + "39", + null + ], + [ + 692, + "DA9A9104-C0DB-4306-BCE5-B825281DFA12", + 692, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-02T00:00:00Z", + "02 11 19 21 34", + "38", + null + ], + [ + 693, + "457BD885-F877-4984-B9EC-CB13469E7BF7", + 693, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-06T00:00:00Z", + "03 11 12 19 33", + "30", + null + ], + [ + 694, + "006D900C-426D-43BB-B1D7-2C7B407BC426", + 694, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-09T00:00:00Z", + "23 25 30 45 50", + "08", + null + ], + [ + 695, + "A4775431-5ADA-4A87-AE5F-C6E639F9E631", + 695, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-13T00:00:00Z", + "22 25 33 36 48", + "40", + null + ], + [ + 696, + "67534450-D8C3-40A5-8913-84D193109350", + 696, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-16T00:00:00Z", + "02 04 21 39 51", + "29", + null + ], + [ + 697, + "C93BDF71-0B5F-4EEE-BFF0-06559684E40B", + 697, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-20T00:00:00Z", + "01 09 10 35 46", + "09", + null + ], + [ + 698, + "87AE85FC-0B31-4036-8BB1-3EB6BFB12353", + 698, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-23T00:00:00Z", + "02 17 20 27 28", + "07", + null + ], + [ + 699, + "0C8FCC5D-F1AA-4F04-AE12-EBDCDD302550", + 699, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-27T00:00:00Z", + "03 11 12 14 21", + "25", + null + ], + [ + 700, + "4598C166-E066-430F-A34B-191133D82DC0", + 700, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-01-30T00:00:00Z", + "13 16 19 53 55", + "02", + null + ], + [ + 701, + "84952D50-FB23-41B8-B8B9-7C563FB0DEF3", + 701, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-03T00:00:00Z", + "04 15 29 43 56", + "29", + null + ], + [ + 702, + "4FBD061D-4178-478A-A9DA-0591952AF4A1", + 702, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-06T00:00:00Z", + "02 12 18 28 31", + "03", + null + ], + [ + 703, + "61079EAE-409B-4FA4-AF31-BD6290B4DECD", + 703, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-10T00:00:00Z", + "18 29 38 43 47", + "07", + null + ], + [ + 704, + "BC0C8E66-8F2B-4627-A61F-16476BE4D0D1", + 704, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-13T00:00:00Z", + "25 36 37 40 51", + "20", + null + ], + [ + 705, + "02D3567D-CDCA-4E4B-8558-805A7F344CA8", + 705, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-17T00:00:00Z", + "01 09 23 27 33", + "24", + null + ], + [ + 706, + "D5889D79-7B25-4EB4-B609-E985347A3E6D", + 706, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-20T00:00:00Z", + "21 28 41 45 55", + "24", + null + ], + [ + 707, + "DBD4B0BD-CCDC-4E1D-AEAC-7B1CFD1863CC", + 707, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-24T00:00:00Z", + "01 27 28 35 40", + "06", + null + ], + [ + 708, + "A4B1FE35-873D-46EA-890E-CA09F4A445A7", + 708, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-02-27T00:00:00Z", + "24 37 44 50 56", + "35", + null + ], + [ + 709, + "813AE8F3-A520-4B94-9830-51FC6CFAEE27", + 709, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-03T00:00:00Z", + "26 32 35 43 52", + "10", + null + ], + [ + 710, + "FC0C4C98-0E7B-42C7-9D18-9707EBD8BC8E", + 710, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-06T00:00:00Z", + "11 18 37 46 55", + "45", + null + ], + [ + 711, + "9A17DCEE-779A-4020-9CEC-8064B73B0EAC", + 711, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-10T00:00:00Z", + "02 27 31 39 40", + "23", + null + ], + [ + 712, + "C2055A92-0EA6-46BF-A085-D1B2F2FD9F87", + 712, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-13T00:00:00Z", + "10 12 26 46 50", + "23", + null + ], + [ + 713, + "471EB7B1-EC76-428C-B4C1-D4746EE3B5BD", + 713, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-17T00:00:00Z", + "09 15 24 28 31", + "17", + null + ], + [ + 714, + "AEC2FFB5-3CF4-4541-AF59-429BA4EA88ED", + 714, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-20T00:00:00Z", + "15 16 20 39 40", + "26", + null + ], + [ + 715, + "5D59F47E-FDB3-4D75-8726-A89B26E960EB", + 715, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-24T00:00:00Z", + "04 25 34 43 44", + "45", + null + ], + [ + 716, + "E3C8C9EC-2595-43D8-9220-801A471A0785", + 716, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-27T00:00:00Z", + "10 15 24 38 50", + "19", + null + ], + [ + 717, + "75F8683A-8CB5-4A64-B394-F3856113C734", + 717, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-03-31T00:00:00Z", + "14 39 47 48 53", + "29", + null + ], + [ + 718, + "1DFBD7FB-D346-47E3-8055-650E565084DB", + 718, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-03T00:00:00Z", + "16 22 38 39 48", + "42", + null + ], + [ + 719, + "F2228ABC-483D-4402-885C-07F9CA41D3FF", + 719, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-07T00:00:00Z", + "02 04 13 17 36", + "15", + null + ], + [ + 720, + "23C5D3A0-28C4-414A-AA41-56BB9FF9E4D6", + 720, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-10T00:00:00Z", + "18 25 36 42 51", + "22", + null + ], + [ + 721, + "7214BB77-B931-442E-8656-AF6388E58DA0", + 721, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-14T00:00:00Z", + "04 11 22 48 50", + "42", + null + ], + [ + 722, + "103C24D8-2F24-4B67-B25B-BE1E6CE96A85", + 722, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-17T00:00:00Z", + "05 13 26 35 45", + "32", + null + ], + [ + 723, + "74CD43FF-6C29-42F2-8492-1D9FD9BE1B96", + 723, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-21T00:00:00Z", + "05 24 37 47 52", + "06", + null + ], + [ + 724, + "0B0DCFE8-1FEF-437F-BD58-33EAEA95BBDE", + 724, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-24T00:00:00Z", + "09 20 21 48 49", + "07", + null + ], + [ + 725, + "21DCD08A-3F15-4065-A97B-85B46045F5D3", + 725, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-04-28T00:00:00Z", + "15 20 24 36 44", + "06", + null + ], + [ + 726, + "351EBC69-A427-4C20-B798-68E178E5088B", + 726, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-01T00:00:00Z", + "09 16 24 40 43", + "35", + null + ], + [ + 727, + "168B47E6-6EB9-4387-B9AB-FBEE6E70187B", + 727, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-05T00:00:00Z", + "05 23 38 39 54", + "03", + null + ], + [ + 728, + "D87CA568-F428-44DC-8E0D-938DAE764D2D", + 728, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-08T00:00:00Z", + "12 27 29 32 34", + "34", + null + ], + [ + 729, + "BE8F8E4C-87AC-419E-8B35-25B645F733A0", + 729, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-12T00:00:00Z", + "04 08 10 14 51", + "31", + null + ], + [ + 730, + "81151545-D0DE-4732-A845-747FD7B426A0", + 730, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-15T00:00:00Z", + "07 12 24 36 48", + "27", + null + ], + [ + 731, + "AFAB890B-9AE6-4DC4-9E2F-FBBDD5CAA71F", + 731, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-19T00:00:00Z", + "02 04 09 15 42", + "13", + null + ], + [ + 732, + "3FB0BBB5-9305-4AD1-A8EF-677EB14D739A", + 732, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-22T00:00:00Z", + "03 29 34 42 49", + "29", + null + ], + [ + 733, + "11EA5295-1010-4F48-9FA7-166D5CE49043", + 733, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-26T00:00:00Z", + "09 18 21 37 55", + "33", + null + ], + [ + 734, + "81049EB0-34A3-404C-805D-EC79155BD474", + 734, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-05-29T00:00:00Z", + "23 30 36 39 48", + "34", + null + ], + [ + 735, + "F22FA563-2C4C-49CD-A213-F3B0258DD2F7", + 735, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-02T00:00:00Z", + "09 13 26 30 35", + "33", + null + ], + [ + 736, + "339FAF34-DD23-4C2C-8FF1-11BC297110D5", + 736, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-05T00:00:00Z", + "05 20 38 41 52", + "20", + null + ], + [ + 737, + "572A228E-A2B7-4853-AC56-B51FA3E4E977", + 737, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-09T00:00:00Z", + "05 17 31 36 56", + "46", + null + ], + [ + 738, + "B1912705-910F-40B0-B26C-C080AE03A64E", + 738, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-12T00:00:00Z", + "06 11 20 32 44", + "38", + null + ], + [ + 739, + "18C01ED7-F086-462D-952C-3690822D9EB3", + 739, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-16T00:00:00Z", + "09 15 21 26 45", + "25", + null + ], + [ + 740, + "778E58D2-A4BF-4397-ACB4-CD45F4594E02", + 740, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-19T00:00:00Z", + "04 09 12 16 46", + "44", + null + ], + [ + 741, + "EBD03D4A-8D22-4069-BB9C-85B2905C1908", + 741, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-23T00:00:00Z", + "12 14 16 31 50", + "09", + null + ], + [ + 742, + "946BC592-27E8-4679-8A4F-D1ADE23BCAB2", + 742, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-26T00:00:00Z", + "11 15 17 29 46", + "16", + null + ], + [ + 743, + "37C1E7E8-D038-4632-8095-CF7C367AF16C", + 743, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-06-30T00:00:00Z", + "07 34 49 54 55", + "34", + null + ], + [ + 744, + "0CEAED99-4AF4-4C56-BDBE-2CD11790E752", + 744, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-03T00:00:00Z", + "05 06 07 11 25", + "31", + null + ], + [ + 745, + "56165FDF-EACB-4D44-8FD0-19188EBF9FDB", + 745, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-07T00:00:00Z", + "25 27 35 38 39", + "28", + null + ], + [ + 746, + "F75DCF35-BB8A-4E25-A08A-C70AED507E1B", + 746, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-10T00:00:00Z", + "05 10 26 27 28", + "04", + null + ], + [ + 747, + "A5AED3DC-82D1-47B2-AD84-3E4CFF492863", + 747, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-14T00:00:00Z", + "20 29 35 45 53", + "41", + null + ], + [ + 748, + "CBC7B3F7-A0FB-4B17-8FC9-B584A48ACE1A", + 748, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-17T00:00:00Z", + "08 17 40 47 50", + "13", + null + ], + [ + 749, + "3972E622-3A12-4459-A2F3-853C6E3DF528", + 749, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-21T00:00:00Z", + "03 08 21 50 52", + "02", + null + ], + [ + 750, + "36750E7C-756E-46DE-9C57-1CDB57C686AF", + 750, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-24T00:00:00Z", + "03 06 43 51 52", + "36", + null + ], + [ + 751, + "0ED2B295-A760-4BFF-A56B-A303E61A48C2", + 751, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-28T00:00:00Z", + "04 17 24 25 48", + "34", + null + ], + [ + 752, + "FC76F901-1F35-4951-9FB1-E2FF0688D0C5", + 752, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-07-31T00:00:00Z", + "17 35 44 52 56", + "22", + null + ], + [ + 753, + "7F2411E9-C4EE-4D90-94DF-387E3D33E14C", + 753, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-04T00:00:00Z", + "01 28 34 42 50", + "27", + null + ], + [ + 754, + "B19ED6DC-2FE3-4379-B92F-F4E04BD8B602", + 754, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-07T00:00:00Z", + "07 18 35 45 56", + "03", + null + ], + [ + 755, + "CAF2B068-BCB0-4E9E-B094-3C092814F3D6", + 755, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-11T00:00:00Z", + "06 12 15 32 42", + "40", + null + ], + [ + 756, + "BE14FCFA-6D56-4B87-9428-F036AF6A153A", + 756, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-14T00:00:00Z", + "08 22 25 33 35", + "46", + null + ], + [ + 757, + "9D7178FE-3F92-4B7C-A73B-30933BA111C6", + 757, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-18T00:00:00Z", + "04 05 26 37 56", + "25", + null + ], + [ + 758, + "DAD3C7AA-522B-4F6F-A217-6B18954EF1D4", + 758, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-21T00:00:00Z", + "09 38 44 48 49", + "13", + null + ], + [ + 759, + "AA1A3D6E-3344-435B-B813-971C58193477", + 759, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-25T00:00:00Z", + "03 12 19 22 40", + "02", + null + ], + [ + 760, + "F24708B7-2F8E-4551-908C-C221C7A9C5D3", + 760, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-08-28T00:00:00Z", + "01 17 31 37 54", + "31", + null + ], + [ + 761, + "7D46008B-19E9-4BA4-8E63-846F0F8F7C11", + 761, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-01T00:00:00Z", + "02 09 28 51 53", + "19", + null + ], + [ + 762, + "146376B5-76BF-492D-828D-3CA640DFDBDA", + 762, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-04T00:00:00Z", + "02 04 06 21 44", + "37", + null + ], + [ + 763, + "74CBE867-A0EA-4BDD-903C-CBCF649F0852", + 763, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-08T00:00:00Z", + "04 10 18 28 50", + "35", + null + ], + [ + 764, + "C5083416-19DA-4EB2-BB73-F106C6714BCD", + 764, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-11T00:00:00Z", + "16 27 48 49 54", + "02", + null + ], + [ + 765, + "54B77269-DF10-43D2-85AC-87310F635F40", + 765, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-15T00:00:00Z", + "29 30 32 35 41", + "39", + null + ], + [ + 766, + "9F3A9E56-B7C2-49BA-AC52-1A9845358AD1", + 766, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-18T00:00:00Z", + "18 27 31 36 52", + "33", + null + ], + [ + 767, + "83DD43D5-A17C-4BC0-A94B-CE5C98800671", + 767, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-22T00:00:00Z", + "26 29 33 39 46", + "24", + null + ], + [ + 768, + "E2289CDE-FE3A-4572-BDDF-7B796DDE0F48", + 768, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-25T00:00:00Z", + "07 27 42 49 52", + "19", + null + ], + [ + 769, + "6C158BB8-3C8D-4821-A36A-12D493870B1D", + 769, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-09-29T00:00:00Z", + "02 21 25 45 50", + "21", + null + ], + [ + 770, + "14EF87A6-B943-4168-A85C-92986474FE73", + 770, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-02T00:00:00Z", + "15 24 51 53 55", + "11", + null + ], + [ + 771, + "2940046E-0856-4C27-BDEC-0081153FE6D9", + 771, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-06T00:00:00Z", + "09 33 51 53 56", + "39", + null + ], + [ + 772, + "4B1ECB95-422B-4E5C-AE4A-A36CC7289AE2", + 772, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-09T00:00:00Z", + "03 14 21 24 51", + "14", + null + ], + [ + 773, + "917603BF-CE49-4D4C-B344-4F7BFB4A3000", + 773, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-13T00:00:00Z", + "17 31 34 45 51", + "24", + null + ], + [ + 774, + "C4B244A5-71AE-4737-8696-FAD69FCC4306", + 774, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-16T00:00:00Z", + "10 13 18 33 51", + "43", + null + ], + [ + 775, + "B09A6263-AE32-48A1-B27F-5261FF85BB0A", + 775, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-20T00:00:00Z", + "13 17 25 45 55", + "08", + null + ], + [ + 776, + "49AC2B38-0F01-4ECF-97F9-DFEE683496FB", + 776, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-23T00:00:00Z", + "27 45 48 54 56", + "02", + null + ], + [ + 777, + "8F5C36CD-13DA-482D-8D06-C70FAD47E5DD", + 777, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-27T00:00:00Z", + "07 13 37 46 51", + "02", + null + ], + [ + 778, + "EC9A3519-606B-4389-9A2E-39C962F5E2B4", + 778, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-10-30T00:00:00Z", + "04 15 17 29 38", + "20", + null + ], + [ + 779, + "167BFB3F-0E07-4C16-978E-FBE7FFD5B68B", + 779, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-03T00:00:00Z", + "05 18 23 31 38", + "20", + null + ], + [ + 780, + "E701E122-932C-47DB-91E4-8EDEC824EF6D", + 780, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-06T00:00:00Z", + "07 11 27 40 46", + "08", + null + ], + [ + 781, + "7DDD4033-B3ED-48A6-806C-8886C6A2BE5B", + 781, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-10T00:00:00Z", + "08 21 29 34 37", + "15", + null + ], + [ + 782, + "65739373-4856-4DEB-B8EB-D2A5867F6AF7", + 782, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-13T00:00:00Z", + "27 43 45 49 54", + "44", + null + ], + [ + 783, + "BD325C4F-DC06-4DE8-8AB0-B0CA898310D2", + 783, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-17T00:00:00Z", + "08 22 27 49 50", + "28", + null + ], + [ + 784, + "BA3F8A87-E1F8-4518-AFA7-6E6CB0094ADE", + 784, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-20T00:00:00Z", + "03 04 07 16 56", + "39", + null + ], + [ + 785, + "10601DE2-F74F-4A16-A5AE-D9B528F37947", + 785, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-24T00:00:00Z", + "10 11 35 37 50", + "12", + null + ], + [ + 786, + "028E0467-039A-4646-B805-419A7EA4215F", + 786, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-11-27T00:00:00Z", + "12 25 37 39 45", + "11", + null + ], + [ + 787, + "CCA3BDA4-4EA3-4847-B489-DA31CE612F46", + 787, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-01T00:00:00Z", + "17 30 39 52 53", + "21", + null + ], + [ + 788, + "5A4D2F95-05B7-45B0-AFC6-0C8671090078", + 788, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-04T00:00:00Z", + "04 33 41 51 56", + "38", + null + ], + [ + 789, + "1AFDE069-1C2C-4B11-ABF2-5D34C99F8009", + 789, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-08T00:00:00Z", + "20 23 28 30 46", + "29", + null + ], + [ + 790, + "C8688557-3C55-40B1-8547-F8F63EA978E2", + 790, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-11T00:00:00Z", + "02 21 27 34 44", + "45", + null + ], + [ + 791, + "170F03BB-4FA6-4012-9DEA-3F355327CB2D", + 791, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-15T00:00:00Z", + "27 31 32 36 47", + "35", + null + ], + [ + 792, + "A1C9B69C-F6E9-4F03-BD08-3612C8130DB2", + 792, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-18T00:00:00Z", + "10 20 30 44 49", + "24", + null + ], + [ + 793, + "2DF0DE5D-822C-4B1F-8189-150829710D6D", + 793, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-22T00:00:00Z", + "03 33 35 39 45", + "13", + null + ], + [ + 794, + "2BFF67A2-5627-45EB-9332-DFA144B11A4E", + 794, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2009-12-29T00:00:00Z", + "02 05 29 35 51", + "03", + null + ], + [ + 795, + "2A5CE53D-DC71-4E03-9BE0-75214C869310", + 795, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-01T00:00:00Z", + "06 08 27 40 41", + "21", + null + ], + [ + 796, + "E0C0761D-CDE8-4951-8FAD-1649611251D5", + 796, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-05T00:00:00Z", + "13 28 39 50 55", + "10", + null + ], + [ + 797, + "FC60EB92-6CC8-4E00-92ED-329B206F34BF", + 797, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-08T00:00:00Z", + "18 20 31 36 43", + "33", + null + ], + [ + 798, + "1395E5F5-EAD5-4A9E-8E30-3D4ED3180582", + 798, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-12T00:00:00Z", + "05 09 31 37 56", + "16", + null + ], + [ + 799, + "61176EE6-194E-4B7A-8289-641D6D73E30F", + 799, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-15T00:00:00Z", + "04 07 19 21 38", + "29", + null + ], + [ + 800, + "053F0AAB-3C80-4608-A15B-11EF823A97A0", + 800, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-19T00:00:00Z", + "04 05 34 38 41", + "18", + null + ], + [ + 801, + "11D64BB4-E070-4C24-8369-142791A0DB96", + 801, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-22T00:00:00Z", + "08 13 27 28 52", + "09", + null + ], + [ + 802, + "D8151C78-F265-4CBB-99A2-42E38293079D", + 802, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-26T00:00:00Z", + "07 08 38 39 48", + "22", + null + ], + [ + 803, + "0CCA6D18-2074-488C-A3D0-DA64DFFD8AA4", + 803, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-01-29T00:00:00Z", + "01 10 22 23 38", + "19", + null + ], + [ + 804, + "F5782C73-F67B-4BC7-88C1-D27461D9D2D3", + 804, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-02T00:00:00Z", + "06 07 26 27 49", + "09", + null + ], + [ + 805, + "31DB7363-8E05-4A5F-B44A-2084214F4376", + 805, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-05T00:00:00Z", + "10 20 45 51 53", + "41", + null + ], + [ + 806, + "F1F49235-006D-4983-8E66-C28093B9935C", + 806, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-09T00:00:00Z", + "02 17 20 26 48", + "12", + null + ], + [ + 807, + "1AF21D48-A038-4F94-AB71-EB64D7ADD2AC", + 807, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-12T00:00:00Z", + "14 16 17 33 47", + "23", + null + ], + [ + 808, + "3B55D6A9-90F8-4A0E-9231-AB28F15F994E", + 808, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-16T00:00:00Z", + "11 12 21 29 45", + "05", + null + ], + [ + 809, + "A119EC98-37A8-48EC-BE53-DEFE528ED3DB", + 809, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-19T00:00:00Z", + "01 22 39 42 46", + "36", + null + ], + [ + 810, + "2FE766E0-110C-4FCE-80B2-179AF7347FAE", + 810, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-23T00:00:00Z", + "04 16 36 40 53", + "18", + null + ], + [ + 811, + "DB5883CA-B9DD-471A-99AC-07BFDB428539", + 811, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-02-26T00:00:00Z", + "04 14 29 54 56", + "40", + null + ], + [ + 812, + "15CB5697-EB46-4932-8B7F-19A32ACF2340", + 812, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-02T00:00:00Z", + "09 12 47 48 56", + "25", + null + ], + [ + 813, + "CF4EB296-ABBE-4034-A548-A8CC9917EC24", + 813, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-05T00:00:00Z", + "11 31 34 44 52", + "32", + null + ], + [ + 814, + "A1EDA1B5-B783-4732-89DC-A359CB1FD0C7", + 814, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-09T00:00:00Z", + "14 16 18 19 29", + "16", + null + ], + [ + 815, + "1D791D17-41CD-4053-804F-3A7058B0EC24", + 815, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-12T00:00:00Z", + "02 15 25 48 53", + "41", + null + ], + [ + 816, + "D4C9077C-B7DD-4890-A6C1-DF0228AA3B1C", + 816, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-16T00:00:00Z", + "03 22 48 52 56", + "13", + null + ], + [ + 817, + "32DD92A6-6176-421B-AD93-6467660CF6D2", + 817, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-19T00:00:00Z", + "10 31 45 50 54", + "25", + null + ], + [ + 818, + "E773448F-7D8E-41B3-A08F-118B31FEB680", + 818, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-23T00:00:00Z", + "03 25 28 29 40", + "13", + null + ], + [ + 819, + "24388C14-9B3E-43A6-A07A-C80597855505", + 819, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-26T00:00:00Z", + "23 41 46 47 52", + "22", + null + ], + [ + 820, + "FC270668-BDB7-47E6-BA4D-7639B11FF369", + 820, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-03-30T00:00:00Z", + "01 11 24 38 44", + "41", + null + ], + [ + 821, + "FDF67DCE-BF83-4409-AFC6-A2FC0E1C35C9", + 821, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-02T00:00:00Z", + "02 17 22 30 31", + "19", + null + ], + [ + 822, + "F8EE5F90-48B8-4E4D-BE7B-F9A3780C04B0", + 822, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-06T00:00:00Z", + "16 43 44 52 56", + "26", + null + ], + [ + 823, + "2D4979F0-21FA-4EB4-A12F-A82ECAD11C85", + 823, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-09T00:00:00Z", + "15 18 39 48 53", + "03", + null + ], + [ + 824, + "3AD05007-2EBF-4675-BCAC-8D7610966D5C", + 824, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-13T00:00:00Z", + "03 12 27 39 47", + "32", + null + ], + [ + 825, + "671D846F-3632-44D6-98E4-E267DA8D19AB", + 825, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-16T00:00:00Z", + "10 16 31 48 50", + "44", + null + ], + [ + 826, + "9217DF4A-F053-4D12-AC26-DE254B56E4B0", + 826, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-20T00:00:00Z", + "05 08 10 34 42", + "25", + null + ], + [ + 827, + "AE0105AC-6C6E-4F11-9879-42A06D3090A3", + 827, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-23T00:00:00Z", + "19 26 28 37 52", + "18", + null + ], + [ + 828, + "65A9C9F5-5792-4D64-B225-3CF46C8D0026", + 828, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-27T00:00:00Z", + "23 37 41 50 55", + "06", + null + ], + [ + 829, + "5423D260-E2FC-4F86-8618-AAFAC601760B", + 829, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-04-30T00:00:00Z", + "14 20 41 47 53", + "40", + null + ], + [ + 830, + "45A9F9A3-30E6-41F0-A703-56B4F9E07294", + 830, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-04T00:00:00Z", + "09 21 31 36 43", + "08", + null + ], + [ + 831, + "1C82A9F5-D878-492C-A2CE-B37E205DB898", + 831, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-07T00:00:00Z", + "02 07 20 34 50", + "40", + null + ], + [ + 832, + "9615C4EB-1283-420B-94A2-48DBDD59A26A", + 832, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-11T00:00:00Z", + "26 33 43 46 54", + "09", + null + ], + [ + 833, + "1A730B61-1C5D-4EBB-8BD2-763F8EA4E8A5", + 833, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-14T00:00:00Z", + "20 21 40 47 56", + "12", + null + ], + [ + 834, + "1CAB05D1-6329-48C2-B5B4-253E53B89D46", + 834, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-18T00:00:00Z", + "11 13 19 37 40", + "26", + null + ], + [ + 835, + "EE46E0D7-377B-4075-9E44-618AC3F3F437", + 835, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-21T00:00:00Z", + "15 20 23 26 30", + "17", + null + ], + [ + 836, + "80585183-B52E-4348-9B2A-FF02017789B8", + 836, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-25T00:00:00Z", + "05 14 17 19 24", + "25", + null + ], + [ + 837, + "749A0427-5968-45CE-BD6C-C864F6F26A71", + 837, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-05-28T00:00:00Z", + "03 11 20 29 39", + "26", + null + ], + [ + 838, + "D72ACE65-0BFD-4826-8747-3CBB207764FA", + 838, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-01T00:00:00Z", + "12 27 44 45 51", + "30", + null + ], + [ + 839, + "78CFF352-C91F-4F79-9985-988B16077D13", + 839, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-04T00:00:00Z", + "12 13 15 17 50", + "23", + null + ], + [ + 840, + "3357706B-14F6-4A84-82EA-0BA1AD4705CE", + 840, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-08T00:00:00Z", + "12 18 28 48 54", + "06", + null + ], + [ + 841, + "F5926E9D-91D0-4FA0-9657-255273DA02BB", + 841, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-11T00:00:00Z", + "06 13 33 34 42", + "25", + null + ], + [ + 842, + "EE8D88B6-371B-48D8-B55F-0226F5058211", + 842, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-15T00:00:00Z", + "04 12 13 21 27", + "46", + null + ], + [ + 843, + "B584633B-6A66-4F79-8F2F-1609E41A44A5", + 843, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-18T00:00:00Z", + "11 36 37 41 55", + "07", + null + ], + [ + 844, + "47480512-F3C4-4411-BCED-EADC1B42F0D5", + 844, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-22T00:00:00Z", + "12 17 21 23 30", + "24", + null + ], + [ + 845, + "508956C9-C492-4141-9CE6-0DCBCE172E9D", + 845, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-25T00:00:00Z", + "01 02 13 19 27", + "21", + null + ], + [ + 846, + "9510B976-63F8-4F92-830F-BB53C4B7D35C", + 846, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-06-29T00:00:00Z", + "03 04 15 27 37", + "35", + null + ], + [ + 847, + "914A95CB-37B6-496A-8A7D-5A27B9F3E497", + 847, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-02T00:00:00Z", + "01 10 12 32 36", + "25", + null + ], + [ + 848, + "AB8D3AC8-D4F4-45A4-A8B9-4A398D6161FF", + 848, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-06T00:00:00Z", + "08 18 45 47 50", + "36", + null + ], + [ + 849, + "3CAF750C-2F9E-4805-AF9D-2F7A17D7390C", + 849, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-09T00:00:00Z", + "01 31 33 34 50", + "41", + null + ], + [ + 850, + "42BB83DD-69F5-4DD0-B7F6-B09CB72F84BB", + 850, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-13T00:00:00Z", + "07 11 14 15 34", + "14", + null + ], + [ + 851, + "A54BB62A-B5C4-4D33-8BF6-A47AD370146C", + 851, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-16T00:00:00Z", + "02 15 18 20 39", + "34", + null + ], + [ + 852, + "35689336-FA69-430B-BB7B-9D8757F5C563", + 852, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-20T00:00:00Z", + "12 18 28 36 43", + "19", + null + ], + [ + 853, + "79CF2CDF-F4FE-41AF-948C-679C89573D5A", + 853, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-23T00:00:00Z", + "16 19 39 44 49", + "26", + null + ], + [ + 854, + "8F6A8839-96B9-4695-B375-9D6ADC32915A", + 854, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-27T00:00:00Z", + "02 07 10 16 29", + "08", + null + ], + [ + 855, + "07371AEF-A119-4A98-BDC6-1E08263E3F78", + 855, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-07-30T00:00:00Z", + "11 30 40 48 52", + "42", + null + ], + [ + 856, + "A66E6504-5920-439B-88CA-8F0736C2CA2C", + 856, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-03T00:00:00Z", + "04 13 20 22 56", + "32", + null + ], + [ + 857, + "E3EC6624-7BB5-470B-AC8A-5CFB8289E377", + 857, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-06T00:00:00Z", + "07 13 30 33 54", + "30", + null + ], + [ + 858, + "A141A3CC-BD51-4E30-84C0-2A7D994FC250", + 858, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-10T00:00:00Z", + "02 14 26 50 56", + "12", + null + ], + [ + 859, + "A0E7F6EB-D326-4A9F-A31D-094EAD6A518E", + 859, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-13T00:00:00Z", + "06 17 24 43 55", + "36", + null + ], + [ + 860, + "D5438DC0-4EC6-48D9-B519-AD24C0B3FB25", + 860, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-17T00:00:00Z", + "11 19 40 43 44", + "33", + null + ], + [ + 861, + "5219DDB6-E022-4D60-9BFE-34FD4ECB709E", + 861, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-20T00:00:00Z", + "04 13 20 29 48", + "36", + null + ], + [ + 862, + "E662E6C4-0BE4-421F-893D-3527D5D5502C", + 862, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-24T00:00:00Z", + "04 23 24 28 32", + "31", + null + ], + [ + 863, + "805E4BEC-91C1-4A75-8465-568254B40416", + 863, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-27T00:00:00Z", + "04 10 26 32 41", + "31", + null + ], + [ + 864, + "8C850AB9-558A-4129-8544-0D9A634FA9E3", + 864, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-08-31T00:00:00Z", + "10 20 29 47 48", + "38", + null + ], + [ + 865, + "88CC3B82-9F43-4566-B130-C5517DBC33BA", + 865, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-03T00:00:00Z", + "10 13 20 28 36", + "09", + null + ], + [ + 866, + "E902EE49-B63A-4DB6-B67C-0FAAC30C3932", + 866, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-07T00:00:00Z", + "08 18 22 24 38", + "23", + null + ], + [ + 867, + "C78C1DE3-8629-429A-BD5B-C42A6F797F9C", + 867, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-10T00:00:00Z", + "11 12 17 21 23", + "20", + null + ], + [ + 868, + "CEBD219F-94FD-4152-9EC0-1A8395E776C9", + 868, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-14T00:00:00Z", + "06 14 50 55 56", + "01", + null + ], + [ + 869, + "2815439B-B45A-48AB-BC06-4E95BBDFED63", + 869, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-17T00:00:00Z", + "03 04 14 18 27", + "13", + null + ], + [ + 870, + "A4C211ED-A3C8-454D-B9AA-ED672D593BC0", + 870, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-21T00:00:00Z", + "03 20 43 47 52", + "26", + null + ], + [ + 871, + "3AE643AE-3752-4D4A-A8E3-A1EB0A794A48", + 871, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-24T00:00:00Z", + "02 28 38 42 55", + "25", + null + ], + [ + 872, + "1C36A6DE-F815-4E0C-BA3C-9144DA40C6B5", + 872, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-09-28T00:00:00Z", + "02 10 13 36 38", + "18", + null + ], + [ + 873, + "54F92A9D-74F4-4E96-802D-4C9838159251", + 873, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-01T00:00:00Z", + "03 08 21 28 52", + "43", + null + ], + [ + 874, + "A907DF1F-CDF1-4896-91D7-7FC18AEECBE6", + 874, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-05T00:00:00Z", + "10 19 24 37 44", + "27", + null + ], + [ + 875, + "8A737E94-9C1C-4D08-8BC8-9269BBC8D96F", + 875, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-08T00:00:00Z", + "24 29 37 48 50", + "19", + null + ], + [ + 876, + "E2152E19-B4AF-4B12-822B-4F8B9222C1ED", + 876, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-12T00:00:00Z", + "10 31 36 37 43", + "15", + null + ], + [ + 877, + "F3D56D53-59CA-4F5B-9758-79848E9FAF15", + 877, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-15T00:00:00Z", + "09 10 13 31 50", + "10", + null + ], + [ + 878, + "22C9895B-CEDF-400F-92EA-223B53FDA227", + 878, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-19T00:00:00Z", + "02 09 14 37 42", + "41", + null + ], + [ + 879, + "A0A4388D-A0C0-4614-8CE5-0EC197C3A92F", + 879, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-22T00:00:00Z", + "02 07 18 32 53", + "18", + null + ], + [ + 880, + "21185BC4-A0B6-401F-966C-F05F66A4AAAB", + 880, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-26T00:00:00Z", + "15 21 30 31 32", + "26", + null + ], + [ + 881, + "FF4917B9-749B-4410-B9AB-52130F6DF61C", + 881, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-10-29T00:00:00Z", + "04 19 26 28 39", + "14", + null + ], + [ + 882, + "6807A66D-E7DC-419D-AF2D-E4F2FCBCB6F4", + 882, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-02T00:00:00Z", + "01 03 12 16 54", + "46", + null + ], + [ + 883, + "FAA07034-9641-44B4-B65A-DBEBBD6750AC", + 883, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-05T00:00:00Z", + "19 25 34 46 53", + "15", + null + ], + [ + 884, + "B4C6A53B-F3AF-4867-84F5-55FB664CB90B", + 884, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-09T00:00:00Z", + "08 26 28 33 53", + "11", + null + ], + [ + 885, + "02A30C8B-B84D-4933-B04C-9188538A5FA7", + 885, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-12T00:00:00Z", + "09 26 28 35 38", + "10", + null + ], + [ + 886, + "11F16F0E-CB24-4E7D-A5F4-4BBF478A37FE", + 886, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-16T00:00:00Z", + "01 26 27 39 46", + "21", + null + ], + [ + 887, + "9E8A03C2-DFEC-4112-A696-EA9DDAD9E046", + 887, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-19T00:00:00Z", + "07 14 31 51 54", + "35", + null + ], + [ + 888, + "A96DE32B-3967-48BA-B33B-D1018E35334B", + 888, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-23T00:00:00Z", + "02 06 12 34 35", + "33", + null + ], + [ + 889, + "4CA5F4E1-FBE4-4E1E-A4B7-1C587DAB70ED", + 889, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-26T00:00:00Z", + "05 09 34 43 47", + "08", + null + ], + [ + 890, + "0AA621FC-44F6-487F-B81C-E2AE461301EF", + 890, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-11-30T00:00:00Z", + "11 16 19 47 53", + "02", + null + ], + [ + 891, + "D1529B07-F805-41BC-A0C0-1551575AE197", + 891, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-03T00:00:00Z", + "06 11 12 18 56", + "12", + null + ], + [ + 892, + "04CE11BD-8B0D-437E-8E0C-0C4B1D14C47D", + 892, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-07T00:00:00Z", + "04 38 45 53 54", + "09", + null + ], + [ + 893, + "BBE92898-012A-42EF-B481-64C5226EB753", + 893, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-10T00:00:00Z", + "23 27 33 44 46", + "36", + null + ], + [ + 894, + "9002B5AC-EE00-4406-A18D-3F2B219DC32A", + 894, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-14T00:00:00Z", + "18 22 25 31 38", + "29", + null + ], + [ + 895, + "FC1726CE-A844-4A99-9DFA-D539BDDCA6D4", + 895, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-17T00:00:00Z", + "11 20 26 46 53", + "12", + null + ], + [ + 896, + "A09E249A-42AA-4FC7-A7AE-DE5A7A81730D", + 896, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-21T00:00:00Z", + "08 11 12 31 32", + "29", + null + ], + [ + 897, + "06BBE3E8-F94D-4C38-84D0-B69EA134FFBF", + 897, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-24T00:00:00Z", + "15 16 27 40 52", + "16", + null + ], + [ + 898, + "20564B01-7B85-4448-B8E7-20634A4F9BDF", + 898, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-28T00:00:00Z", + "06 18 36 40 49", + "07", + null + ], + [ + 899, + "13965554-94D3-4B1F-918E-873DBCAF3770", + 899, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2010-12-31T00:00:00Z", + "10 12 13 35 56", + "09", + null + ], + [ + 900, + "2C0357BE-D0C4-4F6B-AD5D-454A3B01C445", + 900, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-04T00:00:00Z", + "04 08 15 25 47", + "42", + null + ], + [ + 901, + "77D470C4-97D8-4CD6-9CA7-E859EEAB4ED4", + 901, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-07T00:00:00Z", + "04 22 42 46 53", + "20", + null + ], + [ + 902, + "26BAF649-07AE-4D93-B04E-FBE9CC8E49C7", + 902, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-11T00:00:00Z", + "01 04 11 16 45", + "37", + null + ], + [ + 903, + "ED65CBC2-082D-49D7-A606-6BE130637FD4", + 903, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-14T00:00:00Z", + "02 15 17 33 35", + "08", + null + ], + [ + 904, + "79DED60A-4528-436F-96B3-20A5ECD2A325", + 904, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-18T00:00:00Z", + "04 27 29 38 45", + "05", + "04" + ], + [ + 905, + "E504A2AA-4A80-4CA3-87F4-7126B60E3CB2", + 905, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-21T00:00:00Z", + "05 09 21 35 38", + "20", + "04" + ], + [ + 906, + "6F676480-6614-4824-B7A0-A26A8B685BFE", + 906, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-25T00:00:00Z", + "05 08 31 46 50", + "04", + "04" + ], + [ + 907, + "C299984A-6FD1-46F2-A7FE-BF6FBA223648", + 907, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-01-28T00:00:00Z", + "14 33 48 49 50", + "18", + "04" + ], + [ + 908, + "DB803BB1-1023-4152-BE1A-677F08638237", + 908, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-01T00:00:00Z", + "16 22 23 26 35", + "31", + "04" + ], + [ + 909, + "59B74F61-2A5E-45D6-A80C-555F393BE9D2", + 909, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-04T00:00:00Z", + "06 20 29 48 55", + "06", + "04" + ], + [ + 910, + "ED342343-2A2F-43D9-A4AF-B0E8975A8D4F", + 910, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-08T00:00:00Z", + "25 35 36 47 48", + "18", + "02" + ], + [ + 911, + "997BA78B-4852-4D68-9136-0985CFF2A1B2", + 911, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-11T00:00:00Z", + "08 09 17 32 34", + "13", + "02" + ], + [ + 912, + "B9185736-00EE-445E-ABF2-68FD1FD9D41A", + 912, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-15T00:00:00Z", + "17 18 24 35 39", + "18", + "04" + ], + [ + 913, + "97470996-54FB-43DD-A51C-DCAC8B285499", + 913, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-18T00:00:00Z", + "05 06 07 30 45", + "42", + "03" + ], + [ + 914, + "1648D615-BF93-43BB-914C-ED9917530014", + 914, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-22T00:00:00Z", + "15 22 23 48 55", + "31", + "04" + ], + [ + 915, + "1706FD60-3151-4521-8369-ECCF5713BDF4", + 915, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-02-25T00:00:00Z", + "04 05 17 19 50", + "07", + "04" + ], + [ + 916, + "C31F64C8-FC0C-4378-A874-B3525CAEB27B", + 916, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-01T00:00:00Z", + "01 12 19 20 47", + "25", + "03" + ], + [ + 917, + "E7B38725-6D52-4D74-BE16-3EA8FDD10522", + 917, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-04T00:00:00Z", + "08 10 15 23 41", + "07", + "04" + ], + [ + 918, + "85F41156-0B86-480C-B223-BF206B9C4E8C", + 918, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-08T00:00:00Z", + "03 17 19 41 55", + "24", + "04" + ], + [ + 919, + "9377C452-D026-450A-B335-10C3709281F7", + 919, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-11T00:00:00Z", + "14 19 21 42 45", + "06", + "02" + ], + [ + 920, + "ED632697-783D-40E4-BBFA-BC9082954A7C", + 920, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-15T00:00:00Z", + "10 11 12 28 43", + "45", + "04" + ], + [ + 921, + "8681263B-5DAA-42EF-91EC-B7696A1E0849", + 921, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-18T00:00:00Z", + "14 33 34 54 56", + "37", + "04" + ], + [ + 922, + "3A284E39-1A0C-437A-A226-D221A4662F82", + 922, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-22T00:00:00Z", + "01 14 35 50 53", + "43", + "04" + ], + [ + 923, + "0CA4411F-F91F-4E80-B481-B5623FD47A33", + 923, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-25T00:00:00Z", + "22 24 31 52 54", + "04", + "04" + ], + [ + 924, + "CA55CA0F-FA9E-4348-B093-FC8A814140CB", + 924, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-03-29T00:00:00Z", + "06 15 23 34 38", + "43", + "04" + ], + [ + 925, + "EE5FC4AE-6C59-49BD-A6B9-CB0A04129E71", + 925, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-01T00:00:00Z", + "13 14 35 36 53", + "19", + "03" + ], + [ + 926, + "B70B7726-A102-489D-BF40-EB1F09381F4F", + 926, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-05T00:00:00Z", + "01 19 20 31 36", + "09", + "02" + ], + [ + 927, + "12A34C6D-6E1C-4888-B5F8-897E69681A44", + 927, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-08T00:00:00Z", + "06 40 45 50 56", + "11", + "03" + ], + [ + 928, + "8A851800-D763-454E-82FC-A8EBABA79F79", + 928, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-12T00:00:00Z", + "10 23 39 41 45", + "15", + "02" + ], + [ + 929, + "DFD2C533-7E17-4E64-8DE2-708A88683D96", + 929, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-15T00:00:00Z", + "22 23 33 39 48", + "29", + "03" + ], + [ + 930, + "C91C01F8-E7EF-4BBF-BCD3-C10695E342D3", + 930, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-19T00:00:00Z", + "20 24 32 45 51", + "43", + "04" + ], + [ + 931, + "C9A991A6-F088-4BF5-86CC-7786BCC4B8BF", + 931, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-22T00:00:00Z", + "03 18 46 51 53", + "17", + "03" + ], + [ + 932, + "082306E6-63D4-4E90-885E-4F29F45038B2", + 932, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-26T00:00:00Z", + "19 29 32 38 55", + "15", + "03" + ], + [ + 933, + "FDB58993-7061-4DCD-BD25-97ED0F318800", + 933, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-04-29T00:00:00Z", + "09 10 11 33 51", + "29", + "04" + ], + [ + 934, + "E042D17F-5ECB-40B2-8F2B-8326E77CFAD1", + 934, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-03T00:00:00Z", + "01 16 29 36 50", + "16", + "02" + ], + [ + 935, + "BCB6D64F-B258-40C3-BC82-EA562C957524", + 935, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-06T00:00:00Z", + "06 18 26 37 41", + "09", + "03" + ], + [ + 936, + "53C3DF38-DE02-49F1-90A2-108EB17948DD", + 936, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-10T00:00:00Z", + "11 16 34 40 51", + "34", + "04" + ], + [ + 937, + "9062FC96-A0F7-4EBC-9222-207F6758945C", + 937, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-13T00:00:00Z", + "03 33 39 47 53", + "09", + "04" + ], + [ + 938, + "32BB7177-E9EB-47B6-84FC-548D8B8A8406", + 938, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-17T00:00:00Z", + "01 02 17 25 48", + "45", + "04" + ], + [ + 939, + "27A3671C-10EF-401B-A767-610E60A6D0D4", + 939, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-20T00:00:00Z", + "10 17 19 45 48", + "30", + "04" + ], + [ + 940, + "3F03D46F-A972-431C-9605-B0CEDDFBB538", + 940, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-24T00:00:00Z", + "09 12 21 42 43", + "42", + "03" + ], + [ + 941, + "B4084B59-39C3-4252-9F9A-BB40B2CDB0E3", + 941, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-27T00:00:00Z", + "05 07 14 28 56", + "10", + "04" + ], + [ + 942, + "D7487BF7-2906-4A83-9BD9-98340B7FF036", + 942, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-05-31T00:00:00Z", + "28 30 31 37 55", + "13", + "03" + ], + [ + 943, + "361175FE-70B8-4080-BCBE-DB3E33556884", + 943, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-03T00:00:00Z", + "20 23 41 49 53", + "31", + "03" + ], + [ + 944, + "78C57DD5-875D-4F58-BFD9-121A6426D17B", + 944, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-07T00:00:00Z", + "29 32 35 47 52", + "13", + "04" + ], + [ + 945, + "9B6A425B-C5D3-4060-BAE7-97BDCC0BA7A4", + 945, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-10T00:00:00Z", + "18 21 27 37 38", + "07", + "03" + ], + [ + 946, + "9FDFF7B8-D455-4EE2-9AF2-7863146C4254", + 946, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-14T00:00:00Z", + "09 10 20 51 53", + "24", + "04" + ], + [ + 947, + "E4FE6C91-145A-4F31-9329-2976DC2DC0B1", + 947, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-17T00:00:00Z", + "12 29 46 47 51", + "24", + "04" + ], + [ + 948, + "12BDCBD8-F24B-48B1-867C-FD63ACC61CBF", + 948, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-21T00:00:00Z", + "11 24 25 31 46", + "17", + "03" + ], + [ + 949, + "1767DF09-F7CC-4762-B402-0E78147849D2", + 949, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-24T00:00:00Z", + "10 14 40 49 51", + "04", + "03" + ], + [ + 950, + "75829CF8-883B-4288-A747-9CF265DA50D9", + 950, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-06-28T00:00:00Z", + "12 17 27 47 48", + "33", + "04" + ], + [ + 951, + "C4C4306D-220A-43A8-A17B-6CFB22A90C45", + 951, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-01T00:00:00Z", + "12 17 30 35 47", + "26", + "04" + ], + [ + 952, + "1D651FF1-7190-422B-9E1C-9A964497C63B", + 952, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-05T00:00:00Z", + "01 10 13 18 46", + "19", + "02" + ], + [ + 953, + "15662C19-F99B-4447-9E80-6C8BDD767BBD", + 953, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-08T00:00:00Z", + "01 02 22 37 50", + "45", + "03" + ], + [ + 954, + "F61F010C-3070-4BCA-B84E-9040E840FB7B", + 954, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-12T00:00:00Z", + "03 09 11 44 49", + "09", + "04" + ], + [ + 955, + "03407F0F-604A-442F-A41E-4EA6CAFF01B7", + 955, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-15T00:00:00Z", + "16 29 30 46 56", + "06", + "03" + ], + [ + 956, + "4F5FE17B-8F5B-4648-9C22-FF9C6CB4626A", + 956, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-19T00:00:00Z", + "02 09 10 16 35", + "40", + "04" + ], + [ + 957, + "FE5C7077-5151-4BDF-A84B-148E50276C42", + 957, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-22T00:00:00Z", + "23 31 32 39 56", + "38", + "04" + ], + [ + 958, + "7AB8C5B6-90EB-4D60-9460-5F2AA356D05F", + 958, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-26T00:00:00Z", + "20 25 35 52 55", + "10", + "03" + ], + [ + 959, + "4083D81B-59EA-4E2D-B1F4-BEA1BCB41C25", + 959, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-07-29T00:00:00Z", + "08 10 22 47 48", + "35", + "04" + ], + [ + 960, + "61B4C46D-7E74-4438-950B-90514726608E", + 960, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-02T00:00:00Z", + "14 17 19 20 32", + "28", + "04" + ], + [ + 961, + "2CC54035-3718-4107-97B6-4BE09FD71596", + 961, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-05T00:00:00Z", + "06 24 28 33 42", + "19", + "03" + ], + [ + 962, + "C857D075-C3B6-4F20-A7DA-1DC845609E06", + 962, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-09T00:00:00Z", + "11 19 39 45 54", + "15", + "04" + ], + [ + 963, + "2CA2F348-42C1-4F15-8DDB-98966C409F07", + 963, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-12T00:00:00Z", + "09 43 51 54 55", + "13", + "04" + ], + [ + 964, + "1C06FA2B-34CA-4FF9-839A-FA0CBD905412", + 964, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-16T00:00:00Z", + "04 38 41 42 43", + "44", + "04" + ], + [ + 965, + "A7002E4C-D525-4F4C-A6AD-CBCB5A398BF1", + 965, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-19T00:00:00Z", + "05 15 53 54 56", + "22", + "02" + ], + [ + 966, + "D9A6699C-0C64-4546-8D22-6D6AC65F2EEF", + 966, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-23T00:00:00Z", + "11 21 44 48 49", + "23", + "03" + ], + [ + 967, + "E52436B0-9F29-4E7F-81D9-D21216826900", + 967, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-26T00:00:00Z", + "02 03 27 30 47", + "36", + "03" + ], + [ + 968, + "A26F102A-2C79-4F3D-A3E7-F3C58BF013A5", + 968, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-08-30T00:00:00Z", + "02 22 25 28 50", + "18", + "04" + ], + [ + 969, + "C577652E-D5BA-4C64-95CD-7FE4113D1534", + 969, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-02T00:00:00Z", + "25 44 48 49 55", + "20", + "03" + ], + [ + 970, + "353CE32E-67DD-4000-A3B2-165DBE4F2AAD", + 970, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-06T00:00:00Z", + "01 36 38 42 49", + "19", + "04" + ], + [ + 971, + "DA63C527-7600-4B8C-B383-C60019F11E5A", + 971, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-09T00:00:00Z", + "07 12 19 23 31", + "45", + "04" + ], + [ + 972, + "1A5842C0-C7C8-4AE5-B7A0-C6E8526ECD60", + 972, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-13T00:00:00Z", + "22 31 43 48 56", + "45", + "04" + ], + [ + 973, + "B7BAA60D-4658-4CB5-A865-D8C09693BBE7", + 973, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-16T00:00:00Z", + "06 23 41 45 56", + "24", + "04" + ], + [ + 974, + "A79C80C8-5F1B-43F2-A85A-4EABE40717B1", + 974, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-20T00:00:00Z", + "06 29 38 50 51", + "39", + "04" + ], + [ + 975, + "9C7F9D8A-9F22-4D27-AA9F-6B33AC7E70C1", + 975, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-23T00:00:00Z", + "27 31 32 40 52", + "36", + "04" + ], + [ + 976, + "AD2198FD-D11B-4183-9795-0F6E1B615274", + 976, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-27T00:00:00Z", + "02 20 28 36 45", + "37", + "04" + ], + [ + 977, + "14359A50-4A72-49E1-BA4F-88F1D18FEDFD", + 977, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-09-30T00:00:00Z", + "03 19 21 44 45", + "29", + "04" + ], + [ + 978, + "30A42918-32C3-4CE6-987F-AA1F27428177", + 978, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-04T00:00:00Z", + "03 26 40 45 52", + "11", + "03" + ], + [ + 979, + "01BF3321-0A60-4A1E-B5BE-81C2EFF99377", + 979, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-07T00:00:00Z", + "05 15 19 23 38", + "19", + "04" + ], + [ + 980, + "151F6F6E-3E97-4C7D-B393-6F4E62FF5239", + 980, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-11T00:00:00Z", + "25 34 38 44 56", + "27", + "04" + ], + [ + 981, + "786305BD-AE43-4B74-904E-236BDC499173", + 981, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-14T00:00:00Z", + "13 35 42 45 54", + "26", + "04" + ], + [ + 982, + "4D851549-3C28-40F9-9007-52231A2ED3EC", + 982, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-18T00:00:00Z", + "24 25 45 47 53", + "42", + "02" + ], + [ + 983, + "9EF3EFE4-9B8F-4014-8255-65EE45D9C3BE", + 983, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-21T00:00:00Z", + "06 21 35 37 38", + "17", + "03" + ], + [ + 984, + "5A28EBCE-5991-4A98-9931-5F1188307510", + 984, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-25T00:00:00Z", + "13 33 40 44 46", + "08", + "04" + ], + [ + 985, + "9B8BD3AB-FC4E-4877-856E-ACBC96EB4FCA", + 985, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-10-28T00:00:00Z", + "13 31 49 52 56", + "41", + "04" + ], + [ + 986, + "23D572A8-4943-416E-8344-79058FA41CDD", + 986, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-01T00:00:00Z", + "27 31 39 40 46", + "36", + "03" + ], + [ + 987, + "AE43DCE8-48BD-4103-A73D-1A9727E2616D", + 987, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-04T00:00:00Z", + "26 30 32 33 44", + "01", + "04" + ], + [ + 988, + "86A6904E-420B-4093-B38E-5B2786E20787", + 988, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-08T00:00:00Z", + "05 31 45 47 54", + "04", + "04" + ], + [ + 989, + "FCB62BE1-0722-40C7-A08E-C6E4938DC12C", + 989, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-11T00:00:00Z", + "02 16 22 29 50", + "27", + "04" + ], + [ + 990, + "7AE6EB76-503C-4BD5-BF39-A80C061F7F41", + 990, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-15T00:00:00Z", + "03 06 24 30 33", + "21", + "04" + ], + [ + 991, + "E5B962F9-B0B4-458D-9E1D-9E13AB973BD5", + 991, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-18T00:00:00Z", + "04 13 33 39 55", + "03", + "04" + ], + [ + 992, + "EB0D798E-AE4A-43BA-95DF-C7BBC32EBD9B", + 992, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-22T00:00:00Z", + "04 16 23 33 48", + "38", + "02" + ], + [ + 993, + "ACF4DF8E-BE16-45A6-BEDF-88206B701D0B", + 993, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-25T00:00:00Z", + "22 28 42 49 54", + "43", + "03" + ], + [ + 994, + "165668FF-6882-4BD5-8F20-466C5642A6CF", + 994, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-11-29T00:00:00Z", + "17 29 43 48 52", + "36", + "04" + ], + [ + 995, + "A2363856-2A4E-4701-A67B-94FC6ACA1DB0", + 995, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-02T00:00:00Z", + "24 30 48 51 56", + "45", + "04" + ], + [ + 996, + "532D6096-7C43-49C0-BB8C-212540A0DE99", + 996, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-06T00:00:00Z", + "07 21 29 35 49", + "39", + "04" + ], + [ + 997, + "C4B9DE45-9917-4551-9E78-8DA354CD74A6", + 997, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-09T00:00:00Z", + "04 12 29 49 51", + "44", + "04" + ], + [ + 998, + "24CB3C7A-76D3-4FCA-8ECE-C49794E30096", + 998, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-13T00:00:00Z", + "05 06 22 26 41", + "06", + "04" + ], + [ + 999, + "C30F212B-2CE3-406A-B3CB-28B6307A4A5D", + 999, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-16T00:00:00Z", + "02 04 26 36 39", + "27", + "03" + ], + [ + 1000, + "CD1A74E7-9E48-485B-8821-BFF2B6ECB703", + 1000, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-20T00:00:00Z", + "20 24 27 45 51", + "31", + "04" + ], + [ + 1001, + "4EDD3812-7564-4A29-B3E8-D64EE36AC9A7", + 1001, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-23T00:00:00Z", + "03 05 08 18 29", + "14", + "04" + ], + [ + 1002, + "D387D16A-8078-4E85-B4A1-E24BBDF45CC8", + 1002, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-27T00:00:00Z", + "23 32 33 39 43", + "08", + "03" + ], + [ + 1003, + "2F7BF875-07B8-4155-A068-229749172CDE", + 1003, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2011-12-30T00:00:00Z", + "04 24 45 46 52", + "01", + "04" + ], + [ + 1004, + "889504F6-0DFA-46AE-A744-B83293ABC371", + 1004, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-03T00:00:00Z", + "02 03 15 22 36", + "23", + "02" + ], + [ + 1005, + "76A27770-967F-411A-9748-CF2390EE3076", + 1005, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-06T00:00:00Z", + "09 17 28 34 48", + "46", + "02" + ], + [ + 1006, + "BA255100-BE0C-4719-A6D8-8E4E9BEA6A6C", + 1006, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-10T00:00:00Z", + "04 10 16 38 48", + "34", + "03" + ], + [ + 1007, + "82C36070-B9A3-4229-941D-B78430B169E2", + 1007, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-13T00:00:00Z", + "10 27 28 37 51", + "19", + "03" + ], + [ + 1008, + "75E0C7D8-ECD3-4DE1-9A7D-535F3B20CB3B", + 1008, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-17T00:00:00Z", + "03 15 31 36 53", + "27", + "02" + ], + [ + 1009, + "4ED7B6B9-35E5-42F5-B252-E57C515EE88E", + 1009, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-20T00:00:00Z", + "01 09 28 38 47", + "08", + "02" + ], + [ + 1010, + "BC86C784-2F3B-4403-A7DA-AD689471EC92", + 1010, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-24T00:00:00Z", + "10 22 24 36 49", + "33", + "04" + ], + [ + 1011, + "B8BD18B7-206A-4EBE-8DF8-45758EAA7A9D", + 1011, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-27T00:00:00Z", + "03 05 30 36 48", + "23", + "04" + ], + [ + 1012, + "3BBB4C54-DAF1-4D85-964B-D454BD35F996", + 1012, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-01-31T00:00:00Z", + "09 17 18 28 43", + "09", + "03" + ], + [ + 1013, + "EE2BB967-740B-41F2-8E2F-C714F30640E3", + 1013, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-03T00:00:00Z", + "07 19 21 49 53", + "35", + "04" + ], + [ + 1014, + "70FCEB5F-1CF6-4FFB-AD16-BAD74E82508E", + 1014, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-07T00:00:00Z", + "17 23 30 37 45", + "04", + "04" + ], + [ + 1015, + "32CE4FC2-B7D8-4D53-8BE9-5C71C805DB1E", + 1015, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-10T00:00:00Z", + "03 04 18 29 50", + "20", + "04" + ], + [ + 1016, + "A6C2E716-7C33-4C21-8F6D-FD67832236CF", + 1016, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-14T00:00:00Z", + "03 05 10 26 27", + "27", + "02" + ], + [ + 1017, + "78CC6486-2735-47CA-871D-EB288034B18F", + 1017, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-17T00:00:00Z", + "16 25 28 32 40", + "03", + "03" + ], + [ + 1018, + "47263F7C-71EE-43E4-975B-3C5DF80046B7", + 1018, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-21T00:00:00Z", + "09 30 39 42 47", + "37", + "03" + ], + [ + 1019, + "B5FD41BF-5398-4E7C-A04B-6110ABD8EEED", + 1019, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-24T00:00:00Z", + "01 16 18 25 27", + "03", + "04" + ], + [ + 1020, + "2568AF78-E4B3-4C0A-9D84-EB2BBA8674C7", + 1020, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-02-28T00:00:00Z", + "06 15 29 39 51", + "36", + "03" + ], + [ + 1021, + "A33ED94D-C63F-4D5A-A22D-74A6B3B37642", + 1021, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-02T00:00:00Z", + "16 29 48 52 54", + "05", + "02" + ], + [ + 1022, + "59AE5BFB-80D6-405A-9625-2B69FCD4B05E", + 1022, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-06T00:00:00Z", + "20 24 31 33 36", + "44", + "04" + ], + [ + 1023, + "032F093E-4D73-4CBE-8326-F24E4EA1ED75", + 1023, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-09T00:00:00Z", + "09 10 27 36 42", + "11", + "04" + ], + [ + 1024, + "CA113647-C098-4AEF-A96D-15D60FB897F8", + 1024, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-13T00:00:00Z", + "02 08 30 36 48", + "31", + "03" + ], + [ + 1025, + "44AA3D24-858A-406C-B594-06AE881897FE", + 1025, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-16T00:00:00Z", + "28 29 43 51 53", + "07", + "03" + ], + [ + 1026, + "24B69175-A86E-4AFA-8907-6B9ECFFD4D90", + 1026, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-20T00:00:00Z", + "01 04 06 11 14", + "30", + "04" + ], + [ + 1027, + "2D3BF97D-85C5-4BAD-ABF3-8E2D6376AA64", + 1027, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-23T00:00:00Z", + "06 17 19 20 21", + "20", + "04" + ], + [ + 1028, + "287A0E8A-4CA3-46CD-99D5-DA0C70EA8623", + 1028, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-27T00:00:00Z", + "09 19 34 44 51", + "24", + "03" + ], + [ + 1029, + "E0CBAB93-0D60-4131-B751-AF175E839DC5", + 1029, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-03-30T00:00:00Z", + "02 04 23 38 46", + "23", + "03" + ], + [ + 1030, + "2B8F29D2-4F87-4FF3-940F-61A8BB5EAEF5", + 1030, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-03T00:00:00Z", + "11 35 38 41 52", + "40", + "04" + ], + [ + 1031, + "4C5219FC-B9CE-49D3-B015-16B2E70787E4", + 1031, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-06T00:00:00Z", + "02 19 20 24 33", + "39", + "04" + ], + [ + 1032, + "A9D5BE40-C127-4D07-B697-FF1A5C1F23D0", + 1032, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-10T00:00:00Z", + "02 06 12 31 48", + "25", + "04" + ], + [ + 1033, + "2800F10F-2350-4D18-90BD-08B9D6AB5147", + 1033, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-13T00:00:00Z", + "09 14 17 36 42", + "33", + "04" + ], + [ + 1034, + "30125944-9595-44DC-9BC2-496EF0A18A0F", + 1034, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-17T00:00:00Z", + "01 16 24 32 48", + "02", + "04" + ], + [ + 1035, + "B1EC5474-6214-4C5C-8AF8-DB582A346125", + 1035, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-20T00:00:00Z", + "14 23 26 33 35", + "40", + "03" + ], + [ + 1036, + "5F6AEAD5-C667-4EFF-93F6-55E65CDD6E53", + 1036, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-24T00:00:00Z", + "03 09 15 37 38", + "39", + "04" + ], + [ + 1037, + "0F0DA791-5E11-413F-9116-17E2CA8A4393", + 1037, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-04-27T00:00:00Z", + "02 05 45 46 47", + "37", + "04" + ], + [ + 1038, + "0C71166B-0DEE-4DC7-91B1-C07F5A983930", + 1038, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-01T00:00:00Z", + "24 27 31 45 52", + "38", + "04" + ], + [ + 1039, + "B932BD1C-ADB6-4055-BA78-6C974B288CA4", + 1039, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-04T00:00:00Z", + "04 11 21 42 53", + "38", + "04" + ], + [ + 1040, + "BE8AF87B-F38F-4E90-94AA-A7DFC3311A72", + 1040, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-08T00:00:00Z", + "02 06 08 18 51", + "19", + "03" + ], + [ + 1041, + "A94A8741-F148-4E47-8537-2D677D998EA8", + 1041, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-11T00:00:00Z", + "03 15 29 35 54", + "08", + "04" + ], + [ + 1042, + "72D8AD79-C9F3-4DF2-BADF-3DE68622F209", + 1042, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-15T00:00:00Z", + "10 11 12 14 24", + "06", + "04" + ], + [ + 1043, + "6C599BA2-2F12-42D0-92BD-08C0C744DC82", + 1043, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-18T00:00:00Z", + "03 11 22 34 49", + "01", + "04" + ], + [ + 1044, + "723FDBC5-CFF6-4E47-BF82-2239FFD02151", + 1044, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-22T00:00:00Z", + "10 14 35 43 52", + "16", + "02" + ], + [ + 1045, + "A5BBE96D-3E42-4E92-BDCB-EB8AE2FEE2E6", + 1045, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-25T00:00:00Z", + "09 15 21 40 54", + "11", + "04" + ], + [ + 1046, + "305F4750-B4FE-4239-94CC-200981921FE8", + 1046, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-05-29T00:00:00Z", + "02 14 29 53 55", + "31", + "03" + ], + [ + 1047, + "BED1DE4C-7487-4697-ABB0-6EE0DE1D4C04", + 1047, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-01T00:00:00Z", + "02 27 38 46 52", + "45", + "03" + ], + [ + 1048, + "B6CC489D-1533-43CA-89AA-DEC3FA71868C", + 1048, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-05T00:00:00Z", + "37 39 42 53 55", + "22", + "03" + ], + [ + 1049, + "B282494C-029B-48A5-A971-BA1921A48F9C", + 1049, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-08T00:00:00Z", + "04 09 34 40 48", + "25", + "03" + ], + [ + 1050, + "705B58FB-961E-4DFB-9CE5-DD699AE6FE85", + 1050, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-12T00:00:00Z", + "02 09 17 34 50", + "45", + "04" + ], + [ + 1051, + "1AA6BC29-665A-4273-A019-CB18A0EF7E50", + 1051, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-15T00:00:00Z", + "08 12 18 30 40", + "04", + "03" + ], + [ + 1052, + "D28DA568-A586-4B07-BFCA-B6EFFF9E1E31", + 1052, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-19T00:00:00Z", + "11 21 27 30 53", + "11", + "02" + ], + [ + 1053, + "3AF12744-1D00-4BAC-8FA5-2843BBA1A78D", + 1053, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-22T00:00:00Z", + "10 16 19 32 36", + "13", + "03" + ], + [ + 1054, + "8EAB153B-B676-4A10-A75F-8360F91F7055", + 1054, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-26T00:00:00Z", + "03 16 23 35 36", + "20", + "04" + ], + [ + 1055, + "5352FDFD-E36E-422B-ADA4-587EC8275C8F", + 1055, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-06-29T00:00:00Z", + "28 34 39 45 53", + "34", + "04" + ], + [ + 1056, + "26E044FD-9174-44BF-9C91-E9FA6815CEF0", + 1056, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-03T00:00:00Z", + "03 04 24 36 52", + "45", + "04" + ], + [ + 1057, + "2FA5C720-4FDC-4A9F-B91F-07D4A92EA36C", + 1057, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-06T00:00:00Z", + "20 23 28 35 39", + "21", + "03" + ], + [ + 1058, + "7A122C50-A85E-403D-B68B-93290FAAC6D0", + 1058, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-10T00:00:00Z", + "03 11 19 23 36", + "21", + "04" + ], + [ + 1059, + "5478F179-CB82-4D15-8BFF-406E7560B55C", + 1059, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-13T00:00:00Z", + "06 07 13 24 46", + "34", + "02" + ], + [ + 1060, + "87740C9F-5839-4E38-8941-538016EB7A1B", + 1060, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-17T00:00:00Z", + "01 13 21 49 55", + "17", + "04" + ], + [ + 1061, + "E8F5ECD9-405B-4DDC-BB35-6247149D2DD7", + 1061, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-20T00:00:00Z", + "02 44 48 50 52", + "03", + "03" + ], + [ + 1062, + "21E69FF5-7872-4D58-AD7D-419F6B34AB5B", + 1062, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-24T00:00:00Z", + "05 09 38 46 51", + "05", + "04" + ], + [ + 1063, + "2714EA68-34BE-4055-8BC1-C907DE0D79FD", + 1063, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-27T00:00:00Z", + "02 03 04 08 43", + "26", + "03" + ], + [ + 1064, + "F0BBD71B-BB7C-4A97-8582-F86CA8B2F948", + 1064, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-07-31T00:00:00Z", + "05 18 21 29 41", + "37", + "03" + ], + [ + 1065, + "D86272A6-5D75-425F-A394-6165EA82158F", + 1065, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-03T00:00:00Z", + "02 10 13 38 46", + "02", + "03" + ], + [ + 1066, + "24D037E0-9557-4E57-AEB6-EECC0B19A7EE", + 1066, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-07T00:00:00Z", + "30 32 33 42 48", + "07", + "04" + ], + [ + 1067, + "50ECF7BF-2414-4BDA-837F-37F70F919736", + 1067, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-10T00:00:00Z", + "10 18 36 38 44", + "08", + "04" + ], + [ + 1068, + "49E869CF-430E-40E1-9505-A56BF9E5C452", + 1068, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-14T00:00:00Z", + "15 23 34 39 55", + "32", + "04" + ], + [ + 1069, + "4C5FA5C7-BA64-457B-86B4-0E8DB3627DBA", + 1069, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-17T00:00:00Z", + "08 20 24 35 56", + "24", + "03" + ], + [ + 1070, + "81506B15-2BAB-43FE-B9D7-9C71A8AF4EE9", + 1070, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-21T00:00:00Z", + "05 13 20 23 33", + "30", + "02" + ], + [ + 1071, + "952B076F-8AE1-400D-93BA-9867E014DFA2", + 1071, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-24T00:00:00Z", + "25 34 45 46 49", + "34", + "02" + ], + [ + 1072, + "3AFF5326-08D1-4F56-BEAE-51B9F7D0996A", + 1072, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-28T00:00:00Z", + "04 09 40 45 50", + "39", + "04" + ], + [ + 1073, + "537C9CD1-1310-4E5E-809B-D3E090056EE7", + 1073, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-08-31T00:00:00Z", + "31 40 41 47 48", + "45", + "03" + ], + [ + 1074, + "DF515955-CF4F-45B9-9936-F22EAF2DB035", + 1074, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-04T00:00:00Z", + "16 32 39 41 53", + "16", + "03" + ], + [ + 1075, + "C58215A7-C613-40B9-8927-C97403B4E82E", + 1075, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-07T00:00:00Z", + "15 32 38 42 46", + "31", + "04" + ], + [ + 1076, + "245ED977-E62E-4E8C-B64C-B17A1402870B", + 1076, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-11T00:00:00Z", + "05 11 20 33 36", + "11", + "03" + ], + [ + 1077, + "9F3F66A2-40BD-4955-B76E-EDCEBBAB20B0", + 1077, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-14T00:00:00Z", + "16 17 21 40 51", + "20", + "04" + ], + [ + 1078, + "2BE42A83-7582-4311-976D-63325F6C3321", + 1078, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-18T00:00:00Z", + "05 09 22 36 49", + "36", + "03" + ], + [ + 1079, + "DF65731A-4ADB-4724-B5B1-C2D61E1D39E6", + 1079, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-21T00:00:00Z", + "03 13 14 46 55", + "34", + "04" + ], + [ + 1080, + "7EF88A92-5329-4F32-8B37-43827B42F8D5", + 1080, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-25T00:00:00Z", + "07 08 23 50 51", + "26", + "03" + ], + [ + 1081, + "DFF13765-B557-4D84-80BF-8020B16F7107", + 1081, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-09-28T00:00:00Z", + "06 08 14 43 56", + "28", + "04" + ], + [ + 1082, + "E85924F2-4908-48C8-B845-CF32BE2D6D82", + 1082, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-02T00:00:00Z", + "10 11 20 42 55", + "09", + "04" + ], + [ + 1083, + "4136F9B6-D4E6-406E-A256-F09FE9C08F6A", + 1083, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-05T00:00:00Z", + "08 09 16 32 39", + "15", + "03" + ], + [ + 1084, + "8FC75879-BBB0-4BFD-817D-DFAC4BC5FC53", + 1084, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-09T00:00:00Z", + "06 15 16 22 37", + "03", + "04" + ], + [ + 1085, + "DA6C0387-AAC5-4D7B-8AB8-ACFB2DE932D7", + 1085, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-12T00:00:00Z", + "06 10 24 26 42", + "15", + "04" + ], + [ + 1086, + "77632ABE-F1FE-4DF7-9A02-4F3971F88C0A", + 1086, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-16T00:00:00Z", + "13 37 40 46 52", + "29", + "04" + ], + [ + 1087, + "35A41C79-9F9F-4051-8324-4E01959AF6F2", + 1087, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-19T00:00:00Z", + "14 34 36 48 53", + "42", + "03" + ], + [ + 1088, + "C43C079A-8259-46AE-AD0C-C1171C0D9702", + 1088, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-23T00:00:00Z", + "01 17 42 46 55", + "01", + "02" + ], + [ + 1089, + "46175276-4C66-4662-A23B-43E736DA2823", + 1089, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-26T00:00:00Z", + "04 15 24 36 40", + "44", + "02" + ], + [ + 1090, + "717D3849-2E82-4B11-8869-916662186A7D", + 1090, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-10-30T00:00:00Z", + "05 12 18 29 56", + "38", + "04" + ], + [ + 1091, + "37B75EFB-58C1-4F42-8B5C-F8EC5B381204", + 1091, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-02T00:00:00Z", + "04 18 22 38 44", + "24", + "03" + ], + [ + 1092, + "BA9E7188-173F-4C06-94C2-FA01ED9B3A64", + 1092, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-06T00:00:00Z", + "03 05 13 32 35", + "06", + "03" + ], + [ + 1093, + "D4EF0869-D9F0-4ADC-BE7B-356178EBA83A", + 1093, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-09T00:00:00Z", + "18 22 33 35 40", + "11", + "04" + ], + [ + 1094, + "167AB7D8-1685-45F9-B174-BBD1A7209F65", + 1094, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-13T00:00:00Z", + "06 12 31 46 56", + "34", + "02" + ], + [ + 1095, + "00FEB10F-0562-4691-9475-2E8DBF917745", + 1095, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-16T00:00:00Z", + "05 24 26 29 53", + "36", + "04" + ], + [ + 1096, + "FF917F07-13CC-4BA0-B947-7317F69BBD5D", + 1096, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-20T00:00:00Z", + "09 13 22 38 52", + "44", + "04" + ], + [ + 1097, + "EDE051F2-8DAF-4C2B-A7EE-A86E4C90C301", + 1097, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-23T00:00:00Z", + "08 37 44 47 48", + "27", + "04" + ], + [ + 1098, + "4FF05C3B-F34D-489D-A3BD-BF21FC01E90D", + 1098, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-27T00:00:00Z", + "05 12 26 42 49", + "24", + "04" + ], + [ + 1099, + "2CE2BB7D-AC4B-4524-8A19-EAEC23D1DB03", + 1099, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-11-30T00:00:00Z", + "11 22 24 28 31", + "46", + "03" + ], + [ + 1100, + "59EC55D3-6A65-4B9E-B764-A97714792364", + 1100, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-04T00:00:00Z", + "03 19 24 32 43", + "44", + "04" + ], + [ + 1101, + "F5EB2D52-1B44-493A-AAE3-7B024D35A473", + 1101, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-07T00:00:00Z", + "07 43 44 51 56", + "04", + "03" + ], + [ + 1102, + "4514531E-80EE-4556-B1A1-988590D025CC", + 1102, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-11T00:00:00Z", + "39 44 51 52 54", + "13", + "04" + ], + [ + 1103, + "B81A703D-FAC1-44E6-9686-652FD8271F71", + 1103, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-14T00:00:00Z", + "11 28 33 41 43", + "41", + "04" + ], + [ + 1104, + "7CEC7CB4-D889-44F3-8B63-6F8E50BD311A", + 1104, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-18T00:00:00Z", + "01 06 07 18 29", + "16", + "03" + ], + [ + 1105, + "F932DB93-4B9E-4563-A4B8-77E44190251B", + 1105, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-21T00:00:00Z", + "03 18 32 41 56", + "19", + "03" + ], + [ + 1106, + "F9751A75-3897-4B2A-A8B6-41481F808EB6", + 1106, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-25T00:00:00Z", + "02 03 18 34 48", + "36", + "04" + ], + [ + 1107, + "802578FB-DD16-4547-935D-D1148FBA842D", + 1107, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2012-12-28T00:00:00Z", + "10 13 32 40 41", + "32", + "04" + ], + [ + 1108, + "52CE7186-5986-428E-A395-B1C5D65A0BC0", + 1108, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-01T00:00:00Z", + "04 11 21 25 44", + "29", + "04" + ], + [ + 1109, + "AFC4FC11-6440-4195-A4D7-7BABF693798C", + 1109, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-04T00:00:00Z", + "01 02 23 25 55", + "39", + "04" + ], + [ + 1110, + "C7038282-827D-49CE-9421-AE78FADC4136", + 1110, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-08T00:00:00Z", + "03 20 21 38 42", + "19", + "04" + ], + [ + 1111, + "A1EE93AE-0700-4CEB-AAC1-E400CE47CF5E", + 1111, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-11T00:00:00Z", + "24 29 30 34 56", + "01", + "04" + ], + [ + 1112, + "6E6B28D8-DA3A-4A18-ACAA-ED5FBEE6F765", + 1112, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-15T00:00:00Z", + "01 06 12 19 41", + "14", + "04" + ], + [ + 1113, + "1CDA422F-6161-45AB-A608-3265EE8A02DF", + 1113, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-18T00:00:00Z", + "08 18 25 42 49", + "14", + "03" + ], + [ + 1114, + "D9BF1554-63B5-4AAB-B731-BDAC2ED2B49C", + 1114, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-22T00:00:00Z", + "07 11 16 39 54", + "13", + "03" + ], + [ + 1115, + "D9E2F748-C7A5-498C-9C34-ACCF4CD59C53", + 1115, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-25T00:00:00Z", + "11 12 17 31 48", + "01", + "04" + ], + [ + 1116, + "D354463F-ED6D-4C64-97BD-02F99BBFE12D", + 1116, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-01-29T00:00:00Z", + "08 12 27 46 47", + "06", + "03" + ], + [ + 1117, + "344BF005-5F14-456D-8F66-B045F0BDD0CF", + 1117, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-01T00:00:00Z", + "01 30 32 40 41", + "17", + "03" + ], + [ + 1118, + "FF269451-6A86-4792-86A0-F47F087E7B8C", + 1118, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-05T00:00:00Z", + "02 05 10 26 44", + "46", + "04" + ], + [ + 1119, + "946D9BF5-21CE-445F-9B54-23C00BF6B9A4", + 1119, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-08T00:00:00Z", + "06 15 20 39 50", + "05", + "04" + ], + [ + 1120, + "CCE92EEE-5DFE-46DC-A811-FB8FB6C42BDE", + 1120, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-12T00:00:00Z", + "09 22 32 38 55", + "44", + "03" + ], + [ + 1121, + "6E8DC59E-A1D3-4BE3-AD94-C9DDC798BCFD", + 1121, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-15T00:00:00Z", + "11 35 41 42 44", + "42", + "04" + ], + [ + 1122, + "267D0BD4-D7EF-4376-95B2-D11B5E4E4D2E", + 1122, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-19T00:00:00Z", + "01 15 19 30 56", + "28", + "03" + ], + [ + 1123, + "8E59FD84-CE6F-4F32-8BD6-24F2B2C6761A", + 1123, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-22T00:00:00Z", + "09 13 24 38 49", + "30", + "03" + ], + [ + 1124, + "CE025393-8E66-4A35-9785-3AF57314120E", + 1124, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-02-26T00:00:00Z", + "06 07 13 15 43", + "07", + "04" + ], + [ + 1125, + "41BAA06F-92DA-4FBD-BD08-6E0F30CC74EE", + 1125, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-03-01T00:00:00Z", + "17 30 38 43 51", + "20", + "04" + ], + [ + 1126, + "3C759335-70F9-43D8-8579-B10EE02BBA92", + 1126, + 1362743863, + "706580", + 1362743863, + "706580", + "{\n}", + "2013-03-05T00:00:00Z", + "06 20 39 41 46", + "42", + "03" + ], + [ + 1128, + "3BEE54D7-5827-423D-A45B-57280225C64B", + 1128, + 1363348969, + "708543", + 1363348969, + "708543", + "{\n}", + "2013-03-08T00:00:00Z", + "04 11 25 34 35", + "44", + "04" + ], + [ + 1129, + "9BA95032-4CD2-47C0-8849-B2763A756018", + 1129, + 1363348969, + "708543", + 1363348969, + "708543", + "{\n}", + "2013-03-12T00:00:00Z", + "09 12 19 20 30", + "39", + "04" + ], + [ + 1131, + "9EC242F7-CAF9-4BEE-8B68-69FFA06FD50E", + 1131, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-03-15T00:00:00Z", + "04 08 17 22 32", + "08", + "02" + ], + [ + 1132, + "ED91D5E6-75D0-461F-B75F-C71D05680F9A", + 1132, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-03-19T00:00:00Z", + "03 06 14 21 37", + "35", + "03" + ], + [ + 1133, + "484C92DF-9C91-44F8-A0D5-E6B1CA710ECE", + 1133, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-03-22T00:00:00Z", + "14 27 34 37 41", + "38", + "04" + ], + [ + 1134, + "3AE3734D-4290-4BFF-BEDC-6C80DFE1E017", + 1134, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-03-26T00:00:00Z", + "20 33 46 49 51", + "46", + "04" + ], + [ + 1135, + "D94AD183-ACB1-497A-8D41-0D4CB7C7A9B3", + 1135, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-03-29T00:00:00Z", + "25 31 36 46 53", + "21", + "04" + ], + [ + 1136, + "AAD7C104-063F-44FE-9871-D57F7AB15BCF", + 1136, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-04-02T00:00:00Z", + "07 10 14 40 47", + "34", + "04" + ], + [ + 1137, + "51CAFA51-4C1A-4680-A871-B8E95A4D5BC3", + 1137, + 1365512815, + "708543", + 1365512815, + "708543", + "{\n}", + "2013-04-05T00:00:00Z", + "08 15 23 36 41", + "05", + "03" + ], + [ + 1139, + "A6BC9F0F-78FE-46C4-A8B2-A814751D8620", + 1139, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-09T00:00:00Z", + "17 30 41 48 54", + "13", + "04" + ], + [ + 1140, + "31755A74-A1D7-4D79-9036-655BB9675711", + 1140, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-12T00:00:00Z", + "01 10 13 19 21", + "28", + "03" + ], + [ + 1141, + "C8DCB5D0-D886-4EA0-B036-2D28D8E566D2", + 1141, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-16T00:00:00Z", + "02 05 15 18 39", + "42", + "02" + ], + [ + 1142, + "68ACECAD-8C19-4528-9D43-66172BD23FF4", + 1142, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-19T00:00:00Z", + "06 08 12 22 43", + "28", + "04" + ], + [ + 1143, + "FB784F0E-D578-4096-BDB8-FE6B0AA6438B", + 1143, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-23T00:00:00Z", + "09 21 22 32 50", + "10", + "03" + ], + [ + 1144, + "51267C00-092E-4FAD-A0C2-0E80E5B287F8", + 1144, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-26T00:00:00Z", + "17 42 49 54 55", + "31", + "04" + ], + [ + 1145, + "BE7FCB7C-6D9A-4C53-9003-1762D1002834", + 1145, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-04-30T00:00:00Z", + "21 30 34 39 49", + "43", + "03" + ], + [ + 1146, + "37489A5A-AE35-4963-818A-79C81D7C420E", + 1146, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-03T00:00:00Z", + "02 20 34 42 54", + "39", + "02" + ], + [ + 1147, + "4103658B-1FCC-4C61-BD60-A25F14D7CB76", + 1147, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-07T00:00:00Z", + "01 06 13 20 51", + "31", + "04" + ], + [ + 1148, + "73828964-F4E0-4D97-9BE0-1030C96C06DD", + 1148, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-10T00:00:00Z", + "01 19 20 39 49", + "28", + "04" + ], + [ + 1149, + "CD109F37-1660-453B-B11F-E1A042F6367A", + 1149, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-14T00:00:00Z", + "06 10 12 28 32", + "38", + "04" + ], + [ + 1150, + "134C197F-4D35-46D5-97A8-363EC85C5F7A", + 1150, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-17T00:00:00Z", + "11 15 35 43 49", + "41", + "04" + ], + [ + 1151, + "D31E4D6A-1ED7-46E9-8801-C538F2B00DF8", + 1151, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-21T00:00:00Z", + "02 15 17 48 55", + "11", + "04" + ], + [ + 1152, + "67A3676C-9CE9-4AD5-AA4D-816428CD9DD6", + 1152, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-24T00:00:00Z", + "04 05 16 18 53", + "28", + "04" + ], + [ + 1153, + "2C1F1E98-3526-4DCA-99F6-3232C975FF7A", + 1153, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-28T00:00:00Z", + "04 12 25 32 54", + "36", + "04" + ], + [ + 1154, + "281321B5-0D36-4873-BA58-CFF592F88283", + 1154, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-05-31T00:00:00Z", + "02 20 26 44 46", + "26", + "03" + ], + [ + 1155, + "DE8A7985-1514-45D2-B3F4-71066E9A93EA", + 1155, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-04T00:00:00Z", + "10 11 12 20 55", + "19", + "03" + ], + [ + 1156, + "88A78BA1-75B1-4B19-B86B-E3E7A4B56DF3", + 1156, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-07T00:00:00Z", + "01 10 37 48 55", + "21", + "04" + ], + [ + 1157, + "19D77AD1-099E-4B73-867E-AE0E030A1D1B", + 1157, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-11T00:00:00Z", + "15 40 45 50 53", + "28", + "04" + ], + [ + 1158, + "6B2CFEC0-1059-42BB-8177-9884ED63A7FD", + 1158, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-14T00:00:00Z", + "02 05 31 33 34", + "20", + "04" + ], + [ + 1159, + "43196123-3624-4EAA-B62B-CDCE787D5891", + 1159, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-18T00:00:00Z", + "06 17 34 40 48", + "30", + "02" + ], + [ + 1160, + "E696EFBB-4D90-4788-AD22-DB95B76CF993", + 1160, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-21T00:00:00Z", + "03 14 17 40 50", + "03", + "03" + ], + [ + 1161, + "CF648C6E-2F7F-4E79-9CBE-A77779667BBC", + 1161, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-25T00:00:00Z", + "03 05 28 33 51", + "16", + "02" + ], + [ + 1162, + "8DE750D6-72BB-4DFE-BD37-E4B79A787AF5", + 1162, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-06-28T00:00:00Z", + "08 15 35 46 52", + "38", + "04" + ], + [ + 1163, + "F6C35A37-9C0A-497E-84AF-8C541B723501", + 1163, + 1373464329, + "708543", + 1373464329, + "708543", + "{\n}", + "2013-07-02T00:00:00Z", + "36 42 51 52 53", + "40", + "04" + ], + [ + 1165, + "B57DBFEB-3CE5-421A-B4D0-1C6FE19CD9D1", + 1165, + 1373960495, + "708543", + 1373960495, + "708543", + "{\n}", + "2013-07-05T00:00:00Z", + "02 23 41 47 54", + "42", + "04" + ], + [ + 1166, + "C39FE0CC-B623-4A5C-93B0-978C7D117C57", + 1166, + 1373960495, + "708543", + 1373960495, + "708543", + "{\n}", + "2013-07-09T00:00:00Z", + "03 21 43 45 48", + "14", + "02" + ], + [ + 1168, + "B8FC6747-8337-4895-9B3E-EBB6D585DFD1", + 1168, + 1375427752, + "708543", + 1375427752, + "708543", + "{\n}", + "2013-07-12T00:00:00Z", + "04 05 25 27 51", + "10", + "03" + ], + [ + 1169, + "8FE98420-15E7-46B3-80B8-5C969B920EF1", + 1169, + 1375427752, + "708543", + 1375427752, + "708543", + "{\n}", + "2013-07-16T00:00:00Z", + "10 14 21 40 53", + "20", + "02" + ], + [ + 1170, + "DD88EF69-CD96-4E83-89E2-6B53BD97EE73", + 1170, + 1375427752, + "708543", + 1375427752, + "708543", + "{\n}", + "2013-07-19T00:00:00Z", + "16 20 24 39 42", + "46", + "03" + ], + [ + 1171, + "1C7ADA59-1801-4B96-968C-B77854440912", + 1171, + 1375427752, + "708543", + 1375427752, + "708543", + "{\n}", + "2013-07-23T00:00:00Z", + "25 32 35 50 51", + "46", + "03" + ], + [ + 1172, + "EACD3FC7-2935-458E-AA95-44F2C20CB220", + 1172, + 1375427752, + "708543", + 1375427752, + "708543", + "{\n}", + "2013-07-26T00:00:00Z", + "04 22 23 27 38", + "42", + "04" + ], + [ + 1173, + "7DF345B2-D9AE-41E3-9C50-4820B5F6BEC7", + 1173, + 1375427752, + "708543", + 1375427752, + "708543", + "{\n}", + "2013-07-30T00:00:00Z", + "25 27 36 42 44", + "39", + "03" + ], + [ + 1175, + "6373BCDC-8BED-494F-9EF6-27C2632D5059", + 1175, + 1375712208, + "708543", + 1375712208, + "708543", + "{\n}", + "2013-08-02T00:00:00Z", + "08 21 23 25 39", + "04", + "02" + ], + [ + 1177, + "FDC98341-B359-4B13-9ACC-E56CD21D3006", + 1177, + 1376034895, + "708543", + 1376034895, + "708543", + "{\n}", + "2013-08-06T00:00:00Z", + "01 11 16 51 55", + "41", + "03" + ], + [ + 1179, + "4671157E-B666-4D37-BD2D-6BC7301F134C", + 1179, + 1376312414, + "708543", + 1376312414, + "708543", + "{\n}", + "2013-08-09T00:00:00Z", + "11 20 30 34 38", + "12", + "03" + ], + [ + 1181, + "8DDBA2CD-DB9C-4C8D-82FD-6966BE6A59E4", + 1181, + 1376486912, + "708543", + 1376486912, + "708543", + "{\n}", + "2013-08-13T00:00:00Z", + "02 31 32 37 41", + "40", + "04" + ], + [ + 1183, + "0911616E-2F9E-4473-B45B-16E2636132EE", + 1183, + 1376921184, + "708543", + 1376921184, + "708543", + "{\n}", + "2013-08-16T00:00:00Z", + "07 13 26 36 46", + "37", + "04" + ], + [ + 1185, + "54AF8A3A-8432-41BA-9DAB-4005B31898E6", + 1185, + 1377071706, + "708543", + 1377071706, + "708543", + "{\n}", + "2013-08-20T00:00:00Z", + "13 28 35 38 41", + "33", + "03" + ], + [ + 1187, + "75FE181F-FD04-449B-B905-DDE3E9D8B45A", + 1187, + 1377509016, + "708543", + 1377509016, + "708543", + "{\n}", + "2013-08-23T00:00:00Z", + "01 09 17 20 53", + "14", + "04" + ], + [ + 1189, + "AF8A2810-0255-4390-89B7-01B9CD3714B7", + 1189, + 1377695374, + "708543", + 1377695374, + "708543", + "{\n}", + "2013-08-27T00:00:00Z", + "04 07 30 36 38", + "38", + "04" + ], + [ + 1191, + "F340F4D7-005E-43A7-835C-5F437C8CE980", + 1191, + 1377918076, + "708543", + 1377918076, + "708543", + "{\n}", + "2013-08-30T00:00:00Z", + "06 19 24 43 44", + "33", + "02" + ], + [ + 1193, + "57668138-D77E-41A4-A653-A502920BAE5E", + 1193, + 1378263736, + "708543", + 1378263736, + "708543", + "{\n}", + "2013-09-03T00:00:00Z", + "04 13 14 28 41", + "28", + "03" + ], + [ + 1197, + "67057DAF-BB8E-49A3-A9E5-9C4498E7759F", + 1197, + 1378566096, + "708543", + 1378566096, + "708543", + "{\n}", + "2013-09-06T00:00:00Z", + "02 16 17 22 41", + "31", + "04" + ], + [ + 1203, + "2F3EFDD8-73E0-4577-A717-F943FE97BBD0", + 1203, + 1378868474, + "708543", + 1378868474, + "708543", + "{\n}", + "2013-09-10T00:00:00Z", + "02 12 18 54 56", + "01", + "03" + ], + [ + 1205, + "6CD062A7-159D-4079-92DB-AE8C20424C63", + 1205, + 1379127654, + "708543", + 1379127654, + "708543", + "{\n}", + "2013-09-13T00:00:00Z", + "09 22 28 48 54", + "08", + "04" + ], + [ + 1207, + "CFB168A0-A233-48E8-88B8-6EAB7721AD7B", + 1207, + 1379473264, + "708543", + 1379473264, + "708543", + "{\n}", + "2013-09-17T00:00:00Z", + "06 15 27 31 39", + "25", + "02" + ], + [ + 1209, + "B7FB8DDD-3DC7-472E-8C06-CDF77B7A1D20", + 1209, + 1379732475, + "708543", + 1379732475, + "708543", + "{\n}", + "2013-09-20T00:00:00Z", + "01 15 20 21 47", + "34", + "02" + ], + [ + 1211, + "7A049284-67B5-4A91-AF01-9914E831CDA7", + 1211, + 1380078065, + "708543", + 1380078065, + "708543", + "{\n}", + "2013-09-24T00:00:00Z", + "04 11 32 39 40", + "33", + "03" + ], + [ + 1213, + "7D185A57-BF93-48FC-89C5-13047BB01971", + 1213, + 1380337279, + "708543", + 1380337279, + "708543", + "{\n}", + "2013-09-27T00:00:00Z", + "09 23 27 49 51", + "38", + "02" + ], + [ + 1215, + "C521C07D-8F39-415E-B899-05489EEECD08", + 1215, + 1380682866, + "708543", + 1380682866, + "708543", + "{\n}", + "2013-10-01T00:00:00Z", + "07 10 30 37 53", + "01", + "03" + ], + [ + 1217, + "DA977317-43B0-4A2D-A0DE-BBD02E216397", + 1217, + 1380942064, + "708543", + 1380942064, + "708543", + "{\n}", + "2013-10-04T00:00:00Z", + "04 16 24 25 44", + "05", + "03" + ], + [ + 1219, + "178C758D-E83D-45DA-8B41-5FC1668DF08D", + 1219, + 1381287665, + "708543", + 1381287665, + "708543", + "{\n}", + "2013-10-08T00:00:00Z", + "06 15 19 23 40", + "05", + "03" + ], + [ + 1221, + "B591BCA6-8B28-4784-8291-E22BAA150DC9", + 1221, + 1381546854, + "708543", + 1381546854, + "708543", + "{\n}", + "2013-10-11T00:00:00Z", + "03 27 37 45 48", + "46", + "04" + ], + [ + 1223, + "1D2A1993-B0E0-4D79-AAB5-4CDD63EBBE74", + 1223, + 1381892445, + "708543", + 1381892445, + "708543", + "{\n}", + "2013-10-15T00:00:00Z", + "04 23 30 43 50", + "11", + "04" + ], + [ + 1225, + "05047244-5520-4963-9631-FB059B1D818D", + 1225, + 1382497255, + "708543", + 1382497255, + "708543", + "{\n}", + "2013-10-22T00:00:00Z", + "02 03 19 52 71", + "14", + "05" + ], + [ + 1227, + "F67117B4-9506-4B0F-AFB3-2068AFC40EBD", + 1227, + 1382756454, + "708543", + 1382756454, + "708543", + "{\n}", + "2013-10-25T00:00:00Z", + "06 16 45 54 60", + "15", + "02" + ], + [ + 1229, + "A1912FEE-CCAD-4455-BA2A-C7B70FFBEFA0", + 1229, + 1383102063, + "708543", + 1383102063, + "708543", + "{\n}", + "2013-10-29T00:00:00Z", + "20 33 50 53 54", + "07", + "03" + ], + [ + 1231, + "EF38518A-5261-432F-8C5A-AB1DB4938019", + 1231, + 1383361276, + "708543", + 1383361276, + "708543", + "{\n}", + "2013-11-01T00:00:00Z", + "32 35 49 62 67", + "01", + "05" + ], + [ + 1233, + "EBE1179F-A084-44F1-9CE4-93DAA1E8B5EA", + 1233, + 1383706866, + "708543", + 1383706866, + "708543", + "{\n}", + "2013-11-05T00:00:00Z", + "02 11 42 64 74", + "02", + "05" + ], + [ + 1235, + "2621B189-2DA4-4442-81E3-A5C5B3C45E9C", + 1235, + 1383966043, + "708543", + 1383966043, + "708543", + "{\n}", + "2013-11-08T00:00:00Z", + "41 42 51 57 65", + "07", + "02" + ], + [ + 1237, + "240EC7B3-968C-49A8-8964-6BA21C62B9B0", + 1237, + 1384335595, + "708543", + 1384335595, + "708543", + "{\n}", + "2013-11-12T00:00:00Z", + "20 30 32 42 71", + "15", + "05" + ], + [ + 1239, + "0DE2D9C9-90A2-4935-AD2C-3E83D65F9146", + 1239, + 1384571065, + "708543", + 1384571065, + "708543", + "{\n}", + "2013-11-15T00:00:00Z", + "25 44 49 54 63", + "08", + "04" + ], + [ + 1241, + "7935AC34-8C2D-41B9-AD70-D961EA870C52", + 1241, + 1384916445, + "708543", + 1384916445, + "708543", + "{\n}", + "2013-11-19T00:00:00Z", + "14 15 29 49 63", + "02", + "03" + ], + [ + 1243, + "28E02973-21FA-4667-8338-1EAD00A18DD3", + 1243, + 1385175654, + "708543", + 1385175654, + "708543", + "{\n}", + "2013-11-22T00:00:00Z", + "17 23 35 36 44", + "08", + "03" + ], + [ + 1245, + "78A29F4C-E6D8-4220-9BAF-A39EC86B01B1", + 1245, + 1385521297, + "708543", + 1385521297, + "708543", + "{\n}", + "2013-11-26T00:00:00Z", + "27 44 59 74 75", + "03", + "05" + ], + [ + 1247, + "23D353A9-9DA9-48CF-831F-1A1814B3338F", + 1247, + 1385780464, + "708543", + 1385780464, + "708543", + "{\n}", + "2013-11-29T00:00:00Z", + "09 41 43 47 57", + "05", + "04" + ], + [ + 1249, + "F65A0532-2E1D-4F37-8DC8-4393915B1311", + 1249, + 1386126046, + "708543", + 1386126046, + "708543", + "{\n}", + "2013-12-03T00:00:00Z", + "07 12 41 44 59", + "03", + "03" + ], + [ + 1251, + "B2E81356-B8CB-401B-BB42-2B76AD3FF125", + 1251, + 1386385254, + "708543", + 1386385254, + "708543", + "{\n}", + "2013-12-06T00:00:00Z", + "11 29 44 63 64", + "03", + "03" + ], + [ + 1253, + "418BDDC3-6283-4D2B-932E-25AE4BE0E39A", + 1253, + 1386730867, + "708543", + 1386730867, + "708543", + "{\n}", + "2013-12-10T00:00:00Z", + "05 12 22 41 65", + "13", + "02" + ], + [ + 1255, + "9C4371B8-472D-43C9-909F-A2C4853559ED", + 1255, + 1386990065, + "708543", + 1386990065, + "708543", + "{\n}", + "2013-12-13T00:00:00Z", + "19 24 26 27 70", + "12", + "02" + ], + [ + 1257, + "026F619A-B4D9-424B-AF29-10337E920A41", + 1257, + 1387335655, + "708543", + 1387335655, + "708543", + "{\n}", + "2013-12-17T00:00:00Z", + "08 14 17 20 39", + "07", + "04" + ], + [ + 1259, + "68BF57AC-6C45-4467-B7A8-B779BDC0962D", + 1259, + 1387594857, + "708543", + 1387594857, + "708543", + "{\n}", + "2013-12-20T00:00:00Z", + "03 04 31 49 57", + "06", + "02" + ], + [ + 1261, + "6DB61C6B-B71C-423D-A1CE-1339FCAB9E4A", + 1261, + 1387940464, + "708543", + 1387940464, + "708543", + "{\n}", + "2013-12-24T00:00:00Z", + "23 34 53 58 73", + "02", + "03" + ], + [ + 1263, + "F015A899-E4DE-4107-93A9-8A2B153B86CF", + 1263, + 1388286160, + "708543", + 1388286160, + "708543", + "{\n}", + "2013-12-27T00:00:00Z", + "04 15 35 48 49", + "11", + "05" + ], + [ + 1265, + "BEB24506-D802-409A-A5F2-BBFFDA30EF3F", + 1265, + 1388545256, + "708543", + 1388545256, + "708543", + "{\n}", + "2013-12-31T00:00:00Z", + "08 12 34 52 58", + "08", + "03" + ], + [ + 1267, + "42CF4EA0-F05B-47C9-96C4-0988DBFB9E43", + 1267, + 1388804475, + "708543", + 1388804475, + "708543", + "{\n}", + "2014-01-03T00:00:00Z", + "22 24 25 40 70", + "05", + "05" + ], + [ + 1269, + "759EF80C-6780-4CC8-A27B-F715230A2FB2", + 1269, + 1389150065, + "708543", + 1389150065, + "708543", + "{\n}", + "2014-01-07T00:00:00Z", + "13 34 56 62 64", + "06", + "05" + ], + [ + 1271, + "10DAB9D2-46FC-449B-8B66-EBF65D9FD40C", + 1271, + 1389409265, + "708543", + 1389409265, + "708543", + "{\n}", + "2014-01-10T00:00:00Z", + "08 28 36 37 57", + "08", + "03" + ], + [ + 1273, + "9A60089C-24F6-424F-B5CB-D4CCBE7F5988", + 1273, + 1389754865, + "708543", + 1389754865, + "708543", + "{\n}", + "2014-01-14T00:00:00Z", + "04 23 26 62 69", + "13", + "03" + ], + [ + 1275, + "FA057396-A897-42CD-A4FC-6CA5ABBA1C4F", + 1275, + 1390014118, + "708543", + 1390014118, + "708543", + "{\n}", + "2014-01-17T00:00:00Z", + "01 10 26 31 51", + "11", + "04" + ], + [ + 1277, + "D3DFB854-FC39-4840-8827-7D1019D3DA67", + 1277, + 1390359685, + "708543", + 1390359685, + "708543", + "{\n}", + "2014-01-21T00:00:00Z", + "08 23 33 45 52", + "04", + "04" + ], + [ + 1279, + "B9C11D6D-6EAF-46DA-888F-3631F2F8F57F", + 1279, + 1390618854, + "708543", + 1390618854, + "708543", + "{\n}", + "2014-01-24T00:00:00Z", + "22 45 46 47 65", + "10", + "05" + ], + [ + 1281, + "6C8D1F24-E450-49BB-BCC0-3E6EAE0FE1EB", + 1281, + 1390964455, + "708543", + 1390964455, + "708543", + "{\n}", + "2014-01-28T00:00:00Z", + "07 16 28 53 60", + "02", + "03" + ], + [ + 1283, + "382CEE0F-C829-4AFF-BF00-8B39312C4F9C", + 1283, + 1391223655, + "708543", + 1391223655, + "708543", + "{\n}", + "2014-01-31T00:00:00Z", + "03 09 13 47 52", + "08", + "04" + ], + [ + 1285, + "86776381-2947-4FA4-86FC-F558D7CC86E5", + 1285, + 1391569286, + "708543", + 1391569286, + "708543", + "{\n}", + "2014-02-04T00:00:00Z", + "25 44 49 60 73", + "09", + "03" + ], + [ + 1287, + "873B54D5-CB06-4D9B-A0D7-A48660F76ADD", + 1287, + 1391828465, + "708543", + 1391828465, + "708543", + "{\n}", + "2014-02-07T00:00:00Z", + "11 21 23 35 64", + "10", + "03" + ], + [ + 1289, + "FD28870B-0C80-4AF1-B2DF-4C52D4D79E58", + 1289, + 1392174055, + "708543", + 1392174055, + "708543", + "{\n}", + "2014-02-11T00:00:00Z", + "43 64 67 71 73", + "04", + "02" + ], + [ + 1291, + "5159CE5E-66B0-4DB9-9DD9-5B9B4D0745FD", + 1291, + 1392433255, + "708543", + 1392433255, + "708543", + "{\n}", + "2014-02-14T00:00:00Z", + "20 28 35 71 72", + "07", + "03" + ], + [ + 1293, + "DEAFD715-D7CD-4708-B535-D9899DD4621D", + 1293, + 1392778855, + "708543", + 1392778855, + "708543", + "{\n}", + "2014-02-18T00:00:00Z", + "23 29 31 37 70", + "14", + "05" + ], + [ + 1295, + "158825F3-5163-42A3-81DC-70D7B74D3F97", + 1295, + 1393038044, + "708543", + 1393038044, + "708543", + "{\n}", + "2014-02-21T00:00:00Z", + "23 29 32 45 46", + "15", + "05" + ], + [ + 1297, + "40802F04-A3AC-43C2-9734-1D1DC7C3B974", + 1297, + 1393383657, + "708543", + 1393383657, + "708543", + "{\n}", + "2014-02-25T00:00:00Z", + "12 18 25 35 66", + "15", + "05" + ], + [ + 1299, + "5ACF39BD-F796-425E-9F66-CB0B27E7C6B1", + 1299, + 1393642845, + "708543", + 1393642845, + "708543", + "{\n}", + "2014-02-28T00:00:00Z", + "03 31 50 58 59", + "06", + "04" + ], + [ + 1301, + "A28FF876-2890-4BF6-99DD-C392F055CACD", + 1301, + 1393988455, + "708543", + 1393988455, + "708543", + "{\n}", + "2014-03-04T00:00:00Z", + "10 29 31 35 45", + "10", + "02" + ], + [ + 1303, + "A92F3246-6DA4-48B7-90EA-B2D9A5DBFFB3", + 1303, + 1394247656, + "708543", + 1394247656, + "708543", + "{\n}", + "2014-03-07T00:00:00Z", + "11 13 51 57 69", + "01", + "04" + ], + [ + 1305, + "FDEA8FEE-8538-40FC-AEF4-DB0F81B3EB1A", + 1305, + 1394593254, + "708543", + 1394593254, + "708543", + "{\n}", + "2014-03-11T00:00:00Z", + "09 14 56 57 69", + "10", + "04" + ], + [ + 1307, + "BCB912F4-419E-4BE3-983B-200EBAA821E3", + 1307, + 1394852454, + "708543", + 1394852454, + "708543", + "{\n}", + "2014-03-14T00:00:00Z", + "07 20 40 54 69", + "12", + "03" + ], + [ + 1309, + "1030DC1D-317C-4D87-B1B9-C06B46814C7A", + 1309, + 1395198065, + "708543", + 1395198065, + "708543", + "{\n}", + "2014-03-18T00:00:00Z", + "11 19 24 33 51", + "07", + "03" + ], + [ + 1311, + "C4CB2C86-7538-4347-9CD1-070BC0C71401", + 1311, + 1395457255, + "708543", + 1395457255, + "708543", + "{\n}", + "2014-03-21T00:00:00Z", + "02 23 30 35 53", + "10", + "05" + ], + [ + 1313, + "C836D6E0-C01E-4E00-BD1C-A14D1CF63588", + 1313, + 1395802856, + "708543", + 1395802856, + "708543", + "{\n}", + "2014-03-25T00:00:00Z", + "19 26 51 57 73", + "15", + "03" + ], + [ + 1315, + "5448D834-9CE6-4F77-AE17-19710BA851DC", + 1315, + 1396105275, + "708543", + 1396105275, + "708543", + "{\n}", + "2014-03-28T00:00:00Z", + "02 03 09 50 73", + "12", + "03" + ], + [ + 1317, + "5F48BA5C-1DC0-49F2-9AEF-8DCAE61E57CC", + 1317, + 1396407655, + "708543", + 1396407655, + "708543", + "{\n}", + "2014-04-01T00:00:00Z", + "10 23 68 74 75", + "09", + "05" + ], + [ + 1319, + "802D51AA-4C72-4264-8A00-6F1FEB1CA238", + 1319, + 1396666854, + "708543", + 1396666854, + "708543", + "{\n}", + "2014-04-04T00:00:00Z", + "01 10 15 41 54", + "09", + "02" + ], + [ + 1321, + "01F73B3B-B197-4BCE-8F02-95115A601CB5", + 1321, + 1397012466, + "708543", + 1397012466, + "708543", + "{\n}", + "2014-04-08T00:00:00Z", + "35 36 41 60 71", + "03", + "03" + ], + [ + 1323, + "6C79075A-EB20-4E77-89DB-C663CA5BF346", + 1323, + 1397271699, + "708543", + 1397271699, + "708543", + "{\n}", + "2014-04-11T00:00:00Z", + "03 42 44 47 57", + "08", + "05" + ], + [ + 1325, + "E45F48E3-1406-45F0-AB43-FE8D891EBD27", + 1325, + 1397617245, + "708543", + 1397617245, + "708543", + "{\n}", + "2014-04-15T00:00:00Z", + "04 39 46 47 70", + "13", + "03" + ], + [ + 1327, + "5EB30A7D-8459-4869-AE84-2A2DD1DB5B26", + 1327, + 1397876455, + "708543", + 1397876455, + "708543", + "{\n}", + "2014-04-18T00:00:00Z", + "18 25 38 45 63", + "09", + "02" + ], + [ + 1329, + "F7877028-A351-43B9-BD5A-D308A12C0115", + 1329, + 1398222385, + "708543", + 1398222385, + "708543", + "{\n}", + "2014-04-22T00:00:00Z", + "02 18 19 49 50", + "01", + "03" + ], + [ + 1331, + "6BD4A8B0-05E1-4C3B-BBB1-67CB07D2375D", + 1331, + 1398481352, + "708543", + 1398481352, + "708543", + "{\n}", + "2014-04-25T00:00:00Z", + "03 11 18 20 66", + "09", + "02" + ], + [ + 1333, + "AD580C79-D981-4492-9C81-4D975790086E", + 1333, + 1398826854, + "708543", + 1398826854, + "708543", + "{\n}", + "2014-04-29T00:00:00Z", + "07 43 59 61 66", + "03", + "03" + ], + [ + 1335, + "E2A087C6-174E-4627-925E-DE97C997ABED", + 1335, + 1399086054, + "708543", + 1399086054, + "708543", + "{\n}", + "2014-05-02T00:00:00Z", + "01 18 26 35 40", + "13", + "05" + ], + [ + 1337, + "2FDCA593-5848-467B-B3BF-730AED119414", + 1337, + 1399431741, + "708543", + 1399431741, + "708543", + "{\n}", + "2014-05-06T00:00:00Z", + "18 20 27 48 51", + "05", + "03" + ], + [ + 1339, + "B9E82F60-40BE-4CF4-88A5-FC6BD28807D1", + 1339, + 1399690844, + "708543", + 1399690844, + "708543", + "{\n}", + "2014-05-09T00:00:00Z", + "10 28 39 51 59", + "14", + "02" + ], + [ + 1341, + "90CF704A-3004-4DA4-BCE4-A5E1A8D717D3", + 1341, + 1400036529, + "708543", + 1400036529, + "708543", + "{\n}", + "2014-05-13T00:00:00Z", + "37 46 48 70 74", + "01", + "02" + ], + [ + 1343, + "DA1069E2-CB5D-451C-BB3C-7D1C35F561B0", + 1343, + 1400295664, + "708543", + 1400295664, + "708543", + "{\n}", + "2014-05-16T00:00:00Z", + "13 14 16 50 56", + "11", + "05" + ], + [ + 1345, + "F0CCE86A-0493-4D82-BCA8-CCE4EEBA9CB7", + 1345, + 1400641329, + "708543", + 1400641329, + "708543", + "{\n}", + "2014-05-20T00:00:00Z", + "10 40 63 64 69", + "07", + "02" + ], + [ + 1347, + "7FAD9C65-4F10-418D-B767-66A240EE8C87", + 1347, + 1400900518, + "708543", + 1400900518, + "708543", + "{\n}", + "2014-05-23T00:00:00Z", + "12 14 21 38 70", + "15", + "04" + ], + [ + 1349, + "791FB6CC-F7D0-4C9D-BFCE-4F068C0E7F4C", + 1349, + 1401246129, + "708543", + 1401246129, + "708543", + "{\n}", + "2014-05-27T00:00:00Z", + "01 06 10 46 58", + "13", + "02" + ], + [ + 1351, + "99C102A0-EE2C-4831-A852-FFDCAA15BCDC", + 1351, + 1401505329, + "708543", + 1401505329, + "708543", + "{\n}", + "2014-05-30T00:00:00Z", + "10 13 42 43 62", + "02", + "04" + ], + [ + 1353, + "CFDC3F17-1919-4AB6-B8F7-3591D7C31688", + 1353, + 1402024243, + "708543", + 1402024243, + "708543", + "{\n}", + "2014-06-03T00:00:00Z", + "19 28 62 66 74", + "06", + "03" + ], + [ + 1355, + "0FC680AA-3BF1-4785-AD94-A3088BAE1937", + 1355, + 1402110057, + "708543", + 1402110057, + "708543", + "{\n}", + "2014-06-06T00:00:00Z", + "12 29 37 49 72", + "09", + "04" + ], + [ + 1357, + "28AD4295-DD5E-483A-B44C-4C49E82467C9", + 1357, + 1402455655, + "708543", + 1402455655, + "708543", + "{\n}", + "2014-06-10T00:00:00Z", + "02 10 24 26 74", + "07", + "05" + ], + [ + 1359, + "2A70E1C3-7D5F-4525-92BD-CFCFAB3D3CBF", + 1359, + 1402714928, + "708543", + 1402714928, + "708543", + "{\n}", + "2014-06-13T00:00:00Z", + "07 38 46 49 56", + "01", + "05" + ], + [ + 1361, + "94CEE9E6-8F91-4BE7-ABCA-7B2129DC86C4", + 1361, + 1403060540, + "708543", + 1403060540, + "708543", + "{\n}", + "2014-06-17T00:00:00Z", + "10 14 24 47 60", + "03", + "04" + ], + [ + 1363, + "E71CDAAF-A30A-4D3E-9705-96DF940C1792", + 1363, + 1403319665, + "708543", + 1403319665, + "708543", + "{\n}", + "2014-06-20T00:00:00Z", + "01 22 25 29 56", + "03", + "05" + ], + [ + 1365, + "78923DD8-7B8A-4095-A4B5-DE0F205C7455", + 1365, + 1403665339, + "708543", + 1403665339, + "708543", + "{\n}", + "2014-06-24T00:00:00Z", + "13 17 24 47 65", + "10", + "04" + ], + [ + 1367, + "201A2006-4B49-4B3A-A99C-56E811DB26DB", + 1367, + 1403924475, + "708543", + 1403924475, + "708543", + "{\n}", + "2014-06-27T00:00:00Z", + "15 29 31 46 64", + "10", + "03" + ], + [ + 1369, + "B51C0FFE-A2F8-43A3-BFF9-F13ED5437EAC", + 1369, + 1404270128, + "708543", + 1404270128, + "708543", + "{\n}", + "2014-07-01T00:00:00Z", + "09 22 38 47 49", + "15", + "03" + ], + [ + 1371, + "B421489C-518C-44E2-B4E1-1739115E80A4", + 1371, + 1404529254, + "708543", + 1404529254, + "708543", + "{\n}", + "2014-07-04T00:00:00Z", + "16 33 39 58 69", + "02", + "05" + ], + [ + 1373, + "B9CC2A6E-9DDC-4D54-8BB8-C0DE58D4CCAF", + 1373, + 1404874864, + "708543", + 1404874864, + "708543", + "{\n}", + "2014-07-08T00:00:00Z", + "14 25 27 48 49", + "09", + "05" + ], + [ + 1375, + "9A035F2C-B234-4592-BF32-C88182E53A4C", + 1375, + 1405134066, + "708543", + 1405134066, + "708543", + "{\n}", + "2014-07-11T00:00:00Z", + "09 13 30 35 69", + "10", + "05" + ], + [ + 1377, + "4BF0FB2B-65A8-40DA-9DBA-697D7861AD00", + 1377, + 1405479645, + "708543", + 1405479645, + "708543", + "{\n}", + "2014-07-15T00:00:00Z", + "02 04 17 36 40", + "05", + "02" + ], + [ + 1379, + "108F044B-4621-4389-B12F-29CEACF20F30", + 1379, + 1405738855, + "708543", + 1405738855, + "708543", + "{\n}", + "2014-07-18T00:00:00Z", + "05 08 59 65 72", + "03", + "03" + ], + [ + 1381, + "D8B6033E-27F9-40AD-BE99-7F115C07D3A9", + 1381, + 1406084465, + "708543", + 1406084465, + "708543", + "{\n}", + "2014-07-22T00:00:00Z", + "14 18 22 31 47", + "15", + "03" + ], + [ + 1383, + "23AEF0BE-4851-4489-8195-0B5D084A5D76", + 1383, + 1406343656, + "708543", + 1406343656, + "708543", + "{\n}", + "2014-07-25T00:00:00Z", + "22 29 33 41 68", + "12", + "05" + ], + [ + 1385, + "781CE161-A749-41BC-8128-06367FB855CE", + 1385, + 1406689245, + "708543", + 1406689245, + "708543", + "{\n}", + "2014-07-29T00:00:00Z", + "02 08 16 43 74", + "01", + "04" + ], + [ + 1387, + "EC807140-3D55-49C4-BE48-2CD4847B5B50", + 1387, + 1406948455, + "708543", + 1406948455, + "708543", + "{\n}", + "2014-08-01T00:00:00Z", + "13 29 34 37 72", + "06", + "05" + ], + [ + 1389, + "437853F0-FAFD-4FFB-ACC5-9581E3335D29", + 1389, + 1407294066, + "708543", + 1407294066, + "708543", + "{\n}", + "2014-08-05T00:00:00Z", + "25 28 36 45 53", + "06", + "05" + ], + [ + 1391, + "283739E2-D52E-4A05-B041-C3832A4FD03F", + 1391, + 1407553265, + "708543", + 1407553265, + "708543", + "{\n}", + "2014-08-08T00:00:00Z", + "09 16 61 70 75", + "07", + "05" + ], + [ + 1393, + "F9F5E31F-0AF3-48CC-9243-EA28B055525B", + 1393, + 1407898866, + "708543", + 1407898866, + "708543", + "{\n}", + "2014-08-12T00:00:00Z", + "32 53 60 63 68", + "06", + "04" + ], + [ + 1395, + "A551D24C-0E35-43C7-AFD7-BCFC9B1A8458", + 1395, + 1408158065, + "708543", + 1408158065, + "708543", + "{\n}", + "2014-08-15T00:00:00Z", + "16 19 28 29 68", + "09", + "02" + ], + [ + 1397, + "932D43AF-18E1-4C9D-90AC-0EBB473DA2AE", + 1397, + 1408503656, + "708543", + 1408503656, + "708543", + "{\n}", + "2014-08-19T00:00:00Z", + "22 39 56 67 71", + "15", + "04" + ], + [ + 1399, + "869D1C4F-05FE-4CB7-B2B8-2226D93B2BEE", + 1399, + 1408762865, + "708543", + 1408762865, + "708543", + "{\n}", + "2014-08-22T00:00:00Z", + "05 31 34 41 74", + "03", + "05" + ], + [ + 1401, + "5DD5D9B1-0338-4C20-AA2D-6FA5E96F59E0", + 1401, + 1409108455, + "708543", + 1409108455, + "708543", + "{\n}", + "2014-08-26T00:00:00Z", + "29 31 51 60 64", + "01", + "05" + ], + [ + 1403, + "068A5120-3B84-41C2-A798-4D29C04252EF", + 1403, + 1409367666, + "708543", + 1409367666, + "708543", + "{\n}", + "2014-08-29T00:00:00Z", + "03 26 45 58 73", + "12", + "02" + ], + [ + 1405, + "E0F9E0B8-89FE-4966-A782-DC09D6359977", + 1405, + 1409713276, + "708543", + 1409713276, + "708543", + "{\n}", + "2014-09-02T00:00:00Z", + "01 08 54 69 72", + "01", + "03" + ], + [ + 1407, + "509607B9-9609-481E-83C7-DB52AA1DFF16", + 1407, + 1409972456, + "708543", + 1409972456, + "708543", + "{\n}", + "2014-09-05T00:00:00Z", + "07 12 20 24 59", + "07", + "02" + ], + [ + 1409, + "587B5A59-F548-457D-9936-71C0D6749539", + 1409, + 1410359284, + "708543", + 1410359284, + "708543", + "{\n}", + "2014-09-09T00:00:00Z", + "25 34 55 70 71", + "01", + "04" + ], + [ + 1411, + "109218EC-770D-4D23-8FC1-170CAB79D91B", + 1411, + 1410857469, + "708543", + 1410857469, + "708543", + "{\n}", + "2014-09-12T00:00:00Z", + "18 28 33 36 42", + "07", + "03" + ], + [ + 1413, + "3B36FBD4-980C-412C-BE40-DC647C1BC1EC", + 1413, + 1410922895, + "708543", + 1410922895, + "708543", + "{\n}", + "2014-09-16T00:00:00Z", + "25 45 51 53 73", + "02", + "02" + ], + [ + 1415, + "25B65074-AEBB-4AC5-8773-26ECC64BE53B", + 1415, + 1411225291, + "708543", + 1411225291, + "708543", + "{\n}", + "2014-09-19T00:00:00Z", + "16 25 27 29 34", + "02", + "02" + ], + [ + 1417, + "5743D5F1-F6EC-4C4B-A823-8EA8F70F8472", + 1417, + 1411527691, + "708543", + 1411527691, + "708543", + "{\n}", + "2014-09-23T00:00:00Z", + "21 24 25 40 43", + "12", + "05" + ], + [ + 1419, + "3E083094-377E-4539-82CE-9DBEF1F04FF7", + 1419, + 1411786960, + "708543", + 1411786960, + "708543", + "{\n}", + "2014-09-26T00:00:00Z", + "17 26 35 46 62", + "09", + "05" + ], + [ + 1421, + "D765F55E-7EEA-407C-B053-16503F02985E", + 1421, + 1412175692, + "708543", + 1412175692, + "708543", + "{\n}", + "2014-09-30T00:00:00Z", + "03 16 52 54 61", + "06", + "05" + ], + [ + 1423, + "A2B9AB24-47CD-42F2-96AC-EEA20DD75824", + 1423, + 1412391627, + "708543", + 1412391627, + "708543", + "{\n}", + "2014-10-03T00:00:00Z", + "03 20 34 58 67", + "06", + "03" + ], + [ + 1425, + "28DCADB9-7202-4BBF-89B9-B3740E7D1DBD", + 1425, + 1412780470, + "708543", + 1412780470, + "708543", + "{\n}", + "2014-10-07T00:00:00Z", + "16 29 46 48 55", + "02", + "03" + ], + [ + 1427, + "48C60FDD-51FA-4DEA-A448-B4BA3AEEFB6F", + 1427, + 1412996487, + "708543", + 1412996487, + "708543", + "{\n}", + "2014-10-10T00:00:00Z", + "02 32 35 50 59", + "03", + "05" + ], + [ + 1429, + "141DA9CF-E55A-479C-B882-08951E859ECD", + 1429, + 1413342225, + "708543", + 1413342225, + "708543", + "{\n}", + "2014-10-14T00:00:00Z", + "11 37 46 64 68", + "15", + "03" + ], + [ + 1431, + "C9ADA820-57B4-48F6-8E63-4D73F2B38278", + 1431, + 1413601288, + "708543", + 1413601288, + "708543", + "{\n}", + "2014-10-17T00:00:00Z", + "21 31 43 56 60", + "12", + "04" + ], + [ + 1433, + "C8637DC5-F6BC-48BA-86A2-C8C3EA59D9C0", + 1433, + 1413946886, + "708543", + 1413946886, + "708543", + "{\n}", + "2014-10-21T00:00:00Z", + "05 35 37 41 66", + "11", + "05" + ], + [ + 1435, + "F66ADFB5-6426-4807-9FAD-7D32A44811FA", + 1435, + 1414206088, + "708543", + 1414206088, + "708543", + "{\n}", + "2014-10-24T00:00:00Z", + "02 14 21 28 55", + "03", + "03" + ], + [ + 1437, + "AA6A6599-1679-4CEB-A74B-B01FDC4479AF", + 1437, + 1414551686, + "708543", + 1414551686, + "708543", + "{\n}", + "2014-10-28T00:00:00Z", + "03 50 57 58 60", + "11", + "05" + ], + [ + 1439, + "540D4B98-5003-4DE4-9D65-9815DC33BB18", + 1439, + 1414810889, + "708543", + 1414810889, + "708543", + "{\n}", + "2014-10-31T00:00:00Z", + "11 29 36 58 67", + "15", + "02" + ], + [ + 1441, + "50B7B5D2-D3DF-4E29-8D09-95AF015916CB", + 1441, + 1415156491, + "708543", + 1415156491, + "708543", + "{\n}", + "2014-11-04T00:00:00Z", + "09 15 24 39 41", + "01", + "04" + ], + [ + 1443, + "5578102D-B814-45E5-88E3-92E8546BA3E7", + 1443, + 1415415687, + "708543", + 1415415687, + "708543", + "{\n}", + "2014-11-07T00:00:00Z", + "31 35 41 65 66", + "05", + "05" + ], + [ + 1445, + "BCBA72A1-AF88-480F-9F9B-EAE4D5AFC88F", + 1445, + 1415804595, + "708543", + 1415804595, + "708543", + "{\n}", + "2014-11-11T00:00:00Z", + "23 25 28 30 75", + "11", + "05" + ], + [ + 1447, + "226C67C8-8DFA-48F7-B743-25EF3F2AAF62", + 1447, + 1416193460, + "708543", + 1416193460, + "708543", + "{\n}", + "2014-11-14T00:00:00Z", + "03 49 61 62 68", + "15", + "05" + ], + [ + 1449, + "BF321267-5089-4771-B912-00DF34976A87", + 1449, + 1416452617, + "708543", + 1416452617, + "708543", + "{\n}", + "2014-11-18T00:00:00Z", + "37 39 53 68 75", + "06", + "02" + ], + [ + 1451, + "A79F946A-1E3B-4A8E-BB5E-C0C13C99C5B6", + 1451, + 1416625290, + "708543", + 1416625290, + "708543", + "{\n}", + "2014-11-21T00:00:00Z", + "03 12 35 37 63", + "15", + "02" + ], + [ + 1453, + "4533C6C0-AB19-4FE3-9CF8-15DA4CC80699", + 1453, + 1416970890, + "708543", + 1416970890, + "708543", + "{\n}", + "2014-11-25T00:00:00Z", + "10 11 29 47 56", + "04", + "02" + ], + [ + 1455, + "C42CB168-F837-46FE-9253-87B0872F4969", + 1455, + 1417230091, + "708543", + 1417230091, + "708543", + "{\n}", + "2014-11-28T00:00:00Z", + "08 26 29 36 47", + "10", + "03" + ], + [ + 1457, + "98ACB2EF-CFF0-4F85-89DB-49E3049A1B4E", + 1457, + 1417575689, + "708543", + 1417575689, + "708543", + "{\n}", + "2014-12-02T00:00:00Z", + "13 18 22 49 62", + "11", + "05" + ], + [ + 1459, + "34E52148-0F7E-4E2F-A184-88DD9FEEC593", + 1459, + 1417834897, + "708543", + 1417834897, + "708543", + "{\n}", + "2014-12-05T00:00:00Z", + "04 05 11 51 59", + "05", + "05" + ], + [ + 1461, + "5369666F-70AF-42D2-A900-6631404FCFF0", + 1461, + 1418180484, + "708543", + 1418180484, + "708543", + "{\n}", + "2014-12-09T00:00:00Z", + "27 45 49 51 52", + "14", + "05" + ], + [ + 1463, + "76484243-0CFA-4951-8699-9C0115C85933", + 1463, + 1418439700, + "708543", + 1418439700, + "708543", + "{\n}", + "2014-12-12T00:00:00Z", + "02 31 46 58 65", + "07", + "05" + ], + [ + 1465, + "7E4E9479-256F-44C8-BBDC-BD0E17AA3501", + 1465, + 1418785292, + "708543", + 1418785292, + "708543", + "{\n}", + "2014-12-16T00:00:00Z", + "41 58 68 72 73", + "01", + "05" + ], + [ + 1467, + "D2360BBD-56C2-4DD3-B532-91E07CAC7062", + 1467, + 1419044492, + "708543", + 1419044492, + "708543", + "{\n}", + "2014-12-19T00:00:00Z", + "14 18 58 59 68", + "04", + "03" + ], + [ + 1469, + "BD3EE70B-A135-4BC5-98F5-2C7B1F1AD47D", + 1469, + 1419390093, + "708543", + 1419390093, + "708543", + "{\n}", + "2014-12-23T00:00:00Z", + "04 10 31 56 66", + "07", + "03" + ], + [ + 1471, + "5787AFFB-6C5A-448E-9525-1A896D8F69C1", + 1471, + 1419649380, + "708543", + 1419649380, + "708543", + "{\n}", + "2014-12-26T00:00:00Z", + "02 05 10 20 38", + "14", + "03" + ], + [ + 1473, + "720F4D3F-A832-4C4B-A137-5051A202656B", + 1473, + 1419994895, + "708543", + 1419994895, + "708543", + "{\n}", + "2014-12-30T00:00:00Z", + "03 07 44 63 67", + "12", + "04" + ], + [ + 1475, + "1E9AC8BA-D977-4FED-BB99-2BC5277DD02F", + 1475, + 1420254092, + "708543", + 1420254092, + "708543", + "{\n}", + "2015-01-02T00:00:00Z", + "13 15 35 62 74", + "12", + "04" + ], + [ + 1477, + "03F23C47-039E-484C-BBC7-60312DF63D12", + 1477, + 1420599691, + "708543", + 1420599691, + "708543", + "{\n}", + "2015-01-06T00:00:00Z", + "12 20 27 38 75", + "04", + "03" + ], + [ + 1479, + "23409C63-89B9-441B-8CA6-8B9481C7B8DC", + 1479, + 1420858876, + "708543", + 1420858876, + "708543", + "{\n}", + "2015-01-09T00:00:00Z", + "37 49 50 56 57", + "08", + "05" + ], + [ + 1481, + "7D28878E-B1A6-4068-98A0-E6CF1825A96B", + 1481, + 1421204593, + "708543", + 1421204593, + "708543", + "{\n}", + "2015-01-13T00:00:00Z", + "12 20 25 50 51", + "07", + "05" + ], + [ + 1483, + "29F7CCC7-0AF3-4814-A461-D31C3AE51815", + 1483, + 1421463668, + "708543", + 1421463668, + "708543", + "{\n}", + "2015-01-16T00:00:00Z", + "26 32 44 45 58", + "11", + "03" + ], + [ + 1485, + "DCBEEBB5-2F0C-48DD-86C5-C61B20888290", + 1485, + 1421809296, + "708543", + 1421809296, + "708543", + "{\n}", + "2015-01-20T00:00:00Z", + "31 35 56 59 63", + "06", + "05" + ], + [ + 1487, + "7C1F426A-59E8-4DB5-AB4E-219C5325C340", + 1487, + 1422068490, + "708543", + 1422068490, + "708543", + "{\n}", + "2015-01-23T00:00:00Z", + "14 15 32 68 72", + "08", + "02" + ], + [ + 1489, + "854D8323-507E-44FC-BF64-90A934F13D29", + 1489, + 1422414088, + "708543", + 1422414088, + "708543", + "{\n}", + "2015-01-27T00:00:00Z", + "05 26 27 44 57", + "07", + "03" + ], + [ + 1491, + "52F40161-7F01-4506-96F2-5A8A98D4DAC9", + 1491, + 1422673269, + "708543", + 1422673269, + "708543", + "{\n}", + "2015-01-30T00:00:00Z", + "18 31 39 45 55", + "06", + "05" + ], + [ + 1493, + "6A0CE853-9E0D-4ED5-95A1-4E0F9E374FF0", + 1493, + 1423018893, + "708543", + 1423018893, + "708543", + "{\n}", + "2015-02-03T00:00:00Z", + "11 22 25 58 69", + "13", + "05" + ], + [ + 1495, + "BC84605C-8B57-4569-97F0-5AE244C67001", + 1495, + 1423278090, + "708543", + 1423278090, + "708543", + "{\n}", + "2015-02-06T00:00:00Z", + "05 06 17 33 68", + "13", + "03" + ], + [ + 1497, + "8E0F669E-B531-4F3B-B2BF-B2771BD94A74", + 1497, + 1423623690, + "708543", + 1423623690, + "708543", + "{\n}", + "2015-02-10T00:00:00Z", + "07 42 53 58 71", + "15", + "02" + ], + [ + 1499, + "CE96B160-24FB-402B-AA8F-4936E2D39F81", + 1499, + 1423882891, + "708543", + 1423882891, + "708543", + "{\n}", + "2015-02-13T00:00:00Z", + "04 20 44 65 74", + "14", + "03" + ], + [ + 1501, + "1488A3D6-7D6E-444A-A4F5-1CDF80F801F7", + 1501, + 1424228493, + "708543", + 1424228493, + "708543", + "{\n}", + "2015-02-17T00:00:00Z", + "06 45 50 65 66", + "01", + "05" + ], + [ + 1503, + "ECE25E72-E4CA-41C2-8700-DD99960A7BD9", + 1503, + 1424487687, + "708543", + 1424487687, + "708543", + "{\n}", + "2015-02-20T00:00:00Z", + "02 06 08 52 66", + "13", + "03" + ], + [ + 1505, + "12F983C2-99EA-4616-843D-383B1A3D3B05", + 1505, + 1424833287, + "708543", + 1424833287, + "708543", + "{\n}", + "2015-02-24T00:00:00Z", + "15 23 26 45 66", + "04", + "03" + ], + [ + 1507, + "76073F80-C906-400E-8D4C-BC2E9FE6DB1B", + 1507, + 1425092468, + "708543", + 1425092468, + "708543", + "{\n}", + "2015-02-27T00:00:00Z", + "07 49 53 60 64", + "04", + "02" + ], + [ + 1509, + "E0984802-013E-4277-85BF-2D5E8CE49EBA", + 1509, + 1425438096, + "708543", + 1425438096, + "708543", + "{\n}", + "2015-03-03T00:00:00Z", + "09 11 42 44 50", + "03", + "04" + ], + [ + 1511, + "0A3DAF39-2EB3-4650-A72F-89A45ED5FC5D", + 1511, + 1425697322, + "708543", + 1425697322, + "708543", + "{\n}", + "2015-03-06T00:00:00Z", + "30 48 55 68 73", + "05", + "03" + ], + [ + 1513, + "D6EB5B00-F0DF-4CD6-AEFB-3833C1087B69", + 1513, + 1426042905, + "708543", + 1426042905, + "708543", + "{\n}", + "2015-03-10T00:00:00Z", + "10 14 19 30 73", + "14", + "05" + ], + [ + 1515, + "FC3C62B4-CD9E-40CB-AD63-A0920FAA15FE", + 1515, + 1426302087, + "708543", + 1426302087, + "708543", + "{\n}", + "2015-03-13T00:00:00Z", + "08 22 30 42 45", + "03", + "05" + ], + [ + 1517, + "7691B527-2FDA-4AD5-A180-B935E802D9EF", + 1517, + 1426647689, + "708543", + 1426647689, + "708543", + "{\n}", + "2015-03-17T00:00:00Z", + "11 27 44 45 58", + "03", + "05" + ], + [ + 1519, + "00FAB518-D2CA-4B7A-89A4-F81F738490DC", + 1519, + 1426906887, + "708543", + 1426906887, + "708543", + "{\n}", + "2015-03-20T00:00:00Z", + "07 50 54 61 75", + "07", + "04" + ], + [ + 1521, + "606D43E5-EA21-465A-AAC0-2C70C208B935", + 1521, + 1427252484, + "708543", + 1427252484, + "708543", + "{\n}", + "2015-03-24T00:00:00Z", + "02 23 32 45 55", + "12", + "02" + ], + [ + 1523, + "3BF3F918-FD1B-4762-A373-B5D9EB016FE9", + 1523, + 1427511687, + "708543", + 1427511687, + "708543", + "{\n}", + "2015-03-27T00:00:00Z", + "17 21 36 58 70", + "03", + "05" + ], + [ + 1525, + "D1FD0F94-BB97-40B6-BD07-14B355F38EDF", + 1525, + 1427857287, + "708543", + 1427857287, + "708543", + "{\n}", + "2015-03-31T00:00:00Z", + "08 26 41 61 73", + "11", + "05" + ], + [ + 1527, + "75C70A26-B013-47F6-AB17-55C5328B66BC", + 1527, + 1428116490, + "708543", + 1428116490, + "708543", + "{\n}", + "2015-04-03T00:00:00Z", + "10 36 47 63 74", + "02", + "05" + ], + [ + 1529, + "C0FC19C0-5945-4C1F-A836-CB310E1395C3", + 1529, + 1428462088, + "708543", + 1428462088, + "708543", + "{\n}", + "2015-04-07T00:00:00Z", + "05 15 22 26 64", + "06", + "04" + ], + [ + 1531, + "BA163D58-47C9-4B0B-B432-3115631C3403", + 1531, + 1428721288, + "708543", + 1428721288, + "708543", + "{\n}", + "2015-04-10T00:00:00Z", + "06 11 32 46 68", + "09", + "02" + ], + [ + 1533, + "DB69CE29-443B-4F14-B9E5-1CAA95882FD7", + 1533, + 1429066887, + "708543", + 1429066887, + "708543", + "{\n}", + "2015-04-14T00:00:00Z", + "03 07 25 68 71", + "03", + "05" + ], + [ + 1535, + "EF4A13BC-7E42-411E-B38C-89BA969F85CC", + 1535, + 1429326089, + "708543", + 1429326089, + "708543", + "{\n}", + "2015-04-17T00:00:00Z", + "15 18 29 41 50", + "05", + "02" + ], + [ + 1537, + "02ECDBF5-B6FD-4A1D-BBF3-61C1F04A3CE2", + 1537, + 1429671687, + "708543", + 1429671687, + "708543", + "{\n}", + "2015-04-21T00:00:00Z", + "31 33 35 41 69", + "11", + "05" + ], + [ + 1539, + "9A0FE695-8393-4F33-A105-6C1BB5E9EDE9", + 1539, + 1429930889, + "708543", + 1429930889, + "708543", + "{\n}", + "2015-04-24T00:00:00Z", + "24 25 29 47 67", + "04", + "04" + ], + [ + 1541, + "A1D5F972-6D8C-4B76-A289-69E352E806CD", + 1541, + 1430276508, + "708543", + 1430276508, + "708543", + "{\n}", + "2015-04-28T00:00:00Z", + "22 27 55 58 63", + "11", + "05" + ], + [ + 1543, + "CB258EDF-076B-4199-8BFF-7E799B635D55", + 1543, + 1430535711, + "708543", + 1430535711, + "708543", + "{\n}", + "2015-05-01T00:00:00Z", + "17 18 61 66 74", + "03", + "03" + ], + [ + 1545, + "EEB76D4C-E7C1-4C74-BFEC-2296C29AEF0F", + 1545, + 1430881307, + "708543", + 1430881307, + "708543", + "{\n}", + "2015-05-05T00:00:00Z", + "11 21 42 62 71", + "07", + "05" + ], + [ + 1547, + "4E7287E0-B454-4D0D-B2CD-F7973ED0DD0B", + 1547, + 1431140494, + "708543", + 1431140494, + "708543", + "{\n}", + "2015-05-08T00:00:00Z", + "09 21 25 66 72", + "07", + "03" + ], + [ + 1549, + "F11F018E-0E2A-4FD7-88E1-C0978A87AAFD", + 1549, + 1431486108, + "708543", + 1431486108, + "708543", + "{\n}", + "2015-05-12T00:00:00Z", + "14 30 33 36 44", + "02", + "05" + ], + [ + 1551, + "9DC8A2A8-6EEB-4C6F-85D6-2E121BA31891", + 1551, + 1431745290, + "708543", + 1431745290, + "708543", + "{\n}", + "2015-05-15T00:00:00Z", + "11 17 21 36 74", + "15", + "05" + ], + [ + 1553, + "16A8B73D-D63A-471A-9575-C82B0F79348E", + 1553, + 1432090927, + "708543", + 1432090927, + "708543", + "{\n}", + "2015-05-19T00:00:00Z", + "10 12 21 29 65", + "10", + "05" + ], + [ + 1555, + "79E08881-8F9F-4152-8A46-6F4740358B15", + 1555, + 1432350090, + "708543", + 1432350090, + "708543", + "{\n}", + "2015-05-22T00:00:00Z", + "03 14 15 25 48", + "08", + "05" + ], + [ + 1557, + "16AA6E62-2764-4352-8079-E10FD79C6C0A", + 1557, + 1432695687, + "708543", + 1432695687, + "708543", + "{\n}", + "2015-05-26T00:00:00Z", + "01 39 52 69 72", + "12", + "04" + ], + [ + 1559, + "8291B987-7740-4A35-A8AA-444F1CC1E21B", + 1559, + 1432954911, + "708543", + 1432954911, + "708543", + "{\n}", + "2015-05-29T00:00:00Z", + "20 27 38 49 66", + "02", + "04" + ], + [ + 1561, + "BB565492-D644-4BD5-8127-C9CC2005DC73", + 1561, + 1433300489, + "708543", + 1433300489, + "708543", + "{\n}", + "2015-06-02T00:00:00Z", + "02 09 11 22 23", + "12", + "04" + ], + [ + 1563, + "6F42DCC6-0C62-40C6-B530-BE484E52FB3E", + 1563, + 1433559758, + "708543", + 1433559758, + "708543", + "{\n}", + "2015-06-05T00:00:00Z", + "07 22 27 41 49", + "10", + "04" + ], + [ + 1565, + "A3EE789D-9396-4CDA-8B89-899EFDB844C6", + 1565, + 1433905222, + "708543", + 1433905222, + "708543", + "{\n}", + "2015-06-09T00:00:00Z", + "06 16 17 25 36", + "07", + "05" + ], + [ + 1567, + "856CE10D-D4B2-4C16-8A18-31DF4766B6A9", + 1567, + 1434164494, + "708543", + 1434164494, + "708543", + "{\n}", + "2015-06-12T00:00:00Z", + "01 40 42 56 62", + "02", + "05" + ], + [ + 1569, + "422205F9-728E-4DFB-86C2-0CF2A12A9FD4", + 1569, + 1434510087, + "708543", + 1434510087, + "708543", + "{\n}", + "2015-06-16T00:00:00Z", + "08 19 26 56 67", + "14", + "02" + ], + [ + 1571, + "46AF2341-F648-425D-8343-117626DDD550", + 1571, + 1434769320, + "708543", + 1434769320, + "708543", + "{\n}", + "2015-06-19T00:00:00Z", + "04 35 36 52 68", + "08", + "03" + ], + [ + 1573, + "4C88ED32-DEA2-4D0D-B0BC-735ECA9A3C83", + 1573, + 1435114948, + "708543", + 1435114948, + "708543", + "{\n}", + "2015-06-23T00:00:00Z", + "06 13 38 56 70", + "02", + "05" + ], + [ + 1575, + "0FAD5736-617A-4582-A81A-3B61984F2B61", + 1575, + 1435374132, + "708543", + 1435374132, + "708543", + "{\n}", + "2015-06-26T00:00:00Z", + "12 23 33 47 50", + "03", + "05" + ], + [ + 1577, + "5E53C0D5-0652-4D7F-9F12-E3167CA63C1F", + 1577, + 1435719666, + "708543", + 1435719666, + "708543", + "{\n}", + "2015-06-30T00:00:00Z", + "11 17 34 43 50", + "15", + "04" + ], + [ + 1579, + "B9EBA90D-732D-4A17-9675-4BE770E869AF", + 1579, + 1435980252, + "708543", + 1435980252, + "708543", + "{\n}", + "2015-07-03T00:00:00Z", + "33 50 64 71 72", + "09", + "04" + ], + [ + 1581, + "F786B892-2A7D-4C1E-8C50-9044D07A78DB", + 1581, + 1436324525, + "708543", + 1436324525, + "708543", + "{\n}", + "2015-07-07T00:00:00Z", + "06 15 16 28 49", + "14", + "03" + ], + [ + 1583, + "173F799E-8486-47D5-A2E8-55D828DEDFC1", + 1583, + 1436583671, + "708543", + 1436583671, + "708543", + null, + "2015-07-10T00:00:00Z", + "24 27 45 51 54", + "08", + "03" + ], + [ + 1584, + "2885C9A3-6363-42C9-BCE8-AD2C652986CB", + 1584, + 1436929328, + "708543", + 1436929328, + "708543", + null, + "2015-07-14T00:00:00Z", + "19 24 30 35 72", + "05", + "03" + ], + [ + 1585, + "E5F4CC7B-147B-42BA-B75D-2BAE8021C6ED", + 1585, + 1437188486, + "708543", + 1437188486, + "708543", + null, + "2015-07-17T00:00:00Z", + "06 17 30 31 41", + "15", + "03" + ], + [ + 1586, + "E4A64E1F-7F45-4D23-A5BE-FB8B31FB1BC0", + 1586, + 1437534086, + "708543", + 1437534086, + "708543", + null, + "2015-07-21T00:00:00Z", + "20 30 62 65 74", + "01", + "05" + ], + [ + 1587, + "B2F7936C-6001-4234-B9B9-681131049B3D", + 1587, + 1437793264, + "708543", + 1437793264, + "708543", + null, + "2015-07-24T00:00:00Z", + "10 12 26 60 62", + "13", + "05" + ], + [ + 1588, + "CB5C79BF-C111-42EA-B656-345263A124FA", + 1588, + 1438138886, + "708543", + 1438138886, + "708543", + null, + "2015-07-28T00:00:00Z", + "08 35 61 68 75", + "15", + "05" + ], + [ + 1589, + "DBF152CB-ECCE-40CC-834A-E35E6D3198EA", + 1589, + 1438398127, + "708543", + 1438398127, + "708543", + null, + "2015-07-31T00:00:00Z", + "28 32 33 40 46", + "10", + "04" + ], + [ + 1590, + "1AAE9761-BA0D-4883-9981-BEB91B225B68", + 1590, + 1438743707, + "708543", + 1438743707, + "708543", + null, + "2015-08-04T00:00:00Z", + "02 19 44 51 57", + "14", + "02" + ], + [ + 1591, + "C72F41A6-3F86-4EA0-A05B-ECC42BF5068A", + 1591, + 1439002932, + "708543", + 1439002932, + "708543", + null, + "2015-08-07T00:00:00Z", + "01 38 53 63 66", + "10", + "03" + ], + [ + 1592, + "6FEA722E-6A92-4AAA-A853-9186C57C50F3", + 1592, + 1439348526, + "708543", + 1439348526, + "708543", + null, + "2015-08-11T00:00:00Z", + "03 08 29 57 68", + "08", + "04" + ], + [ + 1593, + "CFA8B480-20C9-4999-9546-F1A8CB997E35", + 1593, + 1439607747, + "708543", + 1439607747, + "708543", + null, + "2015-08-14T00:00:00Z", + "12 15 20 52 71", + "03", + "04" + ], + [ + 1594, + "4346D64A-3084-4333-9808-7BEA3322BB67", + 1594, + 1439953329, + "708543", + 1439953329, + "708543", + null, + "2015-08-18T00:00:00Z", + "02 07 33 39 53", + "09", + "03" + ], + [ + 1595, + "D3193CB6-30E4-4F8C-A26C-B7F0B11FC519", + 1595, + 1440212561, + "708543", + 1440212561, + "708543", + null, + "2015-08-21T00:00:00Z", + "13 15 21 41 72", + "01", + "05" + ], + [ + 1596, + "4275034A-4B46-439E-B76B-7EAE60AB3B57", + 1596, + 1440558107, + "708543", + 1440558107, + "708543", + null, + "2015-08-25T00:00:00Z", + "05 44 54 59 63", + "01", + "05" + ], + [ + 1597, + "19875C2F-4710-4402-997B-06277EB1DD3B", + 1597, + 1440817288, + "708543", + 1440817288, + "708543", + null, + "2015-08-28T00:00:00Z", + "13 35 40 60 68", + "09", + "04" + ], + [ + 1598, + "9E1E52A1-49E3-44F8-8A8B-E0AE76939ED0", + 1598, + 1441162926, + "708543", + 1441162926, + "708543", + null, + "2015-09-01T00:00:00Z", + "02 05 35 40 54", + "13", + "05" + ], + [ + 1599, + "ABBF4221-3651-4E33-9826-778CDB6160D5", + 1599, + 1441422137, + "708543", + 1441422137, + "708543", + null, + "2015-09-04T00:00:00Z", + "17 21 39 52 57", + "05", + "05" + ], + [ + 1600, + "F966B71B-2043-42CD-95C3-E1D052D0F5DC", + 1600, + 1441767706, + "708543", + 1441767706, + "708543", + null, + "2015-09-08T00:00:00Z", + "19 20 36 41 46", + "07", + "03" + ], + [ + 1601, + "6C0212B9-27FE-4779-8E1E-4E978B393488", + 1601, + 1442026906, + "708543", + 1442026906, + "708543", + null, + "2015-09-11T00:00:00Z", + "05 11 31 50 67", + "14", + "02" + ], + [ + 1602, + "951A886B-09C7-40FE-8D21-65BFE67E0E20", + 1602, + 1442372505, + "708543", + 1442372505, + "708543", + null, + "2015-09-15T00:00:00Z", + "07 20 35 49 56", + "09", + "04" + ], + [ + 1603, + "8B5F5037-DEB5-44AA-B5DE-D76E18D731DC", + 1603, + 1442631785, + "708543", + 1442631785, + "708543", + null, + "2015-09-18T00:00:00Z", + "17 34 35 51 65", + "07", + "03" + ], + [ + 1604, + "F7432096-1416-4186-AD4E-A36B61D0FDF3", + 1604, + 1442977285, + "708543", + 1442977285, + "708543", + null, + "2015-09-22T00:00:00Z", + "28 30 38 45 51", + "08", + "05" + ], + [ + 1605, + "33D70780-01EA-441A-9A4C-990859DC0629", + 1605, + 1443236506, + "708543", + 1443236506, + "708543", + null, + "2015-09-25T00:00:00Z", + "03 08 38 51 64", + "04", + "05" + ], + [ + 1606, + "C0905F04-1938-4970-AB55-09034B99C92B", + 1606, + 1443582127, + "708543", + 1443582127, + "708543", + null, + "2015-09-29T00:00:00Z", + "08 21 30 61 62", + "09", + "03" + ], + [ + 1607, + "181D106E-63BE-4A21-8A82-973C9467C233", + 1607, + 1443841309, + "708543", + 1443841309, + "708543", + null, + "2015-10-02T00:00:00Z", + "04 14 29 31 47", + "09", + "02" + ], + [ + 1608, + "E40045A0-5E29-4C8E-8CB2-6BD75D932427", + 1608, + 1444186906, + "708543", + 1444186906, + "708543", + null, + "2015-10-06T00:00:00Z", + "17 58 63 64 66", + "13", + "03" + ], + [ + 1609, + "861F130E-42CC-4654-8650-1D386AC20D62", + 1609, + 1444446107, + "708543", + 1444446107, + "708543", + null, + "2015-10-09T00:00:00Z", + "08 09 21 63 75", + "14", + "04" + ], + [ + 1610, + "ECD5BFB6-8892-41CC-B760-EDD8AAB9B93B", + 1610, + 1444791707, + "708543", + 1444791707, + "708543", + null, + "2015-10-13T00:00:00Z", + "07 09 24 38 52", + "01", + "05" + ], + [ + 1611, + "8E5AF013-320C-4B04-81E7-18A40F090924", + 1611, + 1445050907, + "708543", + 1445050907, + "708543", + null, + "2015-10-16T00:00:00Z", + "02 38 48 61 68", + "04", + "03" + ], + [ + 1612, + "3F86F0A3-0657-4C23-964C-B2597E46EED3", + 1612, + 1445396526, + "708543", + 1445396526, + "708543", + null, + "2015-10-20T00:00:00Z", + "06 25 35 38 52", + "04", + "04" + ], + [ + 1613, + "39DEFA41-D1AF-4254-ACC8-2CF8FB9196EB", + 1613, + 1445655706, + "708543", + 1445655706, + "708543", + null, + "2015-10-23T00:00:00Z", + "25 32 37 45 70", + "01", + "05" + ], + [ + 1614, + "6CF15757-6420-41C6-977F-DBD65C34F437", + 1614, + 1446001285, + "708543", + 1446001285, + "708543", + null, + "2015-10-27T00:00:00Z", + "09 26 27 29 74", + "04", + "03" + ], + [ + 1615, + "BF4C8D3B-3CD2-443A-B733-49700D3AF505", + 1615, + 1446260527, + "708543", + 1446260527, + "708543", + null, + "2015-10-30T00:00:00Z", + "17 41 51 53 56", + "15", + "05" + ], + [ + 1616, + "24AC2580-F864-456E-95BE-C6451E52DAA8", + 1616, + 1446606108, + "708543", + 1446606108, + "708543", + null, + "2015-11-03T00:00:00Z", + "16 29 44 69 74", + "12", + "05" + ], + [ + 1617, + "AF9AC066-EA3E-4A56-A549-69462973239E", + 1617, + 1446865313, + "708543", + 1446865313, + "708543", + null, + "2015-11-06T00:00:00Z", + "10 31 35 50 72", + "08", + "03" + ], + [ + 1618, + "5B523B94-4392-493C-8B77-37AAAD523BD0", + 1618, + 1447210947, + "708543", + 1447210947, + "708543", + null, + "2015-11-10T00:00:00Z", + "08 17 20 45 71", + "04", + "04" + ], + [ + 1619, + "33E35597-2F1E-4EA8-B8AE-B408573042C6", + 1619, + 1447470107, + "708543", + 1447470107, + "708543", + null, + "2015-11-13T00:00:00Z", + "17 18 31 35 59", + "09", + "05" + ], + [ + 1620, + "012E2E76-2B89-43BE-807D-24F86894DB3F", + 1620, + 1447815708, + "708543", + 1447815708, + "708543", + null, + "2015-11-17T00:00:00Z", + "12 14 18 24 61", + "10", + "03" + ], + [ + 1621, + "5C3E6FAB-3A63-45F4-BABF-0F2A7B05721A", + 1621, + 1448074906, + "708543", + 1448074906, + "708543", + null, + "2015-11-20T00:00:00Z", + "09 12 29 37 67", + "15", + "02" + ], + [ + 1622, + "50AB6256-911B-4734-B098-A1C7E029FC50", + 1622, + 1448420505, + "708543", + 1448420505, + "708543", + null, + "2015-11-24T00:00:00Z", + "02 19 30 38 70", + "08", + "04" + ], + [ + 1623, + "733C5B78-D944-42F9-9D39-206B69395C1C", + 1623, + 1448679706, + "708543", + 1448679706, + "708543", + null, + "2015-11-27T00:00:00Z", + "16 20 39 56 59", + "12", + "03" + ], + [ + 1624, + "3466B9EB-25AE-493B-9F81-A70C296687D6", + 1624, + 1449025305, + "708543", + 1449025305, + "708543", + null, + "2015-12-01T00:00:00Z", + "05 07 25 50 59", + "12", + "02" + ], + [ + 1625, + "BFDA9763-E55B-4E68-AC4A-64FC5BEA7290", + 1625, + 1449284488, + "708543", + 1449284488, + "708543", + null, + "2015-12-04T00:00:00Z", + "26 42 47 61 73", + "06", + "05" + ], + [ + 1626, + "FB3F13D9-F108-4F20-9550-5597912CFBE5", + 1626, + 1449630108, + "708543", + 1449630108, + "708543", + null, + "2015-12-08T00:00:00Z", + "07 17 37 49 73", + "15", + "03" + ], + [ + 1627, + "9E08A0BF-C5E0-48BE-B88D-D740895745C3", + 1627, + 1449889348, + "708543", + 1449889348, + "708543", + null, + "2015-12-11T00:00:00Z", + "14 20 43 54 69", + "05", + "04" + ], + [ + 1628, + "B94BCB4B-037B-4CD2-AF74-C91D52F1180F", + 1628, + 1450234926, + "708543", + 1450234926, + "708543", + null, + "2015-12-15T00:00:00Z", + "18 25 47 51 61", + "05", + "05" + ], + [ + 1629, + "B5B2B02B-14B7-4157-9A7B-EC5F8BFB91EE", + 1629, + 1450494130, + "708543", + 1450494130, + "708543", + null, + "2015-12-18T00:00:00Z", + "06 23 24 28 62", + "07", + "05" + ], + [ + 1630, + "94CC0B9B-F3D5-4AF1-91EC-2E80DA049A3E", + 1630, + 1450839805, + "708543", + 1450839805, + "708543", + null, + "2015-12-22T00:00:00Z", + "11 21 40 50 70", + "15", + "03" + ], + [ + 1631, + "7D95C3DB-8346-4A0A-99F9-8388D3455F05", + 1631, + 1451098926, + "708543", + 1451098926, + "708543", + null, + "2015-12-25T00:00:00Z", + "15 25 29 44 51", + "04", + "04" + ], + [ + 1632, + "2C7475AA-BF40-446B-AF68-4D0F75B8C6F8", + 1632, + 1451444486, + "708543", + 1451444486, + "708543", + null, + "2015-12-29T00:00:00Z", + "20 25 55 62 74", + "07", + "03" + ], + [ + 1633, + "C76B3278-31E5-4212-9F91-3A9B8FB8FEE7", + 1633, + 1451703685, + "708543", + 1451703685, + "708543", + null, + "2016-01-01T00:00:00Z", + "07 18 37 38 39", + "09", + "05" + ], + [ + 1634, + "1701538C-706D-4F58-BEAD-E85A125BAA93", + 1634, + 1452049285, + "708543", + 1452049285, + "708543", + null, + "2016-01-05T00:00:00Z", + "01 04 36 48 57", + "13", + "05" + ], + [ + 1635, + "2DECE042-B1F3-4BAF-92E2-ACC534B62171", + 1635, + 1452308424, + "708543", + 1452308424, + "708543", + null, + "2016-01-08T00:00:00Z", + "11 39 51 57 75", + "02", + "05" + ], + [ + 1636, + "59AA8588-E389-44D4-898A-B88D215B3180", + 1636, + 1452654246, + "708543", + 1452654246, + "708543", + null, + "2016-01-12T00:00:00Z", + "15 27 29 31 48", + "15", + "04" + ], + [ + 1637, + "EB18630E-DFCB-4DA9-B3C6-5D017B4CB539", + 1637, + 1452913329, + "708543", + 1452913329, + "708543", + null, + "2016-01-15T00:00:00Z", + "29 41 53 54 70", + "12", + "02" + ], + [ + 1638, + "6B3ECBDD-C850-4F5E-876A-3DFD62D39CC0", + 1638, + 1453258928, + "708543", + 1453258928, + "708543", + null, + "2016-01-19T00:00:00Z", + "02 17 31 39 47", + "09", + "02" + ], + [ + 1639, + "6CE292DA-B019-4C72-869B-33F7378737C2", + 1639, + 1453518148, + "708543", + 1453518148, + "708543", + null, + "2016-01-22T00:00:00Z", + "21 25 40 46 56", + "03", + "05" + ], + [ + 1640, + "941AFB5B-975C-451B-A1D4-9BB39C5CDE3A", + 1640, + 1453863685, + "708543", + 1453863685, + "708543", + null, + "2016-01-26T00:00:00Z", + "14 27 39 50 69", + "02", + "02" + ], + [ + 1641, + "DC2CFE1D-AF9A-4D71-A64B-7DC7F04F5F97", + 1641, + 1454122956, + "708543", + 1454122956, + "708543", + null, + "2016-01-29T00:00:00Z", + "20 28 49 51 52", + "06", + "02" + ], + [ + 1642, + "AC5D2A7E-4F80-4BDB-90A6-1D751A93ED93", + 1642, + 1454468486, + "708543", + 1454468486, + "708543", + null, + "2016-02-02T00:00:00Z", + "07 13 25 51 70", + "09", + "04" + ], + [ + 1643, + "1D000580-A2EF-43DF-9A38-DE8E08AACF5A", + 1643, + 1454727710, + "708543", + 1454727710, + "708543", + null, + "2016-02-05T00:00:00Z", + "04 06 23 55 75", + "02", + "03" + ], + [ + 1644, + "297A9E01-53D1-492F-8797-B9ED4B59084D", + 1644, + 1455073306, + "708543", + 1455073306, + "708543", + null, + "2016-02-09T00:00:00Z", + "03 42 46 56 71", + "13", + "04" + ], + [ + 1645, + "3F84D541-E559-42C0-A4CA-E18F9089AA1A", + 1645, + 1455332486, + "708543", + 1455332486, + "708543", + null, + "2016-02-12T00:00:00Z", + "01 07 44 68 73", + "01", + "03" + ], + [ + 1646, + "58DDCF16-F230-4B9A-BDA6-9FE0DB79CB4F", + 1646, + 1455678105, + "708543", + 1455678105, + "708543", + null, + "2016-02-16T00:00:00Z", + "09 31 33 46 64", + "04", + "03" + ], + [ + 1647, + "1538C7E2-86A5-4AD3-B5E1-5C3302FE635C", + 1647, + 1455937343, + "708543", + 1455937343, + "708543", + null, + "2016-02-19T00:00:00Z", + "02 27 41 50 75", + "04", + "04" + ], + [ + 1648, + "BFC5316B-4251-4DB1-8244-C6E36166125B", + 1648, + 1456282885, + "708543", + 1456282885, + "708543", + null, + "2016-02-23T00:00:00Z", + "16 32 39 53 57", + "10", + "05" + ], + [ + 1649, + "F93DA3B6-AAB1-4515-AAD0-7A6B4C31F7E6", + 1649, + 1456542125, + "708543", + 1456542125, + "708543", + null, + "2016-02-26T00:00:00Z", + "03 15 19 62 74", + "14", + "04" + ], + [ + 1650, + "DA81E261-D572-4CB3-8049-F9F396136F54", + 1650, + 1456887623, + "708543", + 1456887623, + "708543", + null, + "2016-03-01T00:00:00Z", + "01 29 33 34 55", + "06", + "05" + ], + [ + 1651, + "9CE887E3-9BF2-47C2-AED3-D6432D439626", + 1651, + 1457146912, + "708543", + 1457146912, + "708543", + null, + "2016-03-04T00:00:00Z", + "21 26 33 48 73", + "14", + "04" + ], + [ + 1652, + "F4CB0CEF-4734-48B2-BFD3-87C959B4BF60", + 1652, + 1457492506, + "708543", + 1457492506, + "708543", + null, + "2016-03-08T00:00:00Z", + "27 37 54 66 69", + "05", + "05" + ], + [ + 1653, + "E7EFFA53-90C7-4A52-BC33-A41CC6F35743", + 1653, + 1457751711, + "708543", + 1457751711, + "708543", + null, + "2016-03-11T00:00:00Z", + "14 18 48 54 71", + "13", + "04" + ], + [ + 1654, + "3B31A0E3-38D3-49F2-86FB-300A875F4FE0", + 1654, + 1458097306, + "708543", + 1458097306, + "708543", + null, + "2016-03-15T00:00:00Z", + "18 26 30 44 68", + "07", + "04" + ], + [ + 1655, + "7346468C-570F-4959-9C47-D3968389C666", + 1655, + 1458356507, + "708543", + 1458356507, + "708543", + null, + "2016-03-18T00:00:00Z", + "05 08 57 59 73", + "13", + "05" + ], + [ + 1656, + "F32E462E-EC01-48B3-99F6-AD6656CC8BAB", + 1656, + 1458702105, + "708543", + 1458702105, + "708543", + null, + "2016-03-22T00:00:00Z", + "06 19 34 38 70", + "05", + "05" + ], + [ + 1657, + "1E34E7D5-CDED-4CC3-907A-DB890B845B3C", + 1657, + 1458961346, + "708543", + 1458961346, + "708543", + null, + "2016-03-25T00:00:00Z", + "04 11 12 35 46", + "12", + "02" + ], + [ + 1658, + "2472EA19-C13B-4A4C-BB18-2770ED68FEB4", + 1658, + 1459306927, + "708543", + 1459306927, + "708543", + null, + "2016-03-29T00:00:00Z", + "33 38 40 46 49", + "15", + "05" + ], + [ + 1659, + "5EAA3253-2899-4961-A8AA-3AF3577FFB34", + 1659, + 1459566137, + "708543", + 1459566137, + "708543", + null, + "2016-04-01T00:00:00Z", + "25 28 33 41 69", + "06", + "02" + ], + [ + 1660, + "730C99CF-8304-4E8E-9DC8-37EDCB468913", + 1660, + 1459911705, + "708543", + 1459911705, + "708543", + null, + "2016-04-05T00:00:00Z", + "13 45 52 53 57", + "10", + "05" + ], + [ + 1661, + "635A8961-E360-46DC-99F2-82C35E8ADE1B", + 1661, + 1460170909, + "708543", + 1460170909, + "708543", + null, + "2016-04-08T00:00:00Z", + "31 38 52 65 71", + "15", + "03" + ], + [ + 1662, + "1684546A-9BF3-40A4-BB78-58D7E7C6EA78", + 1662, + 1460516506, + "708543", + 1460516506, + "708543", + null, + "2016-04-12T00:00:00Z", + "07 11 59 62 63", + "03", + "05" + ], + [ + 1663, + "5FAD000A-6227-42A4-B37B-5C3413481CA5", + 1663, + 1460775769, + "708543", + 1460775769, + "708543", + null, + "2016-04-15T00:00:00Z", + "09 10 34 37 73", + "09", + "05" + ], + [ + 1664, + "59F5A789-DE19-4648-B46D-196833A64927", + 1664, + 1461121307, + "708543", + 1461121307, + "708543", + null, + "2016-04-19T00:00:00Z", + "09 28 40 57 65", + "02", + "05" + ], + [ + 1665, + "1EFFFA59-5E1A-4F67-B885-4403A2EEA36B", + 1665, + 1461380489, + "708543", + 1461380489, + "708543", + null, + "2016-04-22T00:00:00Z", + "02 19 21 42 60", + "13", + "05" + ], + [ + 1666, + "3D1A81F6-FC6D-4A43-ABBD-124B3C6A15CB", + 1666, + 1461726127, + "708543", + 1461726127, + "708543", + null, + "2016-04-26T00:00:00Z", + "14 16 17 28 48", + "02", + "02" + ], + [ + 1667, + "9F063336-F99B-4B5A-B425-CAC2772F5DC5", + 1667, + 1461985308, + "708543", + 1461985308, + "708543", + null, + "2016-04-29T00:00:00Z", + "05 06 37 55 74", + "10", + "05" + ], + [ + 1668, + "9CA74EE6-461C-4AE1-96C1-7C9041086E65", + 1668, + 1462330906, + "708543", + 1462330906, + "708543", + null, + "2016-05-03T00:00:00Z", + "28 29 33 36 45", + "15", + "05" + ], + [ + 1669, + "28B4E2DD-05CD-435F-8144-373554ADCC07", + 1669, + 1462590107, + "708543", + 1462590107, + "708543", + null, + "2016-05-06T00:00:00Z", + "14 26 27 32 36", + "07", + "04" + ], + [ + 1670, + "E6136A00-E6CD-4564-9BDB-5D8658C1266F", + 1670, + 1462935706, + "708543", + 1462935706, + "708543", + null, + "2016-05-10T00:00:00Z", + "12 22 46 56 74", + "04", + "03" + ], + [ + 1671, + "144177A9-0D5C-41E0-87AA-B476C6076F11", + 1671, + 1463194908, + "708543", + 1463194908, + "708543", + null, + "2016-05-13T00:00:00Z", + "20 21 38 54 66", + "07", + "04" + ], + [ + 1672, + "77A58B0B-B6FB-43A3-99D5-C1A8962A3683", + 1672, + 1463540486, + "708543", + 1463540486, + "708543", + null, + "2016-05-17T00:00:00Z", + "17 24 27 48 75", + "06", + "03" + ], + [ + 1673, + "C90DB1FC-B9F4-44F1-BAE0-56541E75CB7C", + 1673, + 1463799716, + "708543", + 1463799716, + "708543", + null, + "2016-05-20T00:00:00Z", + "19 24 26 40 68", + "08", + "02" + ], + [ + 1674, + "31AA7AEB-7AFF-4E7C-AB41-1E61FF8D940E", + 1674, + 1464145306, + "708543", + 1464145306, + "708543", + null, + "2016-05-24T00:00:00Z", + "11 50 51 70 75", + "15", + "04" + ], + [ + 1675, + "4F63AC2C-8696-43A3-95D2-EFDBC8F93FA8", + 1675, + 1464404510, + "708543", + 1464404510, + "708543", + null, + "2016-05-27T00:00:00Z", + "18 41 50 68 70", + "09", + "03" + ], + [ + 1676, + "CFB15510-5ACA-4A3C-8120-F0B60A465B2D", + 1676, + 1464750107, + "708543", + 1464750107, + "708543", + null, + "2016-05-31T00:00:00Z", + "09 31 34 41 49", + "08", + "05" + ], + [ + 1677, + "C0EA471B-8C90-446F-948D-E5D2F022020A", + 1677, + 1465009311, + "708543", + 1465009311, + "708543", + null, + "2016-06-03T00:00:00Z", + "32 54 65 66 71", + "10", + "03" + ], + [ + 1678, + "35E2149B-4F4B-4FA7-8E33-1AFE8AABF057", + 1678, + 1465375783, + "708543", + 1465375783, + "708543", + null, + "2016-06-07T00:00:00Z", + "25 48 51 65 72", + "04", + "04" + ], + [ + 1679, + "6E874453-0778-4D7F-9713-0A4A3074D7E3", + 1679, + 1465614107, + "708543", + 1465614107, + "708543", + null, + "2016-06-10T00:00:00Z", + "34 61 66 67 68", + "07", + "05" + ], + [ + 1680, + "B21F8F34-9F29-463F-AC25-79A1FB778512", + 1680, + 1465959706, + "708543", + 1465959706, + "708543", + null, + "2016-06-14T00:00:00Z", + "36 37 38 52 62", + "06", + "05" + ], + [ + 1681, + "FF41B26A-4D95-46FD-90D6-BE358A9D7FEB", + 1681, + 1466218908, + "708543", + 1466218908, + "708543", + null, + "2016-06-17T00:00:00Z", + "20 23 30 44 59", + "09", + "05" + ], + [ + 1682, + "093F0CEB-4416-493E-BAC0-DADCBE527A9C", + 1682, + 1466564486, + "708543", + 1466564486, + "708543", + null, + "2016-06-21T00:00:00Z", + "06 13 21 49 50", + "10", + "05" + ], + [ + 1683, + "0DAE0DED-2901-4FFF-B384-08A5D8C81B7A", + 1683, + 1466823708, + "708543", + 1466823708, + "708543", + null, + "2016-06-24T00:00:00Z", + "11 14 54 57 63", + "11", + "05" + ], + [ + 1684, + "6C7CBB06-FAA1-480F-BF36-333F4BBD0CF2", + 1684, + 1467169306, + "708543", + 1467169306, + "708543", + null, + "2016-06-28T00:00:00Z", + "15 17 20 35 55", + "07", + "02" + ], + [ + 1685, + "C9B81A72-3904-4620-8449-41A9290F4FBE", + 1685, + 1467428490, + "708543", + 1467428490, + "708543", + null, + "2016-07-01T00:00:00Z", + "20 41 42 45 49", + "14", + "02" + ], + [ + 1686, + "D1A987BF-16F8-4ED2-96D9-B3E17B64D960", + 1686, + 1467774149, + "708543", + 1467774149, + "708543", + null, + "2016-07-05T00:00:00Z", + "29 46 53 64 73", + "10", + "05" + ], + [ + 1687, + "5F960802-C664-4042-9335-123EC20BE436", + 1687, + 1468033308, + "708543", + 1468033308, + "708543", + null, + "2016-07-08T00:00:00Z", + "08 19 20 55 73", + "05", + "02" + ], + [ + 1688, + "9D920794-C05B-485C-924A-9982FFD79A80", + 1688, + 1468378905, + "708543", + 1468378905, + "708543", + null, + "2016-07-12T00:00:00Z", + "06 08 22 46 68", + "04", + "04" + ], + [ + 1689, + "2144EBBB-EDA3-4E17-8BCB-A0682E6E2711", + 1689, + 1468638086, + "708543", + 1468638086, + "708543", + null, + "2016-07-15T00:00:00Z", + "16 51 52 56 58", + "04", + "02" + ], + [ + 1690, + "72A8E501-6FCD-44BE-9F14-D2428CFD296A", + 1690, + 1468983705, + "708543", + 1468983705, + "708543", + null, + "2016-07-19T00:00:00Z", + "03 34 54 65 66", + "04", + "05" + ], + [ + 1691, + "6C611C43-B591-4FB2-B377-364CC0E42915", + 1691, + 1469242907, + "708543", + 1469242907, + "708543", + null, + "2016-07-22T00:00:00Z", + "08 24 25 26 30", + "07", + "04" + ], + [ + 1692, + "984FA443-EEBD-4558-B81C-5C3067CB6BED", + 1692, + 1469588505, + "708543", + 1469588505, + "708543", + null, + "2016-07-26T00:00:00Z", + "01 04 31 36 54", + "09", + "03" + ], + [ + 1693, + "3DF563C7-1EC0-490A-AD2B-F65CC5700B89", + 1693, + 1469847706, + "708543", + 1469847706, + "708543", + null, + "2016-07-29T00:00:00Z", + "11 16 19 31 48", + "04", + "05" + ], + [ + 1694, + "4D0679B3-5476-40DD-89FE-93378295A073", + 1694, + 1470193285, + "708543", + 1470193285, + "708543", + null, + "2016-08-02T00:00:00Z", + "03 12 36 54 70", + "12", + "05" + ], + [ + 1695, + "5CB223B1-DD54-4EE5-BA4B-07A736D4DB1E", + 1695, + 1470452508, + "708543", + 1470452508, + "708543", + null, + "2016-08-05T00:00:00Z", + "05 18 28 54 74", + "06", + "04" + ], + [ + 1696, + "295B3CAA-7AD7-48EA-99C7-B607F0BD93C0", + 1696, + 1470798106, + "708543", + 1470798106, + "708543", + null, + "2016-08-09T00:00:00Z", + "12 19 20 44 66", + "01", + "05" + ], + [ + 1697, + "2D055176-5D79-486C-8319-DE5093C0C312", + 1697, + 1471057309, + "708543", + 1471057309, + "708543", + null, + "2016-08-12T00:00:00Z", + "04 41 44 56 69", + "10", + "04" + ], + [ + 1698, + "E3A9ADEA-B623-49E8-ABBB-51BB2E3D316E", + 1698, + 1471402905, + "708543", + 1471402905, + "708543", + null, + "2016-08-16T00:00:00Z", + "02 43 52 62 63", + "06", + "05" + ], + [ + 1699, + "B905E132-9D91-4425-A6B8-6912D3A5690B", + 1699, + 1471687310, + "708543", + 1471687310, + "708543", + null, + "2016-08-19T00:00:00Z", + "22 37 45 65 73", + "13", + "05" + ], + [ + 1700, + "DCC4E78B-4BF2-4D5D-8229-BCE9DEEB08C0", + 1700, + 1472076211, + "708543", + 1472076211, + "708543", + null, + "2016-08-23T00:00:00Z", + "02 07 46 61 66", + "01", + "02" + ], + [ + 1701, + "273F2248-9E79-4C97-B889-CAAD926DFA38", + 1701, + 1472292089, + "708543", + 1472292089, + "708543", + null, + "2016-08-26T00:00:00Z", + "10 11 31 41 44", + "14", + "02" + ], + [ + 1702, + "8B3C608A-E36D-43C1-9D18-1D403785CFB5", + 1702, + 1472637685, + "708543", + 1472637685, + "708543", + null, + "2016-08-30T00:00:00Z", + "28 32 41 51 71", + "11", + "04" + ], + [ + 1703, + "8E89CD90-99D4-4B76-9804-BFD0A158ED62", + 1703, + 1472896890, + "708543", + 1472896890, + "708543", + null, + "2016-09-02T00:00:00Z", + "22 28 41 46 60", + "03", + "03" + ], + [ + 1704, + "7D26FA54-E694-4AEA-95D9-6DEA7A996E01", + 1704, + 1473268935, + "708543", + 1473268935, + "708543", + null, + "2016-09-06T00:00:00Z", + "25 37 58 69 75", + "08", + "03" + ], + [ + 1705, + "FAF31467-323F-475D-A552-14C8A21B01CB", + 1705, + 1473501665, + "708543", + 1473501665, + "708543", + null, + "2016-09-09T00:00:00Z", + "01 34 43 44 63", + "11", + "04" + ], + [ + 1706, + "84C31388-A7AA-4E26-9744-E84E09C5552C", + 1706, + 1473847264, + "708543", + 1473847264, + "708543", + null, + "2016-09-13T00:00:00Z", + "06 15 17 39 56", + "15", + "03" + ], + [ + 1707, + "E6018DA5-15BE-41C0-9D93-531D725B4888", + 1707, + 1474106467, + "708543", + 1474106467, + "708543", + null, + "2016-09-16T00:00:00Z", + "13 21 28 34 40", + "15", + "03" + ], + [ + 1708, + "387F9D9B-8BC1-4DCA-B7E5-AC82FE71B8E0", + 1708, + 1474452067, + "708543", + 1474452067, + "708543", + null, + "2016-09-20T00:00:00Z", + "02 22 34 62 72", + "02", + "05" + ], + [ + 1709, + "9FAE3266-01D8-4DBF-9A73-3D8E1EEAC979", + 1709, + 1474711269, + "708543", + 1474711269, + "708543", + null, + "2016-09-23T00:00:00Z", + "01 05 08 25 62", + "14", + "03" + ], + [ + 1710, + "8B93C93D-B84C-4555-AED4-3D9CB3AA9776", + 1710, + 1475056863, + "708543", + 1475056863, + "708543", + null, + "2016-09-27T00:00:00Z", + "14 16 26 53 72", + "04", + "04" + ], + [ + 1711, + "4C02FA18-E31D-48D7-9452-7A226FDCB303", + 1711, + 1475316064, + "708543", + 1475316064, + "708543", + null, + "2016-09-30T00:00:00Z", + "21 30 47 50 57", + "09", + "05" + ], + [ + 1712, + "BF8A02DB-6CB8-4518-9D1A-39EDD6544658", + 1712, + 1475661663, + "708543", + 1475661663, + "708543", + null, + "2016-10-04T00:00:00Z", + "18 29 30 54 66", + "01", + "05" + ], + [ + 1713, + "1C68ACE2-D84B-455D-8013-D73C46A33B3C", + 1713, + 1475920864, + "708543", + 1475920864, + "708543", + null, + "2016-10-07T00:00:00Z", + "24 37 42 50 65", + "14", + "02" + ], + [ + 1714, + "F8296378-E773-4580-B6DE-BAFA66825C08", + 1714, + 1476266463, + "708543", + 1476266463, + "708543", + null, + "2016-10-11T00:00:00Z", + "36 39 42 45 48", + "03", + "02" + ], + [ + 1715, + "1674EA77-1766-4DBD-9B00-65384F2D0B10", + 1715, + 1476525664, + "708543", + 1476525664, + "708543", + null, + "2016-10-14T00:00:00Z", + "07 27 60 64 74", + "05", + "03" + ], + [ + 1716, + "9596D39E-D8E8-4CAA-B7FF-BA7A0B9849DD", + 1716, + 1476871264, + "708543", + 1476871264, + "708543", + null, + "2016-10-18T00:00:00Z", + "07 24 28 65 74", + "01", + "02" + ], + [ + 1717, + "00AA4CA5-AE12-4E21-8121-97BE38E6C511", + 1717, + 1477130472, + "708543", + 1477130472, + "708543", + null, + "2016-10-21T00:00:00Z", + "12 43 44 48 66", + "03", + "04" + ], + [ + 1718, + "0A85CFA3-AE43-4729-8311-BFBA0AADE5D4", + 1718, + 1477476148, + "708543", + 1477476148, + "708543", + null, + "2016-10-25T00:00:00Z", + "08 09 24 49 67", + "13", + "03" + ], + [ + 1719, + "9219598E-02DA-4CF5-854C-93EB269927DF", + 1719, + 1477735313, + "708543", + 1477735313, + "708543", + null, + "2016-10-28T00:00:00Z", + "07 38 46 57 66", + "02", + "05" + ], + [ + 1720, + "32C5372F-AFE4-4A21-A2C0-4476B4136338", + 1720, + 1478080862, + "708543", + 1478080862, + "708543", + null, + "2016-11-01T00:00:00Z", + "19 24 31 39 45", + "13", + "02" + ], + [ + 1721, + "E0DAAFDE-7446-4E41-8D60-38D73DF49F0E", + 1721, + 1478340064, + "708543", + 1478340064, + "708543", + null, + "2016-11-04T00:00:00Z", + "10 29 32 44 46", + "10", + "03" + ], + [ + 1722, + "0344AAB0-8B3C-43C2-9C70-9009F8E9FBA5", + 1722, + 1478689263, + "708543", + 1478689263, + "708543", + null, + "2016-11-08T00:00:00Z", + "46 48 53 61 74", + "12", + "04" + ], + [ + 1723, + "F348889E-FDF7-4DB6-8492-E44FD7807A44", + 1723, + 1478948463, + "708543", + 1478948463, + "708543", + null, + "2016-11-11T00:00:00Z", + "16 40 47 53 59", + "11", + "05" + ], + [ + 1724, + "45E178E8-1A5D-4C5C-A8CD-491DC5B192D7", + 1724, + 1479294062, + "708543", + 1479294062, + "708543", + null, + "2016-11-15T00:00:00Z", + "09 17 23 57 71", + "06", + "03" + ], + [ + 1725, + "6FF8AD19-266E-47BE-8DDC-0604876C3BAD", + 1725, + 1479553263, + "708543", + 1479553263, + "708543", + null, + "2016-11-18T00:00:00Z", + "31 32 49 55 58", + "15", + "05" + ], + [ + 1726, + "A78E2756-66C5-442A-AABD-F2EDC0E468EE", + 1726, + 1479899137, + "708543", + 1479899137, + "708543", + null, + "2016-11-22T00:00:00Z", + "01 43 45 66 69", + "07", + "05" + ], + [ + 1727, + "EFC65225-EFB0-4CDC-8EFF-626C6B56421E", + 1727, + 1480158306, + "708543", + 1480158306, + "708543", + null, + "2016-11-25T00:00:00Z", + "44 47 49 69 75", + "10", + "03" + ], + [ + 1728, + "60D9C9FE-16A3-4665-8B22-562BC0455695", + 1728, + 1480503662, + "708543", + 1480503662, + "708543", + null, + "2016-11-29T00:00:00Z", + "22 33 49 51 59", + "08", + "04" + ], + [ + 1729, + "4E86685E-363A-43CE-A927-4E327A8E0796", + 1729, + 1480762864, + "708543", + 1480762864, + "708543", + null, + "2016-12-02T00:00:00Z", + "03 33 35 49 51", + "01", + "02" + ], + [ + 1730, + "053614AB-69B8-4A4E-9309-3EAED9879AC4", + 1730, + 1481108463, + "708543", + 1481108463, + "708543", + null, + "2016-12-06T00:00:00Z", + "13 34 48 53 63", + "12", + "04" + ], + [ + 1731, + "DA02B9B1-5288-4D72-B13D-DAA2D3848E1D", + 1731, + 1481454064, + "708543", + 1481454064, + "708543", + null, + "2016-12-09T00:00:00Z", + "19 27 47 67 68", + "01", + "05" + ], + [ + 1732, + "3AD77F5E-F385-4384-8D55-6E0537C8371D", + 1732, + 1481713263, + "708543", + 1481713263, + "708543", + null, + "2016-12-13T00:00:00Z", + "02 15 26 34 41", + "14", + "05" + ], + [ + 1733, + "45ADFFB5-0863-456E-BBDA-A17A74B1B3FC", + 1733, + 1481972465, + "708543", + 1481972465, + "708543", + null, + "2016-12-16T00:00:00Z", + "01 08 15 36 43", + "06", + "05" + ], + [ + 1734, + "77491A99-CD4A-406E-9794-2EB82DEDB58D", + 1734, + 1482318191, + "708543", + 1482318191, + "708543", + null, + "2016-12-20T00:00:00Z", + "01 12 14 48 65", + "02", + "05" + ], + [ + 1735, + "714943E2-57A3-4101-8ED2-F4FC7530E30B", + 1735, + 1482577541, + "708543", + 1482577541, + "708543", + null, + "2016-12-23T00:00:00Z", + "21 30 39 60 69", + "15", + "05" + ], + [ + 1736, + "9283006E-6539-4923-B806-004B27DCFE8C", + 1736, + 1482922987, + "708543", + 1482922987, + "708543", + null, + "2016-12-27T00:00:00Z", + "02 28 30 38 39", + "11", + "04" + ], + [ + 1737, + "AE2B492D-A47C-482A-AD4D-10D664C3BA67", + 1737, + 1483182148, + "708543", + 1483182148, + "708543", + null, + "2016-12-30T00:00:00Z", + "06 21 33 39 43", + "02", + "02" + ], + [ + 1738, + "5D46057F-9D99-4702-81CC-4F49A38D643F", + 1738, + 1483527775, + "708543", + 1483527775, + "708543", + null, + "2017-01-03T00:00:00Z", + "14 16 23 49 53", + "12", + "02" + ], + [ + 1739, + "2D5234E0-E230-4272-91E3-8416C6B75BF6", + 1739, + 1483786929, + "708543", + 1483786929, + "708543", + null, + "2017-01-06T00:00:00Z", + "06 10 44 47 54", + "06", + "05" + ], + [ + 1740, + "3DC94C0A-7A60-45E1-A0E9-24383610F930", + 1740, + 1484132463, + "708543", + 1484132463, + "708543", + null, + "2017-01-10T00:00:00Z", + "11 20 40 41 59", + "15", + "05" + ], + [ + 1741, + "0301A455-E49F-4073-8F9D-503176FAC83E", + 1741, + 1484391663, + "708543", + 1484391663, + "708543", + null, + "2017-01-13T00:00:00Z", + "10 44 58 74 75", + "11", + "03" + ], + [ + 1742, + "F4F58F62-5E75-4002-BDEF-D80122F8413D", + 1742, + 1484737264, + "708543", + 1484737264, + "708543", + null, + "2017-01-17T00:00:00Z", + "20 31 54 56 59", + "03", + "05" + ], + [ + 1744, + "0B9EA1DD-8367-47A3-940D-66AB052177C6", + 1744, + 1485342205, + "708543", + 1485342205, + "708543", + null, + "2017-01-20T00:00:00Z", + "07 09 24 41 53", + "14", + "03" + ], + [ + 1745, + "63C31E5D-BA55-43C2-9E9B-9B4BA7DB0B74", + 1745, + 1485342246, + "708543", + 1485342246, + "708543", + null, + "2017-01-24T00:00:00Z", + "08 42 54 63 67", + "11", + "04" + ], + [ + 1746, + "759F3C65-541D-49FF-BE9A-28D067247072", + 1746, + 1485601284, + "708543", + 1485601284, + "708543", + null, + "2017-01-27T00:00:00Z", + "17 37 53 54 61", + "08", + "03" + ], + [ + 1747, + "E68E6833-8A5D-471C-854A-A8951B2FEC47", + 1747, + 1485946975, + "708543", + 1485946975, + "708543", + null, + "2017-01-31T00:00:00Z", + "03 14 27 62 72", + "04", + "03" + ], + [ + 1748, + "40A6F426-B63F-4829-813E-B85B848156A9", + 1748, + 1486206064, + "708543", + 1486206064, + "708543", + null, + "2017-02-03T00:00:00Z", + "03 06 29 30 64", + "03", + "05" + ], + [ + 1749, + "C6F73F48-40BF-485D-A2CD-473041C2F024", + 1749, + 1486551663, + "708543", + 1486551663, + "708543", + null, + "2017-02-07T00:00:00Z", + "23 28 37 56 71", + "12", + "05" + ], + [ + 1750, + "38FEE57B-E1E5-484E-923E-967FA6B59C7B", + 1750, + 1486810865, + "708543", + 1486810865, + "708543", + null, + "2017-02-10T00:00:00Z", + "32 39 51 62 75", + "14", + "05" + ], + [ + 1751, + "1ED88425-BBBE-481E-B401-8FB56251794C", + 1751, + 1487156483, + "708543", + 1487156483, + "708543", + null, + "2017-02-14T00:00:00Z", + "07 11 33 60 68", + "15", + "05" + ], + [ + 1752, + "50DC084A-AB4F-4CF9-9431-1242348550D7", + 1752, + 1487415663, + "708543", + 1487415663, + "708543", + null, + "2017-02-17T00:00:00Z", + "04 56 58 67 75", + "08", + "05" + ], + [ + 1753, + "3657D265-4C07-4890-BFA3-C188C1846DAF", + 1753, + 1487761263, + "708543", + 1487761263, + "708543", + null, + "2017-02-21T00:00:00Z", + "09 21 30 32 75", + "09", + "05" + ], + [ + 1754, + "D41829B2-3AA3-4663-9BAE-B7F2E91290E7", + 1754, + 1488020464, + "708543", + 1488020464, + "708543", + null, + "2017-02-24T00:00:00Z", + "12 29 33 42 68", + "14", + "03" + ], + [ + 1755, + "B0F99384-F7AE-402A-BACC-F6F317DC6DED", + 1755, + 1488366063, + "708543", + 1488366063, + "708543", + null, + "2017-02-28T00:00:00Z", + "20 33 45 58 69", + "04", + "02" + ], + [ + 1756, + "F8753135-AD9D-4059-9862-C4AA0AAB259C", + 1756, + 1488625264, + "708543", + 1488625264, + "708543", + null, + "2017-03-03T00:00:00Z", + "14 26 39 48 51", + "09", + "05" + ], + [ + 1757, + "D4F83543-9B57-40C6-A9DE-FCEE3E05B3CE", + 1757, + 1488970863, + "708543", + 1488970863, + "708543", + null, + "2017-03-07T00:00:00Z", + "03 30 45 53 68", + "11", + "03" + ], + [ + 1758, + "A4282612-1A7F-461F-81C4-DB4E6EEACD96", + 1758, + 1489230064, + "708543", + 1489230064, + "708543", + null, + "2017-03-10T00:00:00Z", + "26 38 42 58 70", + "05", + "05" + ], + [ + 1759, + "CE0B76F1-7657-4984-A22F-874F6106E232", + 1759, + 1489572063, + "708543", + 1489572063, + "708543", + null, + "2017-03-14T00:00:00Z", + "16 23 28 33 59", + "13", + "03" + ], + [ + 1760, + "0638F069-9AFE-4471-A553-D074B4574341", + 1760, + 1489831264, + "708543", + 1489831264, + "708543", + null, + "2017-03-17T00:00:00Z", + "11 27 31 58 60", + "10", + "04" + ], + [ + 1761, + "22420896-3EE1-4690-BFFF-564A46D017D7", + 1761, + 1490176862, + "708543", + 1490176862, + "708543", + null, + "2017-03-21T00:00:00Z", + "04 45 53 73 75", + "07", + "03" + ], + [ + 1762, + "DB64A17B-1CDD-4077-944B-CD8A6DCE8E76", + 1762, + 1490436062, + "708543", + 1490436062, + "708543", + null, + "2017-03-24T00:00:00Z", + "05 28 37 61 69", + "01", + "05" + ], + [ + 1763, + "3EA50957-B887-4FB0-AB54-70F5A9ED385C", + 1763, + 1490781664, + "708543", + 1490781664, + "708543", + null, + "2017-03-28T00:00:00Z", + "30 33 35 37 46", + "10", + "05" + ], + [ + 1764, + "9893AE26-8C83-4E1A-A74F-3563F9C980AE", + 1764, + 1491040863, + "708543", + 1491040863, + "708543", + null, + "2017-03-31T00:00:00Z", + "17 24 27 32 58", + "10", + "03" + ], + [ + 1765, + "B935B56A-C478-43EF-AF02-AC85613DF286", + 1765, + 1491386467, + "708543", + 1491386467, + "708543", + null, + "2017-04-04T00:00:00Z", + "13 24 34 35 55", + "09", + "05" + ], + [ + 1766, + "ED3D7FE2-51BC-4055-ADF6-05FDD98A75AE", + 1766, + 1491645663, + "708543", + 1491645663, + "708543", + null, + "2017-04-07T00:00:00Z", + "30 33 43 47 69", + "15", + "05" + ], + [ + 1767, + "EFA3E720-B90F-42BF-AAB4-7815B320B313", + 1767, + 1491991262, + "708543", + 1491991262, + "708543", + null, + "2017-04-11T00:00:00Z", + "19 34 35 38 49", + "08", + "05" + ], + [ + 1768, + "10D0ECDB-2152-4073-840D-78AE2A4085BD", + 1768, + 1492250463, + "708543", + 1492250463, + "708543", + null, + "2017-04-14T00:00:00Z", + "05 10 55 60 73", + "12", + "05" + ], + [ + 1769, + "AE102C01-DAE4-461A-9CC1-23B5B9694881", + 1769, + 1492596083, + "708543", + 1492596083, + "708543", + null, + "2017-04-18T00:00:00Z", + "08 29 30 43 64", + "06", + "03" + ], + [ + 1770, + "A6AD1EA5-6800-451A-ACDE-1187FAD9B566", + 1770, + 1492855281, + "708543", + 1492855281, + "708543", + null, + "2017-04-21T00:00:00Z", + "01 12 13 32 34", + "10", + "02" + ], + [ + 1771, + "17BE4C71-7B00-47D6-B4CE-1EFC7E3A2916", + 1771, + 1493200863, + "708543", + 1493200863, + "708543", + null, + "2017-04-25T00:00:00Z", + "03 13 33 40 50", + "02", + "04" + ], + [ + 1772, + "A020B997-F086-4F1B-99E8-36C46069D873", + 1772, + 1493460064, + "708543", + 1493460064, + "708543", + null, + "2017-04-28T00:00:00Z", + "06 13 18 20 31", + "13", + "04" + ], + [ + 1773, + "1727AFF8-9F51-4634-8E03-C5CF20E45000", + 1773, + 1493805664, + "708543", + 1493805664, + "708543", + null, + "2017-05-02T00:00:00Z", + "05 14 42 43 58", + "01", + "04" + ], + [ + 1774, + "30DFFCED-2E18-4FB6-BD33-62FD300F0E44", + 1774, + 1494064867, + "708543", + 1494064867, + "708543", + null, + "2017-05-05T00:00:00Z", + "04 23 33 47 53", + "07", + "04" + ], + [ + 1775, + "5976EE30-2E10-4BF9-BD9D-AD1C8E1EEFC1", + 1775, + 1494410464, + "708543", + 1494410464, + "708543", + null, + "2017-05-09T00:00:00Z", + "06 29 45 69 73", + "11", + "05" + ], + [ + 1776, + "6F450884-CDD9-4523-9265-FA369DD13916", + 1776, + 1494669666, + "708543", + 1494669666, + "708543", + null, + "2017-05-12T00:00:00Z", + "28 34 41 42 47", + "13", + "04" + ], + [ + 1777, + "E31793AD-5A3D-46D6-92CD-F913A92498CF", + 1777, + 1495015264, + "708543", + 1495015264, + "708543", + null, + "2017-05-16T00:00:00Z", + "04 35 39 56 72", + "11", + "05" + ], + [ + 1778, + "A2D9FAC3-749D-48A9-B5F4-CBE7C647FDE6", + 1778, + 1495274464, + "708543", + 1495274464, + "708543", + null, + "2017-05-19T00:00:00Z", + "01 04 05 24 30", + "01", + "03" + ], + [ + 1779, + "2C2AD6B7-7EFC-44E7-B605-9056848A94F8", + 1779, + 1495620065, + "708543", + 1495620065, + "708543", + null, + "2017-05-23T00:00:00Z", + "06 13 17 33 60", + "14", + "02" + ], + [ + 1780, + "05675B2E-FE56-4DC0-81FA-A8AB14DD214D", + 1780, + 1495879264, + "708543", + 1495879264, + "708543", + null, + "2017-05-26T00:00:00Z", + "25 26 28 37 56", + "05", + "03" + ], + [ + 1781, + "346129F8-E92D-43DF-91DE-B694AB06BF04", + 1781, + 1496224863, + "708543", + 1496224863, + "708543", + null, + "2017-05-30T00:00:00Z", + "05 20 32 37 67", + "05", + "05" + ], + [ + 1782, + "72417B49-381B-4F9A-BFE5-AC92EFF700DF", + 1782, + 1496484066, + "708543", + 1496484066, + "708543", + null, + "2017-06-02T00:00:00Z", + "07 42 57 69 72", + "10", + "03" + ], + [ + 1783, + "417815C8-6350-42FE-9DA2-BDA965D13F75", + 1783, + 1496829663, + "708543", + 1496829663, + "708543", + null, + "2017-06-06T00:00:00Z", + "03 05 16 49 75", + "05", + "03" + ], + [ + 1784, + "11947D29-85FA-4288-B16A-7673C450B25C", + 1784, + 1497088864, + "708543", + 1497088864, + "708543", + null, + "2017-06-09T00:00:00Z", + "03 16 28 33 37", + "09", + "05" + ], + [ + 1785, + "BA728323-F4EB-4037-AE22-37CA3D6FF2AE", + 1785, + 1497434463, + "708543", + 1497434463, + "708543", + null, + "2017-06-13T00:00:00Z", + "27 51 62 68 75", + "08", + "03" + ], + [ + 1786, + "D5161AD7-1ED0-45A6-803D-24D27B3B72AD", + 1786, + 1497693665, + "708543", + 1497693665, + "708543", + null, + "2017-06-16T00:00:00Z", + "18 22 26 30 44", + "09", + "05" + ], + [ + 1787, + "E58ABE14-127D-49FF-8B96-F3A43551985D", + 1787, + 1498039264, + "708543", + 1498039264, + "708543", + null, + "2017-06-20T00:00:00Z", + "02 15 41 49 63", + "03", + "03" + ], + [ + 1788, + "E0AB73AA-FB82-4D5A-BBE6-3C8C7F4C35E2", + 1788, + 1498298464, + "708543", + 1498298464, + "708543", + null, + "2017-06-23T00:00:00Z", + "12 20 53 66 74", + "11", + "02" + ], + [ + 1789, + "317B88B2-1E7B-4988-8E08-DB2D6B93FDB5", + 1789, + 1498644063, + "708543", + 1498644063, + "708543", + null, + "2017-06-27T00:00:00Z", + "04 21 45 52 57", + "14", + "04" + ], + [ + 1790, + "704B021F-90F0-430C-827F-344C6716B574", + 1790, + 1498903263, + "708543", + 1498903263, + "708543", + null, + "2017-06-30T00:00:00Z", + "10 38 51 55 64", + "06", + "05" + ], + [ + 1791, + "77AE800A-DB56-460A-968D-FC03DCDA98FC", + 1791, + 1499248863, + "708543", + 1499248863, + "708543", + null, + "2017-07-04T00:00:00Z", + "16 39 47 53 71", + "15", + "04" + ], + [ + 1792, + "B699871F-3188-410B-BD10-CF831C3ED41D", + 1792, + 1499508064, + "708543", + 1499508064, + "708543", + null, + "2017-07-07T00:00:00Z", + "02 09 11 28 60", + "10", + "05" + ], + [ + 1793, + "DB8207CA-BD86-4ABB-B937-8FB0177A4AE9", + 1793, + 1499853662, + "708543", + 1499853662, + "708543", + null, + "2017-07-11T00:00:00Z", + "07 18 24 55 74", + "10", + "02" + ], + [ + 1794, + "7E9FDDE3-A7BC-436C-9A65-D81EE060EAD0", + 1794, + 1500112863, + "708543", + 1500112863, + "708543", + null, + "2017-07-14T00:00:00Z", + "11 12 24 32 73", + "01", + "04" + ], + [ + 1795, + "1212E8CB-D109-45ED-90A6-C568D2E40C2E", + 1795, + 1500458464, + "708543", + 1500458464, + "708543", + null, + "2017-07-18T00:00:00Z", + "08 12 23 51 73", + "06", + "04" + ], + [ + 1796, + "FD732321-5433-49B1-AC3E-22D79F295C62", + 1796, + 1500717663, + "708543", + 1500717663, + "708543", + null, + "2017-07-21T00:00:00Z", + "18 31 36 50 74", + "10", + "04" + ], + [ + 1797, + "63EA61AF-4FF9-404F-B971-DB540DBFE9D5", + 1797, + 1501063263, + "708543", + 1501063263, + "708543", + null, + "2017-07-25T00:00:00Z", + "02 05 26 58 60", + "06", + "03" + ], + [ + 1798, + "DC590A73-39DE-4FCC-93B3-07241059B1E0", + 1798, + 1501322464, + "708543", + 1501322464, + "708543", + null, + "2017-07-28T00:00:00Z", + "04 06 31 49 52", + "11", + "03" + ] + ] +} diff --git a/test/inputs/json/misc/617e8.json b/test/inputs/json/misc/617e8.json index f4ab7f0e3..9e174b997 100644 --- a/test/inputs/json/misc/617e8.json +++ b/test/inputs/json/misc/617e8.json @@ -1,716 +1,4741 @@ { - "meta" : { - "view" : { - "id" : "kwxv-fwze", - "name" : "Lottery Cash 4 Life Winning Numbers: Beginning 2014", - "attribution" : "New York State Gaming Commission", - "attributionLink" : "http://nylottery.ny.gov/wps/portal/Home/Lottery/home/your+lottery/drawing+results/drawingresults_cash4life", - "averageRating" : 0, - "category" : "Government & Finance", - "createdAt" : 1403034474, - "description" : "Go to http://on.ny.gov/1xRIvPz on the New York Lottery website for past Cash 4 Life results and payouts.", - "displayType" : "table", - "downloadCount" : 24233, - "hideFromCatalog" : false, - "hideFromDataJson" : false, - "indexUpdatedAt" : 1501261257, - "locale" : "", - "newBackend" : false, - "numberOfComments" : 0, - "oid" : 26475943, - "provenance" : "official", - "publicationAppendEnabled" : false, - "publicationDate" : 1501236068, - "publicationGroup" : 1619790, - "publicationStage" : "published", - "rowsUpdatedAt" : 1501236065, - "rowsUpdatedBy" : "xzik-pf59", - "tableId" : 14359574, - "totalTimesRated" : 0, - "viewCount" : 4833328, - "viewLastModified" : 1501236068, - "viewType" : "tabular", - "columns" : [ { - "id" : -1, - "name" : "sid", - "dataTypeName" : "meta_data", - "fieldName" : ":sid", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "id", - "dataTypeName" : "meta_data", - "fieldName" : ":id", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "position", - "dataTypeName" : "meta_data", - "fieldName" : ":position", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "created_at", - "dataTypeName" : "meta_data", - "fieldName" : ":created_at", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "created_meta", - "dataTypeName" : "meta_data", - "fieldName" : ":created_meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "updated_at", - "dataTypeName" : "meta_data", - "fieldName" : ":updated_at", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "updated_meta", - "dataTypeName" : "meta_data", - "fieldName" : ":updated_meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : -1, - "name" : "meta", - "dataTypeName" : "meta_data", - "fieldName" : ":meta", - "position" : 0, - "renderTypeName" : "meta_data", - "format" : { }, - "flags" : [ "hidden" ] - }, { - "id" : 313240570, - "name" : "Draw Date", - "dataTypeName" : "calendar_date", - "fieldName" : "draw_date", - "position" : 1, - "renderTypeName" : "calendar_date", - "tableColumnId" : 20316627, - "width" : 140, - "cachedContents" : { - "largest" : "2017-07-27T00:00:00", - "non_null" : 326, - "null" : 0, - "top" : [ { - "item" : "2017-03-16T00:00:00", - "count" : 20 - }, { - "item" : "2017-03-20T00:00:00", - "count" : 19 - }, { - "item" : "2017-03-23T00:00:00", - "count" : 18 - }, { - "item" : "2017-03-27T00:00:00", - "count" : 17 - }, { - "item" : "2017-03-30T00:00:00", - "count" : 16 - }, { - "item" : "2017-04-03T00:00:00", - "count" : 15 - }, { - "item" : "2017-04-06T00:00:00", - "count" : 14 - }, { - "item" : "2017-04-10T00:00:00", - "count" : 13 - }, { - "item" : "2017-04-13T00:00:00", - "count" : 12 - }, { - "item" : "2017-04-17T00:00:00", - "count" : 11 - }, { - "item" : "2017-04-20T00:00:00", - "count" : 10 - }, { - "item" : "2017-04-24T00:00:00", - "count" : 9 - }, { - "item" : "2017-04-27T00:00:00", - "count" : 8 - }, { - "item" : "2017-05-01T00:00:00", - "count" : 7 - }, { - "item" : "2017-05-04T00:00:00", - "count" : 6 - }, { - "item" : "2017-05-08T00:00:00", - "count" : 5 - }, { - "item" : "2017-05-11T00:00:00", - "count" : 4 - }, { - "item" : "2017-05-15T00:00:00", - "count" : 3 - }, { - "item" : "2017-05-18T00:00:00", - "count" : 2 - }, { - "item" : "2017-05-22T00:00:00", - "count" : 1 - } ], - "smallest" : "2014-06-16T00:00:00" - }, - "format" : { - "view" : "date", - "align" : "center" + "meta": { + "view": { + "id": "kwxv-fwze", + "name": "Lottery Cash 4 Life Winning Numbers: Beginning 2014", + "attribution": "New York State Gaming Commission", + "attributionLink": "http://nylottery.ny.gov/wps/portal/Home/Lottery/home/your+lottery/drawing+results/drawingresults_cash4life", + "averageRating": 0, + "category": "Government & Finance", + "createdAt": 1403034474, + "description": "Go to http://on.ny.gov/1xRIvPz on the New York Lottery website for past Cash 4 Life results and payouts.", + "displayType": "table", + "downloadCount": 24233, + "hideFromCatalog": false, + "hideFromDataJson": false, + "indexUpdatedAt": 1501261257, + "locale": "", + "newBackend": false, + "numberOfComments": 0, + "oid": 26475943, + "provenance": "official", + "publicationAppendEnabled": false, + "publicationDate": 1501236068, + "publicationGroup": 1619790, + "publicationStage": "published", + "rowsUpdatedAt": 1501236065, + "rowsUpdatedBy": "xzik-pf59", + "tableId": 14359574, + "totalTimesRated": 0, + "viewCount": 4833328, + "viewLastModified": 1501236068, + "viewType": "tabular", + "columns": [ + { + "id": -1, + "name": "sid", + "dataTypeName": "meta_data", + "fieldName": ":sid", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "id", + "dataTypeName": "meta_data", + "fieldName": ":id", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "position", + "dataTypeName": "meta_data", + "fieldName": ":position", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "created_at", + "dataTypeName": "meta_data", + "fieldName": ":created_at", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "created_meta", + "dataTypeName": "meta_data", + "fieldName": ":created_meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "updated_at", + "dataTypeName": "meta_data", + "fieldName": ":updated_at", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "updated_meta", + "dataTypeName": "meta_data", + "fieldName": ":updated_meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": -1, + "name": "meta", + "dataTypeName": "meta_data", + "fieldName": ":meta", + "position": 0, + "renderTypeName": "meta_data", + "format": {}, + "flags": ["hidden"] + }, + { + "id": 313240570, + "name": "Draw Date", + "dataTypeName": "calendar_date", + "fieldName": "draw_date", + "position": 1, + "renderTypeName": "calendar_date", + "tableColumnId": 20316627, + "width": 140, + "cachedContents": { + "largest": "2017-07-27T00:00:00Z", + "non_null": 326, + "null": 0, + "top": [ + { + "item": "2017-03-16T00:00:00Z", + "count": 20 + }, + { + "item": "2017-03-20T00:00:00Z", + "count": 19 + }, + { + "item": "2017-03-23T00:00:00Z", + "count": 18 + }, + { + "item": "2017-03-27T00:00:00Z", + "count": 17 + }, + { + "item": "2017-03-30T00:00:00Z", + "count": 16 + }, + { + "item": "2017-04-03T00:00:00Z", + "count": 15 + }, + { + "item": "2017-04-06T00:00:00Z", + "count": 14 + }, + { + "item": "2017-04-10T00:00:00Z", + "count": 13 + }, + { + "item": "2017-04-13T00:00:00Z", + "count": 12 + }, + { + "item": "2017-04-17T00:00:00Z", + "count": 11 + }, + { + "item": "2017-04-20T00:00:00Z", + "count": 10 + }, + { + "item": "2017-04-24T00:00:00Z", + "count": 9 + }, + { + "item": "2017-04-27T00:00:00Z", + "count": 8 + }, + { + "item": "2017-05-01T00:00:00Z", + "count": 7 + }, + { + "item": "2017-05-04T00:00:00Z", + "count": 6 + }, + { + "item": "2017-05-08T00:00:00Z", + "count": 5 + }, + { + "item": "2017-05-11T00:00:00Z", + "count": 4 + }, + { + "item": "2017-05-15T00:00:00Z", + "count": 3 + }, + { + "item": "2017-05-18T00:00:00Z", + "count": 2 + }, + { + "item": "2017-05-22T00:00:00Z", + "count": 1 + } + ], + "smallest": "2014-06-16T00:00:00Z" + }, + "format": { + "view": "date", + "align": "center" + } + }, + { + "id": 313240571, + "name": "Winning Numbers", + "dataTypeName": "text", + "description": "Winning numbers", + "fieldName": "winning_numbers", + "position": 2, + "renderTypeName": "text", + "tableColumnId": 20316628, + "width": 188, + "cachedContents": { + "largest": "46 50 56 57 58", + "non_null": 326, + "null": 0, + "top": [ + { + "item": "13 14 36 48 57", + "count": 20 + }, + { + "item": "13 22 41 46 56", + "count": 19 + }, + { + "item": "02 28 30 39 53", + "count": 18 + }, + { + "item": "32 42 58 59 60", + "count": 17 + }, + { + "item": "24 38 40 44 49", + "count": 16 + }, + { + "item": "12 15 28 46 57", + "count": 15 + }, + { + "item": "04 06 17 48 53", + "count": 14 + }, + { + "item": "20 22 37 55 56", + "count": 13 + }, + { + "item": "17 19 49 50 56", + "count": 12 + }, + { + "item": "05 09 12 33 46", + "count": 11 + }, + { + "item": "22 23 37 56 60", + "count": 10 + }, + { + "item": "19 33 35 36 48", + "count": 9 + }, + { + "item": "02 20 27 29 53", + "count": 8 + }, + { + "item": "07 19 23 24 40", + "count": 7 + }, + { + "item": "01 02 17 24 38", + "count": 6 + }, + { + "item": "22 34 42 46 57", + "count": 5 + }, + { + "item": "06 20 30 34 36", + "count": 4 + }, + { + "item": "02 27 28 34 39", + "count": 3 + }, + { + "item": "04 29 30 55 58", + "count": 2 + }, + { + "item": "04 06 25 31 47", + "count": 1 + } + ], + "smallest": "01 02 14 29 59" + }, + "format": { + "align": "center" + } + }, + { + "id": 313240572, + "name": "Cash Ball", + "dataTypeName": "text", + "description": "Cash ball", + "fieldName": "cash_ball", + "position": 3, + "renderTypeName": "text", + "tableColumnId": 20316629, + "width": 134, + "cachedContents": { + "largest": "04", + "non_null": 326, + "null": 0, + "top": [ + { + "item": "03", + "count": 20 + }, + { + "item": "02", + "count": 19 + }, + { + "item": "04", + "count": 18 + }, + { + "item": "01", + "count": 17 + } + ], + "smallest": "01" + }, + "format": { + "align": "center" + } + } + ], + "grants": [ + { + "inherited": false, + "type": "viewer", + "flags": ["public"] + } + ], + "metadata": { + "custom_fields": { + "Notes": { + "Notes": "The information contained on these pages is believed to be accurate. In the event of a discrepancy between the information displayed on this Web site concerning winning numbers and payouts and the information contained in the official and certified files maintained by the New York Lottery's Drawing Unit, those maintained by the Drawing Unit shall prevail." + }, + "Common Core": { + "Contact Email": "opendata@its.ny.gov", + "Publisher": "State of New York", + "Contact Name": "Open Data NY" + }, + "Dataset Summary": { + "Granularity": "By draw", + "Coverage": "Statewide", + "Data Frequency": "Twice weekly", + "Posting Frequency": "Twice weekly", + "Dataset Owner": "New York State Gaming Commission", + "Organization": "The New York Lottery", + "Time Period": "Beginning 6/16/2014", + "Contact Information": "Info@gaming.ny.gov" + }, + "Additional Resources": { + "See Also": "http://www.gaming.ny.gov/" + }, + "Dataset Information": { + "Agency": "Gaming Commission, New York State" + } + }, + "renderTypeConfig": { + "visible": { + "table": true + } + }, + "availableDisplayTypes": ["table", "fatrow", "page"], + "jsonQuery": { + "order": [ + { + "ascending": false, + "columnFieldName": "draw_date" + } + ] + }, + "rdfSubject": "0", + "attachments": [ + { + "blobId": "", + "assetId": "TVLdpXbCpZhhc1DSgHaSY0QOSV_L7LM1wGCcx_Txx5k", + "name": "NYSGAM_Cash4Life_Overview.pdf", + "filename": "NYSGAM_Cash4Life_Overview.pdf" + }, + { + "blobId": "", + "assetId": "8eMY9KKmZL0Ig4zEfycwd2X8qhZlv3mzJUBoIOYrO9o", + "name": "NYSGAM_Cash4Life_Winning_Numbers_DataDictionary.pdf", + "filename": "NYSGAM_Cash4Life_Winning_Numbers_DataDictionary.pdf" + } + ] + }, + "owner": { + "id": "xzik-pf59", + "displayName": "NY Open Data", + "profileImageUrlLarge": "/api/users/xzik-pf59/profile_images/LARGE", + "profileImageUrlMedium": "/api/users/xzik-pf59/profile_images/THUMB", + "profileImageUrlSmall": "/api/users/xzik-pf59/profile_images/TINY", + "roleName": "publisher", + "screenName": "NY Open Data", + "rights": [ + "create_datasets", + "edit_others_datasets", + "edit_nominations", + "approve_nominations", + "moderate_comments", + "manage_stories", + "feature_items", + "change_configurations", + "view_domain", + "view_others_datasets", + "create_pages", + "edit_pages", + "view_goals", + "view_dashboards", + "edit_goals", + "edit_dashboards", + "manage_provenance", + "view_story", + "view_unpublished_story", + "view_all_dataset_status_logs", + "use_data_connectors" + ] + }, + "query": { + "orderBys": [ + { + "ascending": false, + "expression": { + "columnId": 313240570, + "type": "column" + } + } + ] + }, + "rights": ["read"], + "tableAuthor": { + "id": "xzik-pf59", + "displayName": "NY Open Data", + "profileImageUrlLarge": "/api/users/xzik-pf59/profile_images/LARGE", + "profileImageUrlMedium": "/api/users/xzik-pf59/profile_images/THUMB", + "profileImageUrlSmall": "/api/users/xzik-pf59/profile_images/TINY", + "roleName": "publisher", + "screenName": "NY Open Data", + "rights": [ + "create_datasets", + "edit_others_datasets", + "edit_nominations", + "approve_nominations", + "moderate_comments", + "manage_stories", + "feature_items", + "change_configurations", + "view_domain", + "view_others_datasets", + "create_pages", + "edit_pages", + "view_goals", + "view_dashboards", + "edit_goals", + "edit_dashboards", + "manage_provenance", + "view_story", + "view_unpublished_story", + "view_all_dataset_status_logs", + "use_data_connectors" + ] + }, + "tags": ["cash 4 life", "new york lottery", "winning", "results"], + "flags": ["default", "restorable", "restorePossibleForType"] } - }, { - "id" : 313240571, - "name" : "Winning Numbers", - "dataTypeName" : "text", - "description" : "Winning numbers", - "fieldName" : "winning_numbers", - "position" : 2, - "renderTypeName" : "text", - "tableColumnId" : 20316628, - "width" : 188, - "cachedContents" : { - "largest" : "46 50 56 57 58", - "non_null" : 326, - "null" : 0, - "top" : [ { - "item" : "13 14 36 48 57", - "count" : 20 - }, { - "item" : "13 22 41 46 56", - "count" : 19 - }, { - "item" : "02 28 30 39 53", - "count" : 18 - }, { - "item" : "32 42 58 59 60", - "count" : 17 - }, { - "item" : "24 38 40 44 49", - "count" : 16 - }, { - "item" : "12 15 28 46 57", - "count" : 15 - }, { - "item" : "04 06 17 48 53", - "count" : 14 - }, { - "item" : "20 22 37 55 56", - "count" : 13 - }, { - "item" : "17 19 49 50 56", - "count" : 12 - }, { - "item" : "05 09 12 33 46", - "count" : 11 - }, { - "item" : "22 23 37 56 60", - "count" : 10 - }, { - "item" : "19 33 35 36 48", - "count" : 9 - }, { - "item" : "02 20 27 29 53", - "count" : 8 - }, { - "item" : "07 19 23 24 40", - "count" : 7 - }, { - "item" : "01 02 17 24 38", - "count" : 6 - }, { - "item" : "22 34 42 46 57", - "count" : 5 - }, { - "item" : "06 20 30 34 36", - "count" : 4 - }, { - "item" : "02 27 28 34 39", - "count" : 3 - }, { - "item" : "04 29 30 55 58", - "count" : 2 - }, { - "item" : "04 06 25 31 47", - "count" : 1 - } ], - "smallest" : "01 02 14 29 59" - }, - "format" : { - "align" : "center" - } - }, { - "id" : 313240572, - "name" : "Cash Ball", - "dataTypeName" : "text", - "description" : "Cash ball", - "fieldName" : "cash_ball", - "position" : 3, - "renderTypeName" : "text", - "tableColumnId" : 20316629, - "width" : 134, - "cachedContents" : { - "largest" : "04", - "non_null" : 326, - "null" : 0, - "top" : [ { - "item" : "03", - "count" : 20 - }, { - "item" : "02", - "count" : 19 - }, { - "item" : "04", - "count" : 18 - }, { - "item" : "01", - "count" : 17 - } ], - "smallest" : "01" - }, - "format" : { - "align" : "center" - } - } ], - "grants" : [ { - "inherited" : false, - "type" : "viewer", - "flags" : [ "public" ] - } ], - "metadata" : { - "custom_fields" : { - "Notes" : { - "Notes" : "The information contained on these pages is believed to be accurate. In the event of a discrepancy between the information displayed on this Web site concerning winning numbers and payouts and the information contained in the official and certified files maintained by the New York Lottery's Drawing Unit, those maintained by the Drawing Unit shall prevail." - }, - "Common Core" : { - "Contact Email" : "opendata@its.ny.gov", - "Publisher" : "State of New York", - "Contact Name" : "Open Data NY" - }, - "Dataset Summary" : { - "Granularity" : "By draw", - "Coverage" : "Statewide", - "Data Frequency" : "Twice weekly", - "Posting Frequency" : "Twice weekly", - "Dataset Owner" : "New York State Gaming Commission", - "Organization" : "The New York Lottery", - "Time Period" : "Beginning 6/16/2014", - "Contact Information" : "Info@gaming.ny.gov" - }, - "Additional Resources" : { - "See Also" : "http://www.gaming.ny.gov/" - }, - "Dataset Information" : { - "Agency" : "Gaming Commission, New York State" - } - }, - "renderTypeConfig" : { - "visible" : { - "table" : true - } - }, - "availableDisplayTypes" : [ "table", "fatrow", "page" ], - "jsonQuery" : { - "order" : [ { - "ascending" : false, - "columnFieldName" : "draw_date" - } ] - }, - "rdfSubject" : "0", - "attachments" : [ { - "blobId" : "", - "assetId" : "TVLdpXbCpZhhc1DSgHaSY0QOSV_L7LM1wGCcx_Txx5k", - "name" : "NYSGAM_Cash4Life_Overview.pdf", - "filename" : "NYSGAM_Cash4Life_Overview.pdf" - }, { - "blobId" : "", - "assetId" : "8eMY9KKmZL0Ig4zEfycwd2X8qhZlv3mzJUBoIOYrO9o", - "name" : "NYSGAM_Cash4Life_Winning_Numbers_DataDictionary.pdf", - "filename" : "NYSGAM_Cash4Life_Winning_Numbers_DataDictionary.pdf" - } ] - }, - "owner" : { - "id" : "xzik-pf59", - "displayName" : "NY Open Data", - "profileImageUrlLarge" : "/api/users/xzik-pf59/profile_images/LARGE", - "profileImageUrlMedium" : "/api/users/xzik-pf59/profile_images/THUMB", - "profileImageUrlSmall" : "/api/users/xzik-pf59/profile_images/TINY", - "roleName" : "publisher", - "screenName" : "NY Open Data", - "rights" : [ "create_datasets", "edit_others_datasets", "edit_nominations", "approve_nominations", "moderate_comments", "manage_stories", "feature_items", "change_configurations", "view_domain", "view_others_datasets", "create_pages", "edit_pages", "view_goals", "view_dashboards", "edit_goals", "edit_dashboards", "manage_provenance", "view_story", "view_unpublished_story", "view_all_dataset_status_logs", "use_data_connectors" ] - }, - "query" : { - "orderBys" : [ { - "ascending" : false, - "expression" : { - "columnId" : 313240570, - "type" : "column" - } - } ] - }, - "rights" : [ "read" ], - "tableAuthor" : { - "id" : "xzik-pf59", - "displayName" : "NY Open Data", - "profileImageUrlLarge" : "/api/users/xzik-pf59/profile_images/LARGE", - "profileImageUrlMedium" : "/api/users/xzik-pf59/profile_images/THUMB", - "profileImageUrlSmall" : "/api/users/xzik-pf59/profile_images/TINY", - "roleName" : "publisher", - "screenName" : "NY Open Data", - "rights" : [ "create_datasets", "edit_others_datasets", "edit_nominations", "approve_nominations", "moderate_comments", "manage_stories", "feature_items", "change_configurations", "view_domain", "view_others_datasets", "create_pages", "edit_pages", "view_goals", "view_dashboards", "edit_goals", "edit_dashboards", "manage_provenance", "view_story", "view_unpublished_story", "view_all_dataset_status_logs", "use_data_connectors" ] - }, - "tags" : [ "cash 4 life", "new york lottery", "winning", "results" ], - "flags" : [ "default", "restorable", "restorePossibleForType" ] - } - }, - "data" : [ [ 1, "012CAE53-5033-48B4-BADA-E2EDB4C82D76", 1, 1403096267, "707756", 1403096267, "707756", "{\n}", "2014-06-16T00:00:00", "09 36 44 53 59", "03" ] -, [ 3, "9A327854-2BA9-474A-B392-EBBDF0806559", 3, 1403233340, "708543", 1403233340, "708543", "{\n}", "2014-06-19T00:00:00", "08 13 43 56 60", "02" ] -, [ 5, "B03A03EA-661A-452F-9084-6B95EDE9EFEA", 5, 1403578864, "708543", 1403578864, "708543", "{\n}", "2014-06-23T00:00:00", "05 16 21 33 47", "04" ] -, [ 7, "205077A2-7F97-42B3-9BF8-592B6E314EC6", 7, 1403861033, "708543", 1403861033, "708543", "{\n}", "2014-06-26T00:00:00", "15 22 51 52 58", "03" ] -, [ 9, "038EA5F2-C6F5-4DA9-B57A-EA185D8A609B", 9, 1404183739, "708543", 1404183739, "708543", "{\n}", "2014-06-30T00:00:00", "01 04 10 28 33", "02" ] -, [ 11, "FB8E9108-DA9A-4D9C-9BDF-3727F7A862AA", 11, 1404442822, "708543", 1404442822, "708543", "{\n}", "2014-07-03T00:00:00", "08 10 25 28 31", "02" ] -, [ 13, "49BC2CEE-8BEB-4A2B-9951-D0669FC80A57", 13, 1404788422, "708543", 1404788422, "708543", "{\n}", "2014-07-07T00:00:00", "11 13 23 54 55", "02" ] -, [ 15, "81B00141-368C-4C89-A943-5512A585E9B6", 15, 1405047685, "708543", 1405047685, "708543", "{\n}", "2014-07-10T00:00:00", "11 12 31 54 59", "03" ] -, [ 17, "B2217278-0DF2-4BD9-993B-CBF3E38005D8", 17, 1405393265, "708543", 1405393265, "708543", "{\n}", "2014-07-14T00:00:00", "09 19 34 37 49", "02" ] -, [ 19, "7A02B89B-7A1E-41F6-A4DD-D25CE447B9DE", 19, 1405652467, "708543", 1405652467, "708543", "{\n}", "2014-07-17T00:00:00", "08 09 22 46 51", "01" ] -, [ 21, "3BFADF1B-EDD6-415A-8790-05AAEECFB7C3", 21, 1405998064, "708543", 1405998064, "708543", "{\n}", "2014-07-21T00:00:00", "04 06 11 24 31", "03" ] -, [ 23, "EAAAAB4F-C17E-4129-B18A-5A2197AFBEAC", 23, 1406257265, "708543", 1406257265, "708543", "{\n}", "2014-07-24T00:00:00", "05 20 35 43 48", "03" ] -, [ 25, "68097553-6CC4-4787-865A-747B130D5EBE", 25, 1406602865, "708543", 1406602865, "708543", "{\n}", "2014-07-28T00:00:00", "06 15 31 51 53", "02" ] -, [ 27, "76996EA0-DD54-4EB5-B5C2-7FF8FE6E6386", 27, 1406862065, "708543", 1406862065, "708543", "{\n}", "2014-07-31T00:00:00", "13 25 26 32 58", "01" ] -, [ 29, "91616BD7-CD64-4F70-92AD-260AED90744E", 29, 1407207665, "708543", 1407207665, "708543", "{\n}", "2014-08-04T00:00:00", "17 21 36 48 60", "03" ] -, [ 31, "DB3F3DF6-C19A-4970-9F76-060B7D1DD383", 31, 1407466895, "708543", 1407466895, "708543", "{\n}", "2014-08-07T00:00:00", "03 18 38 40 49", "02" ] -, [ 33, "60819CBF-EA03-477B-ABF2-0BD2242A9438", 33, 1407812457, "708543", 1407812457, "708543", "{\n}", "2014-08-11T00:00:00", "05 10 33 48 57", "03" ] -, [ 35, "0C13DB12-A55A-42A7-A2BB-66D0C7C50645", 35, 1408071655, "708543", 1408071655, "708543", "{\n}", "2014-08-14T00:00:00", "03 11 34 46 60", "02" ] -, [ 37, "1839C767-92D9-4A0D-8897-02DB365BA7C7", 37, 1408417266, "708543", 1408417266, "708543", "{\n}", "2014-08-18T00:00:00", "06 10 29 44 57", "02" ] -, [ 39, "774C4C27-7C65-48D1-89AA-89C3D9AF5C6B", 39, 1408676455, "708543", 1408676455, "708543", "{\n}", "2014-08-21T00:00:00", "11 24 40 43 47", "02" ] -, [ 41, "C1877239-185A-4B3D-946E-F5512047707A", 41, 1409022066, "708543", 1409022066, "708543", "{\n}", "2014-08-25T00:00:00", "06 08 34 40 59", "04" ] -, [ 43, "0BB0CCA8-09D9-475F-B97A-8084266C10C3", 43, 1409281275, "708543", 1409281275, "708543", "{\n}", "2014-08-28T00:00:00", "12 24 27 38 49", "02" ] -, [ 45, "6DB0C8AB-5075-4BB1-9149-2A7BEC028612", 45, 1409626855, "708543", 1409626855, "708543", "{\n}", "2014-09-01T00:00:00", "09 21 27 45 53", "02" ] -, [ 47, "0374F671-02F0-4D00-AB0F-689BD851BBFF", 47, 1409886057, "708543", 1409886057, "708543", "{\n}", "2014-09-04T00:00:00", "03 21 28 32 56", "03" ] -, [ 49, "DA294964-7674-4E5A-BBBC-D5452940E330", 49, 1410249467, "708543", 1410249467, "708543", "{\n}", "2014-09-08T00:00:00", "01 17 23 44 45", "02" ] -, [ 51, "60E229E5-B1B3-4EB3-B235-ECE3320C2151", 51, 1410490873, "708543", 1410490873, "708543", "{\n}", "2014-09-11T00:00:00", "12 44 56 58 59", "02" ] -, [ 53, "AF1C8CC1-1FBA-4462-9314-ED07B787BEF7", 53, 1410857335, "708543", 1410857335, "708543", "{\n}", "2014-09-15T00:00:00", "03 05 09 32 56", "01" ] -, [ 55, "C7EB51A3-93B2-4A41-9CB7-E19F2294C189", 55, 1411138891, "708543", 1411138891, "708543", "{\n}", "2014-09-18T00:00:00", "05 10 11 24 28", "03" ] -, [ 57, "AF5594CC-74AE-4B25-8D3A-E75AB61F320C", 57, 1411484595, "708543", 1411484595, "708543", "{\n}", "2014-09-22T00:00:00", "28 39 40 53 54", "01" ] -, [ 59, "A5A781A5-5521-4B22-B514-F5DFA3F6D25A", 59, 1411741475, "708543", 1411741475, "708543", "{\n}", "2014-09-25T00:00:00", "09 11 28 30 41", "04" ] -, [ 61, "6942D491-BAE6-4106-BBFF-9692E675D407", 61, 1412089290, "708543", 1412089290, "708543", "{\n}", "2014-09-29T00:00:00", "19 36 37 43 50", "01" ] -, [ 63, "756710CC-B5F0-4283-8BA0-3689222F93BC", 63, 1412348485, "708543", 1412348485, "708543", "{\n}", "2014-10-02T00:00:00", "23 34 35 44 52", "01" ] -, [ 65, "EFC086DD-DE15-4DD8-9310-16911270BB89", 65, 1412737309, "708543", 1412737309, "708543", "{\n}", "2014-10-06T00:00:00", "16 30 37 52 55", "03" ] -, [ 67, "AA1A6D71-13B5-44E0-9B81-0BB34DAE7EA4", 67, 1412910109, "708543", 1412910109, "708543", "{\n}", "2014-10-09T00:00:00", "23 26 32 50 57", "04" ] -, [ 69, "1335B8F0-D3F5-4F48-B286-3F798CBC701D", 69, 1413255710, "708543", 1413255710, "708543", "{\n}", "2014-10-13T00:00:00", "10 13 49 54 57", "04" ] -, [ 71, "46182F8D-360D-488B-A4F9-05514FA57EFB", 71, 1413514894, "708543", 1413514894, "708543", "{\n}", "2014-10-16T00:00:00", "12 13 20 28 45", "04" ] -, [ 73, "0EBA077B-BE4A-4D7C-9944-8741019B368E", 73, 1413860491, "708543", 1413860491, "708543", "{\n}", "2014-10-20T00:00:00", "08 16 43 52 59", "03" ] -, [ 75, "4E97E80D-7E86-48D3-A356-461BDC559E2D", 75, 1414119691, "708543", 1414119691, "708543", "{\n}", "2014-10-23T00:00:00", "09 22 24 36 54", "01" ] -, [ 77, "D79ED4C9-E736-4503-9F8F-44E814128A11", 77, 1414465287, "708543", 1414465287, "708543", "{\n}", "2014-10-27T00:00:00", "06 09 28 40 41", "01" ] -, [ 79, "792BD778-BFDB-4778-A82C-FC9A225D944F", 79, 1414724491, "708543", 1414724491, "708543", "{\n}", "2014-10-30T00:00:00", "19 22 29 38 53", "01" ] -, [ 81, "896D69B7-9696-4D2F-9534-540A5EFF5C46", 81, 1415113288, "708543", 1415113288, "708543", "{\n}", "2014-11-03T00:00:00", "03 27 28 49 52", "04" ] -, [ 83, "0D294751-4AF6-47C1-A95E-9D9709CC0F7F", 83, 1415329353, "708543", 1415329353, "708543", "{\n}", "2014-11-06T00:00:00", "03 07 14 20 32", "03" ] -, [ 85, "9FA03830-2A74-4DD2-85A0-0ABDDA81D1D1", 85, 1415804550, "708543", 1415804550, "708543", "{\n}", "2014-11-10T00:00:00", "07 21 30 53 55", "02" ] -, [ 87, "38EC3289-915B-4D7B-8B5A-6C70EC890078", 87, 1415934097, "708543", 1415934097, "708543", "{\n}", "2014-11-13T00:00:00", "07 08 16 49 56", "04" ] -, [ 89, "4BB65C7D-C7AE-4B3B-B97B-04AB4F0F8837", 89, 1416279689, "708543", 1416279689, "708543", "{\n}", "2014-11-17T00:00:00", "08 23 37 38 58", "01" ] -, [ 91, "AACF639A-77E9-4D8C-8998-75A1A9279F42", 91, 1416538890, "708543", 1416538890, "708543", "{\n}", "2014-11-20T00:00:00", "02 40 46 59 60", "02" ] -, [ 93, "E4FBC55A-B4ED-468A-A44C-CE5445C21A1B", 93, 1416884510, "708543", 1416884510, "708543", "{\n}", "2014-11-24T00:00:00", "08 25 26 33 56", "01" ] -, [ 95, "776BD8AD-7BBC-45E0-8E90-39811986C977", 95, 1417143689, "708543", 1417143689, "708543", "{\n}", "2014-11-27T00:00:00", "09 30 43 51 55", "03" ] -, [ 97, "EBF6ECC5-0B85-438D-8A46-9FCE5E519E29", 97, 1417489289, "708543", 1417489289, "708543", "{\n}", "2014-12-01T00:00:00", "04 07 33 50 55", "01" ] -, [ 99, "33276E54-A25A-4344-9522-952660A46FC6", 99, 1417748490, "708543", 1417748490, "708543", "{\n}", "2014-12-04T00:00:00", "01 15 21 41 60", "04" ] -, [ 101, "1A59B642-300B-4971-97A2-2EEB3B617A96", 101, 1418094070, "708543", 1418094070, "708543", "{\n}", "2014-12-08T00:00:00", "04 11 14 46 59", "04" ] -, [ 103, "A9B2120A-45B0-4B5A-91A6-2CD14B6CB804", 103, 1418353294, "708543", 1418353294, "708543", "{\n}", "2014-12-11T00:00:00", "12 22 27 35 49", "04" ] -, [ 105, "BF8D8512-533A-47D8-B958-1D53A359D5F6", 105, 1418698895, "708543", 1418698895, "708543", "{\n}", "2014-12-15T00:00:00", "08 22 31 38 40", "03" ] -, [ 107, "520953D2-4DFD-404D-8D61-713CBDD641E5", 107, 1418958101, "708543", 1418958101, "708543", "{\n}", "2014-12-18T00:00:00", "20 22 26 27 43", "02" ] -, [ 109, "5A0507CF-B794-43A6-A30D-9B830091D8A3", 109, 1419303692, "708543", 1419303692, "708543", "{\n}", "2014-12-22T00:00:00", "03 17 30 50 55", "03" ] -, [ 111, "E12FA573-ED28-4726-8E80-9783452BECA0", 111, 1419562871, "708543", 1419562871, "708543", "{\n}", "2014-12-25T00:00:00", "05 14 22 37 60", "02" ] -, [ 113, "E194E4AF-152C-4229-88F9-45F7629E0ABF", 113, 1419908521, "708543", 1419908521, "708543", "{\n}", "2014-12-29T00:00:00", "08 09 35 37 41", "04" ] -, [ 115, "BBB2C4CC-93DE-4015-B820-FB007F1CB762", 115, 1420167754, "708543", 1420167754, "708543", "{\n}", "2015-01-01T00:00:00", "13 19 20 21 35", "02" ] -, [ 117, "ED96AB53-FCDB-46E9-8440-3655AC3FB34C", 117, 1420513290, "708543", 1420513290, "708543", "{\n}", "2015-01-05T00:00:00", "12 23 29 38 43", "03" ] -, [ 119, "0C5A0B65-8D2D-4839-8786-5081A47668C8", 119, 1420772494, "708543", 1420772494, "708543", "{\n}", "2015-01-08T00:00:00", "16 28 38 43 45", "03" ] -, [ 121, "D42D2EBF-7700-4F5B-9BC0-FD5637A19FD9", 121, 1421118090, "708543", 1421118090, "708543", "{\n}", "2015-01-12T00:00:00", "01 05 11 39 47", "01" ] -, [ 123, "008F206D-92EB-4A20-B887-E6689B25E3E2", 123, 1421377288, "708543", 1421377288, "708543", "{\n}", "2015-01-15T00:00:00", "12 15 22 25 27", "03" ] -, [ 125, "0E8CB1B4-823F-4E60-A773-1A939E96DC06", 125, 1421722893, "708543", 1421722893, "708543", "{\n}", "2015-01-19T00:00:00", "18 29 47 52 53", "03" ] -, [ 127, "2AA47495-72C5-4086-98EF-CDE64374946E", 127, 1421982100, "708543", 1421982100, "708543", "{\n}", "2015-01-22T00:00:00", "08 11 35 47 60", "02" ] -, [ 129, "60873354-72B3-48C2-8CB3-13BD630B4DBC", 129, 1422327709, "708543", 1422327709, "708543", "{\n}", "2015-01-26T00:00:00", "01 20 24 46 57", "01" ] -, [ 131, "9E0C5355-4E03-477D-A073-4BED0B3A24C1", 131, 1422586894, "708543", 1422586894, "708543", "{\n}", "2015-01-29T00:00:00", "08 24 28 57 60", "02" ] -, [ 133, "EFA8A999-2C71-4357-81B8-DD1FBBBEDB2A", 133, 1422932500, "708543", 1422932500, "708543", "{\n}", "2015-02-02T00:00:00", "04 08 17 20 21", "04" ] -, [ 135, "42FB45D1-A071-4F57-9CE2-08A01CDDF478", 135, 1423191694, "708543", 1423191694, "708543", "{\n}", "2015-02-05T00:00:00", "14 17 38 40 45", "02" ] -, [ 137, "11ECE352-720D-42CC-9205-4CDF6500FA83", 137, 1423537294, "708543", 1423537294, "708543", "{\n}", "2015-02-09T00:00:00", "09 17 36 38 53", "04" ] -, [ 139, "93BCF5A7-5C23-4672-AC03-40720ED5F22B", 139, 1423796489, "708543", 1423796489, "708543", "{\n}", "2015-02-12T00:00:00", "06 11 32 56 60", "02" ] -, [ 141, "D322B0C0-56A8-4374-A29A-80CFDE1D6543", 141, 1424142113, "708543", 1424142113, "708543", "{\n}", "2015-02-16T00:00:00", "06 26 35 40 43", "02" ] -, [ 143, "DC6AD720-4BF5-4C4F-95A0-752F916BBEFF", 143, 1424401290, "708543", 1424401290, "708543", "{\n}", "2015-02-19T00:00:00", "18 43 51 52 60", "04" ] -, [ 145, "9E251D18-D632-4E4E-BE91-389DAC1E83EF", 145, 1424746886, "708543", 1424746886, "708543", "{\n}", "2015-02-23T00:00:00", "01 14 20 21 43", "04" ] -, [ 147, "E4F2CA88-3B82-48DF-8BCC-0F48ED01025E", 147, 1425049289, "708543", 1425049289, "708543", "{\n}", "2015-02-26T00:00:00", "03 16 20 38 49", "03" ] -, [ 149, "A0BC2444-1A83-4EC9-A5C7-DD4BEBEC8BAC", 149, 1425351687, "708543", 1425351687, "708543", "{\n}", "2015-03-02T00:00:00", "08 23 27 38 47", "04" ] -, [ 151, "DEA71FE8-C1A6-4822-AFAA-21E11860F30E", 151, 1425610898, "708543", 1425610898, "708543", "{\n}", "2015-03-05T00:00:00", "10 22 46 47 48", "04" ] -, [ 153, "7CDE1F9C-B37A-4688-B430-4B876FF1E3AC", 153, 1425956488, "708543", 1425956488, "708543", "{\n}", "2015-03-09T00:00:00", "19 34 35 54 57", "03" ] -, [ 155, "05A29298-CC69-4E09-BEA3-5A2C9BA94CAA", 155, 1426561286, "708543", 1426561286, "708543", "{\n}", "2015-03-16T00:00:00", "12 18 33 44 46", "01" ] -, [ 157, "6CCFF205-6249-4098-BCEE-133280F60530", 157, 1426820509, "708543", 1426820509, "708543", "{\n}", "2015-03-19T00:00:00", "02 12 28 51 54", "01" ] -, [ 159, "E1D85EB5-A7E8-419E-9BBC-4FC4E30128A1", 159, 1427166105, "708543", 1427166105, "708543", "{\n}", "2015-03-23T00:00:00", "18 26 28 35 36", "04" ] -, [ 161, "F4F2FB7D-6BD3-4DF3-A3BB-A8572B4F99DA", 161, 1427425305, "708543", 1427425305, "708543", "{\n}", "2015-03-26T00:00:00", "06 35 36 47 53", "02" ] -, [ 163, "5BCAA6C8-600B-42A8-AE34-259DC41EC39B", 163, 1427770905, "708543", 1427770905, "708543", "{\n}", "2015-03-30T00:00:00", "09 23 43 45 52", "02" ] -, [ 165, "845ECC12-550A-4E48-B410-47AE380B0456", 165, 1428030106, "708543", 1428030106, "708543", "{\n}", "2015-04-02T00:00:00", "15 22 29 34 37", "03" ] -, [ 167, "2B936DE6-6D4B-4FA1-9F98-CF5C39A7A0B6", 167, 1428375707, "708543", 1428375707, "708543", "{\n}", "2015-04-06T00:00:00", "02 16 20 25 50", "03" ] -, [ 169, "ABA57A21-845C-43BD-A750-462A07940823", 169, 1428634907, "708543", 1428634907, "708543", "{\n}", "2015-04-09T00:00:00", "05 07 27 43 50", "03" ] -, [ 171, "8A3DF170-CB4F-4B1C-882D-A91384A892FA", 171, 1428980487, "708543", 1428980487, "708543", "{\n}", "2015-04-13T00:00:00", "07 17 26 34 60", "04" ] -, [ 173, "C8CE05E3-B5CA-4289-8704-6652FE4DB081", 173, 1429239707, "708543", 1429239707, "708543", "{\n}", "2015-04-16T00:00:00", "01 06 11 13 23", "01" ] -, [ 175, "67068049-9182-466F-841B-191C0C834971", 175, 1429585286, "708543", 1429585286, "708543", "{\n}", "2015-04-20T00:00:00", "35 36 37 53 56", "04" ] -, [ 177, "2B244FB4-5148-42BB-8C0F-18F72302A072", 177, 1429844487, "708543", 1429844487, "708543", "{\n}", "2015-04-23T00:00:00", "03 12 30 40 56", "02" ] -, [ 179, "BE06E4D1-AE96-40F3-97A5-5A937E0983D5", 179, 1430190127, "708543", 1430190127, "708543", "{\n}", "2015-04-27T00:00:00", "13 14 29 46 47", "01" ] -, [ 181, "5FC39380-1949-40E6-B9DD-5FB1648901D7", 181, 1430449308, "708543", 1430449308, "708543", "{\n}", "2015-04-30T00:00:00", "09 26 29 46 58", "02" ] -, [ 183, "12EA4AE4-F823-427B-9DF7-AAE2BB7DCA08", 183, 1430794909, "708543", 1430794909, "708543", "{\n}", "2015-05-04T00:00:00", "03 05 21 30 60", "04" ] -, [ 185, "D9E721A6-B28A-4811-BC5D-D2BDAABA692F", 185, 1431054131, "708543", 1431054131, "708543", "{\n}", "2015-05-07T00:00:00", "04 11 44 47 53", "02" ] -, [ 187, "5BF8802C-A0CE-4DA2-B482-3133F62C4B77", 187, 1431399749, "708543", 1431399749, "708543", "{\n}", "2015-05-11T00:00:00", "07 08 14 18 52", "01" ] -, [ 189, "90482458-111E-4B10-B506-3D3B50C5013D", 189, 1431659009, "708543", 1431659009, "708543", "{\n}", "2015-05-14T00:00:00", "06 28 34 39 43", "02" ] -, [ 191, "DD2AF2B3-DBB3-44ED-A0D6-1E1BE8D10624", 191, 1432004548, "708543", 1432004548, "708543", "{\n}", "2015-05-18T00:00:00", "16 30 35 38 51", "01" ] -, [ 193, "41866238-C5D3-4CC9-9E88-A15076EA3C50", 193, 1432263708, "708543", 1432263708, "708543", "{\n}", "2015-05-21T00:00:00", "18 22 24 29 56", "04" ] -, [ 195, "86C4BD79-F837-4B0E-A2D7-FB8EA3623DC8", 195, 1432609440, "708543", 1432609440, "708543", "{\n}", "2015-05-25T00:00:00", "15 40 48 59 60", "01" ] -, [ 197, "88A989DB-863E-481F-825E-632FEE7BF997", 197, 1432868513, "708543", 1432868513, "708543", "{\n}", "2015-05-28T00:00:00", "08 25 28 33 47", "01" ] -, [ 199, "168810EE-D7D4-4CA0-B514-2F78BFBC2CA4", 199, 1433214108, "708543", 1433214108, "708543", "{\n}", "2015-06-01T00:00:00", "07 10 23 37 56", "03" ] -, [ 201, "D5E3EC37-3306-41FE-99C9-9A6C18983111", 201, 1433473306, "708543", 1433473306, "708543", "{\n}", "2015-06-04T00:00:00", "04 09 32 41 43", "02" ] -, [ 203, "BE6B2BA7-5F95-4A31-9DF3-8BF03DFCA091", 203, 1433818929, "708543", 1433818929, "708543", "{\n}", "2015-06-08T00:00:00", "33 39 43 49 52", "03" ] -, [ 205, "FC34C3C6-2380-4FE3-8D7E-5913155A26C9", 205, 1434078114, "708543", 1434078114, "708543", "{\n}", "2015-06-11T00:00:00", "17 24 43 49 57", "02" ] -, [ 207, "CD40F120-C2CB-48C5-A139-622DEB4F65B6", 207, 1434423759, "708543", 1434423759, "708543", "{\n}", "2015-06-15T00:00:00", "10 14 16 32 34", "03" ] -, [ 209, "E983452E-64EC-400E-93D1-70D70F5F20E2", 209, 1434682981, "708543", 1434682981, "708543", "{\n}", "2015-06-18T00:00:00", "01 02 14 29 59", "03" ] -, [ 211, "9656A33A-C34E-4F34-A928-5010D8584C0C", 211, 1435028542, "708543", 1435028542, "708543", "{\n}", "2015-06-22T00:00:00", "05 26 27 51 59", "02" ] -, [ 213, "EBF6F368-12B2-4DA9-941C-9A1CD9982750", 213, 1435287707, "708543", 1435287707, "708543", "{\n}", "2015-06-25T00:00:00", "03 26 27 29 58", "01" ] -, [ 215, "C95EA299-841C-470A-A919-660D41CB7A19", 215, 1435633286, "708543", 1435633286, "708543", "{\n}", "2015-06-29T00:00:00", "01 19 37 49 56", "03" ] -, [ 217, "8E894D24-2D77-4E0C-ADFE-39BC258A29DC", 217, 1435892551, "708543", 1435892551, "708543", "{\n}", "2015-07-02T00:00:00", "18 19 31 43 54", "03" ] -, [ 219, "8536A4D2-1AD1-4009-A572-3E5A6162C627", 219, 1436238167, "708543", 1436238167, "708543", "{\n}", "2015-07-06T00:00:00", "03 10 30 33 40", "01" ] -, [ 221, "C46245BD-9AE0-441F-B363-E17E984A3CFA", 221, 1436497289, "708543", 1436497289, "708543", "{\n}", "2015-07-09T00:00:00", "19 34 36 54 55", "01" ] -, [ 223, "4BDC3777-34BD-4258-8E5C-A964D265E8A6", 223, 1436842990, "708543", 1436842990, "708543", null, "2015-07-13T00:00:00", "05 23 27 55 57", "01" ] -, [ 224, "10889320-B901-47FC-AFD6-75BDE9356FF7", 224, 1437102065, "708543", 1437102065, "708543", null, "2015-07-16T00:00:00", "22 29 47 53 54", "03" ] -, [ 225, "9A754F78-F807-4021-B9A7-035BA2C6CBE1", 225, 1437447725, "708543", 1437447725, "708543", null, "2015-07-20T00:00:00", "10 29 47 48 55", "04" ] -, [ 226, "8EA5F297-5030-4AA2-AE0E-9A71375EE66B", 226, 1437706890, "708543", 1437706890, "708543", null, "2015-07-23T00:00:00", "08 26 28 41 52", "04" ] -, [ 227, "6373AF9F-31E8-4346-9422-1994C4DE879D", 227, 1438052506, "708543", 1438052506, "708543", null, "2015-07-27T00:00:00", "03 05 36 43 53", "03" ] -, [ 228, "498DEED9-EFBF-4296-B13B-AEC0017F3135", 228, 1438311725, "708543", 1438311725, "708543", null, "2015-07-30T00:00:00", "15 16 26 27 51", "02" ] -, [ 229, "9E06C3EA-C137-4F17-A67F-C8CE28D8BEF8", 229, 1438657327, "708543", 1438657327, "708543", null, "2015-08-03T00:00:00", "25 29 30 38 39", "03" ] -, [ 230, "05461696-20D9-417B-90D2-4351469BBA1F", 230, 1438916529, "708543", 1438916529, "708543", null, "2015-08-06T00:00:00", "04 05 24 31 42", "02" ] -, [ 231, "DF0DB2F5-0C4E-4953-B716-B95ADAE9A742", 231, 1439262152, "708543", 1439262152, "708543", null, "2015-08-10T00:00:00", "02 07 11 33 47", "02" ] -, [ 232, "74954961-473B-4546-8C15-42BBDD81C47B", 232, 1439564546, "708543", 1439564546, "708543", null, "2015-08-13T00:00:00", "08 12 50 51 56", "04" ] -, [ 233, "CAC3EB9F-5BF5-454A-86BD-68A3F18DBDB6", 233, 1439866949, "708543", 1439866949, "708543", null, "2015-08-17T00:00:00", "05 19 21 24 27", "03" ] -, [ 234, "910E19A6-4152-4BDE-9BF1-60AA55BED6F3", 234, 1440126149, "708543", 1440126149, "708543", null, "2015-08-20T00:00:00", "06 14 25 39 56", "04" ] -, [ 235, "03CF6AAE-2276-4DC4-AC2D-7F9A038AA615", 235, 1440471749, "708543", 1440471749, "708543", null, "2015-08-24T00:00:00", "02 19 35 37 44", "03" ] -, [ 236, "21833935-DBB4-4A8C-ACEB-8C28EC36AD6B", 236, 1440730943, "708543", 1440730943, "708543", null, "2015-08-27T00:00:00", "05 29 37 55 58", "02" ] -, [ 237, "05804F56-7B0A-4227-9EF4-2E98CA8B9129", 237, 1441076532, "708543", 1441076532, "708543", null, "2015-08-31T00:00:00", "12 15 44 45 47", "01" ] -, [ 238, "69159851-6432-4A78-83D8-4D47C1871671", 238, 1441335740, "708543", 1441335740, "708543", null, "2015-09-03T00:00:00", "20 33 46 49 51", "04" ] -, [ 239, "C1500EE4-EB00-4C95-B624-88DC44D43872", 239, 1441681331, "708543", 1441681331, "708543", null, "2015-09-07T00:00:00", "04 21 26 45 46", "04" ] -, [ 240, "D7558560-CCF8-430B-A516-6A02D1C6C6BC", 240, 1442286105, "708543", 1442286105, "708543", null, "2015-09-14T00:00:00", "03 07 14 19 25", "02" ] -, [ 241, "819B7082-516B-4A46-94ED-CD29F5AFF3AF", 241, 1442545304, "708543", 1442545304, "708543", null, "2015-09-17T00:00:00", "14 15 17 35 56", "02" ] -, [ 242, "9F4B80B3-0FC2-41CA-A394-E1FD348C43D5", 242, 1442890890, "708543", 1442890890, "708543", null, "2015-09-21T00:00:00", "17 27 39 44 49", "01" ] -, [ 243, "3D22C9B7-519E-4549-BCF9-7DD9B46A441A", 243, 1442934107, "708543", 1442934107, "708543", null, "2015-09-10T00:00:00", "11 16 50 55 56", "04" ] -, [ 244, "46D6D1F4-BD73-4959-9240-FEC3E7D0F0CF", 244, 1443150147, "708543", 1443150147, "708543", null, "2015-09-24T00:00:00", "14 17 29 39 50", "03" ] -, [ 245, "49D625D0-79BE-4144-A9BE-F1BE234D202D", 245, 1443495706, "708543", 1443495706, "708543", null, "2015-09-28T00:00:00", "01 25 29 43 54", "02" ] -, [ 246, "DC858348-F3ED-4D7C-858C-E914015E5E6A", 246, 1443754927, "708543", 1443754927, "708543", null, "2015-10-01T00:00:00", "25 37 39 47 55", "03" ] -, [ 247, "81C2B637-F49A-41B4-800F-1D6DDC3ACF3E", 247, 1444100546, "708543", 1444100546, "708543", null, "2015-10-05T00:00:00", "08 20 34 41 43", "03" ] -, [ 248, "9013BCB6-CE28-4C96-ADC8-25C2329E6653", 248, 1444359767, "708543", 1444359767, "708543", null, "2015-10-08T00:00:00", "25 27 28 42 53", "02" ] -, [ 249, "8B2BA24A-545E-4453-939D-7B9AF5A82F1B", 249, 1444705326, "708543", 1444705326, "708543", null, "2015-10-12T00:00:00", "28 30 36 38 39", "04" ] -, [ 250, "F0E3B49C-EF02-4205-8C7C-06B79D869EB0", 250, 1444964525, "708543", 1444964525, "708543", null, "2015-10-15T00:00:00", "07 11 39 40 45", "02" ] -, [ 251, "BDAA2D7D-27B1-45EA-A1FB-7A5D0F0FCED2", 251, 1445310125, "708543", 1445310125, "708543", null, "2015-10-19T00:00:00", "04 08 31 46 54", "03" ] -, [ 252, "7423590E-8D14-45A2-9820-0AA6E0F39573", 252, 1445569305, "708543", 1445569305, "708543", null, "2015-10-22T00:00:00", "05 18 45 52 57", "02" ] -, [ 253, "40D07FF0-0812-4BA8-96CC-777F1BE5CC81", 253, 1445914946, "708543", 1445914946, "708543", null, "2015-10-26T00:00:00", "17 20 45 49 58", "02" ] -, [ 254, "70C6BBEF-E408-489E-8944-F99F53CA4108", 254, 1446174085, "708543", 1446174085, "708543", null, "2015-10-29T00:00:00", "10 31 32 34 51", "04" ] -, [ 255, "CD77860A-B40A-4809-8C24-3FA2360ED81A", 255, 1446519796, "708543", 1446519796, "708543", null, "2015-11-02T00:00:00", "01 07 12 34 44", "01" ] -, [ 256, "C558D5E5-22CC-43EA-BDA7-D44CCFB7F83A", 256, 1446778887, "708543", 1446778887, "708543", null, "2015-11-05T00:00:00", "13 20 25 31 51", "03" ] -, [ 257, "7461A9DC-4A7C-4E6F-90A2-AD8B7D5797D4", 257, 1447124506, "708543", 1447124506, "708543", null, "2015-11-09T00:00:00", "06 09 11 27 37", "03" ] -, [ 258, "F49A1AEC-852B-4F80-A7B4-8A1C92B3DE82", 258, 1447383624, "708543", 1447383624, "708543", null, "2015-11-12T00:00:00", "06 41 44 49 56", "04" ] -, [ 259, "4E5D11CB-2D6A-4221-A4C4-3ABC18F9FB46", 259, 1447729327, "708543", 1447729327, "708543", null, "2015-11-16T00:00:00", "06 20 28 34 40", "03" ] -, [ 260, "416BEBC5-580E-4D05-9749-C0F135231E80", 260, 1447988529, "708543", 1447988529, "708543", null, "2015-11-19T00:00:00", "02 07 21 38 48", "04" ] -, [ 261, "B1D35BFE-94AC-424B-868F-0F6F15AD4EB4", 261, 1448334106, "708543", 1448334106, "708543", null, "2015-11-23T00:00:00", "04 21 42 43 59", "04" ] -, [ 262, "14B39058-519A-4E79-9012-BE289B006246", 262, 1448593285, "708543", 1448593285, "708543", null, "2015-11-26T00:00:00", "13 23 43 47 59", "03" ] -, [ 263, "0511598D-7453-4CFF-BA2C-E58525A8AFF0", 263, 1448938966, "708543", 1448938966, "708543", null, "2015-11-30T00:00:00", "04 07 08 19 53", "04" ] -, [ 264, "BA08DC3D-1F1A-4F33-B8DC-1EAD043EDA4A", 264, 1449198126, "708543", 1449198126, "708543", null, "2015-12-03T00:00:00", "08 10 27 37 39", "01" ] -, [ 265, "E6957ED1-4C85-42E5-B20F-A413B19E9AD9", 265, 1449543688, "708543", 1449543688, "708543", null, "2015-12-07T00:00:00", "03 05 36 40 44", "02" ] -, [ 266, "9CE576B4-F88C-4AEB-905F-6EAF7F29C942", 266, 1449802936, "708543", 1449802936, "708543", null, "2015-12-10T00:00:00", "10 47 48 53 58", "02" ] -, [ 267, "76C71A89-020A-4154-89CB-E7E8FFFE597A", 267, 1450148626, "708543", 1450148626, "708543", null, "2015-12-14T00:00:00", "46 50 56 57 58", "01" ] -, [ 268, "90567CD2-57B0-4436-84FB-9FFB867E870F", 268, 1450407725, "708543", 1450407725, "708543", null, "2015-12-17T00:00:00", "26 49 52 54 56", "01" ] -, [ 269, "8B379FC0-AF52-437C-99E5-7F12F4F92213", 269, 1450753388, "708543", 1450753388, "708543", null, "2015-12-21T00:00:00", "09 27 33 40 49", "03" ] -, [ 270, "74367FD8-49EB-40D0-B411-210103794D50", 270, 1451012527, "708543", 1451012527, "708543", null, "2015-12-24T00:00:00", "05 19 36 41 55", "02" ] -, [ 271, "93018B4E-8B54-45CC-B998-A5BF858BDC9F", 271, 1451358229, "708543", 1451358229, "708543", null, "2015-12-28T00:00:00", "07 11 16 23 24", "02" ] -, [ 272, "A295AB45-D532-44E4-BACA-AC0A70587F5E", 272, 1451617326, "708543", 1451617326, "708543", null, "2015-12-31T00:00:00", "01 05 24 47 55", "01" ] -, [ 273, "B8E84552-9E0A-4B17-836B-AAE4079BC556", 273, 1451962965, "708543", 1451962965, "708543", null, "2016-01-04T00:00:00", "08 19 25 51 52", "03" ] -, [ 274, "BE18BC72-52BE-4033-B8A9-4626A8CF0EEB", 274, 1451963067, "708543", 1451963067, "708543", null, "2015-03-12T00:00:00", "03 06 17 47 48", "01" ] -, [ 275, "2E040FA4-DBA5-4784-9B4D-2876309578F3", 275, 1452222146, "708543", 1452222146, "708543", null, "2016-01-07T00:00:00", "14 31 37 54 56", "01" ] -, [ 276, "4FDFAA43-4862-4F0A-B041-BC3ADA834F35", 276, 1452567745, "708543", 1452567745, "708543", null, "2016-01-11T00:00:00", "04 20 30 34 36", "02" ] -, [ 277, "CFAA63BC-0EA2-4CB5-9E1A-AB5D99D0DB67", 277, 1452826946, "708543", 1452826946, "708543", null, "2016-01-14T00:00:00", "23 27 29 36 60", "04" ] -, [ 278, "2A929F8D-6EF6-4468-8AAE-FB650C9C0575", 278, 1453172605, "708543", 1453172605, "708543", null, "2016-01-18T00:00:00", "14 17 39 43 51", "03" ] -, [ 279, "713D5E49-AB48-49B7-9E0A-983831BA98B9", 279, 1453431707, "708543", 1453431707, "708543", null, "2016-01-21T00:00:00", "11 13 36 46 48", "04" ] -, [ 280, "87722842-E694-462C-BCE2-33F27977EAFF", 280, 1453777406, "708543", 1453777406, "708543", null, "2016-01-25T00:00:00", "19 24 38 55 56", "04" ] -, [ 281, "47C6704D-9200-4B34-B220-05C000CF8FA0", 281, 1454036487, "708543", 1454036487, "708543", null, "2016-01-28T00:00:00", "04 05 15 25 59", "02" ] -, [ 282, "7BBFAE55-5759-4C8C-957A-6B492291B6A8", 282, 1454382227, "708543", 1454382227, "708543", null, "2016-02-01T00:00:00", "02 09 22 43 44", "01" ] -, [ 283, "C121AB49-5B80-494E-8F1A-BFBD4A303F77", 283, 1454641306, "708543", 1454641306, "708543", null, "2016-02-04T00:00:00", "08 12 23 40 54", "01" ] -, [ 284, "7B04BDF0-3D43-48EA-ADE6-9CD4834A07CB", 284, 1454987128, "708543", 1454987128, "708543", null, "2016-02-08T00:00:00", "13 23 48 57 59", "02" ] -, [ 285, "82C7F79A-D888-4ADF-9588-E26CEFBECCDD", 285, 1455246328, "708543", 1455246328, "708543", null, "2016-02-11T00:00:00", "06 31 35 40 55", "02" ] -, [ 286, "8EC5B96F-C188-4465-89EB-F887EB3D0EE1", 286, 1455591808, "708543", 1455591808, "708543", null, "2016-02-15T00:00:00", "02 09 30 37 42", "02" ] -, [ 287, "C8975BF7-2707-4128-B038-CA24C6479AC6", 287, 1455850911, "708543", 1455850911, "708543", null, "2016-02-18T00:00:00", "21 24 37 38 49", "04" ] -, [ 288, "C2C83C0F-110F-48DF-BB4B-5FA814445E21", 288, 1456196566, "708543", 1456196566, "708543", null, "2016-02-22T00:00:00", "08 09 10 11 27", "04" ] -, [ 289, "70EA9E33-5346-4356-8B0D-BB5D4994D0C2", 289, 1456455707, "708543", 1456455707, "708543", null, "2016-02-25T00:00:00", "02 16 19 33 39", "03" ] -, [ 290, "77747333-4D77-461B-91BE-321169F75BBE", 290, 1456801366, "708543", 1456801366, "708543", null, "2016-02-29T00:00:00", "03 17 26 47 58", "01" ] -, [ 291, "8B5BFF9C-D3B5-4363-8919-9920B32B5972", 291, 1457060507, "708543", 1457060507, "708543", null, "2016-03-03T00:00:00", "07 13 35 40 45", "04" ] -, [ 292, "0A190D1C-A984-4C3B-85A3-7888E3EB6AFB", 292, 1457406146, "708543", 1457406146, "708543", null, "2016-03-07T00:00:00", "09 21 24 37 38", "02" ] -, [ 293, "D5CF7DBD-F742-46B5-933B-0461C4AF35BD", 293, 1457665307, "708543", 1457665307, "708543", null, "2016-03-10T00:00:00", "06 12 21 40 57", "01" ] -, [ 294, "438D098F-0FD7-4AE4-ABE1-5F3B627598A6", 294, 1458010948, "708543", 1458010948, "708543", null, "2016-03-14T00:00:00", "17 28 37 38 41", "01" ] -, [ 295, "3753CF29-DD5E-4E34-B0B2-DCE5A4705745", 295, 1458270085, "708543", 1458270085, "708543", null, "2016-03-17T00:00:00", "11 16 34 44 56", "01" ] -, [ 296, "D72F0087-09BE-49E2-AC57-6745208BFD3A", 296, 1458615706, "708543", 1458615706, "708543", null, "2016-03-21T00:00:00", "13 30 41 50 55", "01" ] -, [ 297, "E3AA41F1-C4D0-4868-AB15-115FC538A42D", 297, 1458874906, "708543", 1458874906, "708543", null, "2016-03-24T00:00:00", "17 24 30 45 48", "03" ] -, [ 298, "C2BF8733-16B5-4227-8C6A-B844DB98C50C", 298, 1459220505, "708543", 1459220505, "708543", null, "2016-03-28T00:00:00", "20 33 49 53 56", "04" ] -, [ 299, "4F49FA6F-1798-4D53-A584-C20494804316", 299, 1459479705, "708543", 1459479705, "708543", null, "2016-03-31T00:00:00", "09 17 28 38 45", "01" ] -, [ 300, "A447AD72-8550-482E-97C7-3C99DF68E0CF", 300, 1459825329, "708543", 1459825329, "708543", null, "2016-04-04T00:00:00", "05 26 32 36 58", "04" ] -, [ 301, "58B023C5-98DF-40D0-83E0-F59455C54A22", 301, 1460084526, "708543", 1460084526, "708543", null, "2016-04-07T00:00:00", "02 11 32 50 54", "02" ] -, [ 302, "EF0612D5-4C76-415B-B319-6AEC5556CF37", 302, 1460430128, "708543", 1460430128, "708543", null, "2016-04-11T00:00:00", "15 30 34 38 55", "02" ] -, [ 303, "A97F5813-253E-4260-8574-D345AFC22F9D", 303, 1460689307, "708543", 1460689307, "708543", null, "2016-04-14T00:00:00", "24 25 48 55 56", "02" ] -, [ 304, "3C793ED7-C910-471F-B618-B402368054AE", 304, 1461034930, "708543", 1461034930, "708543", null, "2016-04-18T00:00:00", "06 25 29 33 44", "02" ] -, [ 305, "36F1E6A8-801D-4403-A665-5EEAB32626AB", 305, 1461294107, "708543", 1461294107, "708543", null, "2016-04-21T00:00:00", "06 12 20 40 53", "04" ] -, [ 306, "EADE786A-269F-400F-8C33-89F4B0AD1942", 306, 1461639766, "708543", 1461639766, "708543", null, "2016-04-25T00:00:00", "02 18 27 52 57", "04" ] -, [ 307, "AB171349-0D36-4C32-AA59-4FBBC152CAF8", 307, 1461898908, "708543", 1461898908, "708543", null, "2016-04-28T00:00:00", "04 14 22 47 58", "03" ] -, [ 308, "CCF28D0A-BF2A-493D-AB70-A9FF0030A0D8", 308, 1462244607, "708543", 1462244607, "708543", null, "2016-05-02T00:00:00", "10 14 30 55 56", "01" ] -, [ 309, "4B2467EE-76B5-4234-93AF-08DA874D2C97", 309, 1462503706, "708543", 1462503706, "708543", null, "2016-05-05T00:00:00", "17 18 30 43 49", "04" ] -, [ 310, "D1703DB4-0C48-4EE1-9143-EE7D721F51E0", 310, 1462849327, "708543", 1462849327, "708543", null, "2016-05-09T00:00:00", "20 23 38 48 56", "03" ] -, [ 311, "A92AB3F1-4B91-4DAD-9B0B-ED02022D66E2", 311, 1463108526, "708543", 1463108526, "708543", null, "2016-05-12T00:00:00", "04 13 15 16 32", "04" ] -, [ 312, "50F030BF-4F12-4CB4-927F-5CAFDF89C31E", 312, 1463454165, "708543", 1463454165, "708543", null, "2016-05-16T00:00:00", "04 20 25 32 45", "03" ] -, [ 313, "FA8A7822-FDF4-4388-8AF3-6E9D045D78B8", 313, 1463713286, "708543", 1463713286, "708543", null, "2016-05-19T00:00:00", "10 18 37 40 57", "04" ] -, [ 314, "D6178B28-AE42-4CA4-9FF0-D9B878E98335", 314, 1464058906, "708543", 1464058906, "708543", null, "2016-05-23T00:00:00", "04 19 26 33 58", "02" ] -, [ 315, "551DFBDF-EC8E-456D-A09D-5A9B8B42BD9D", 315, 1464318105, "708543", 1464318105, "708543", null, "2016-05-26T00:00:00", "04 13 26 34 43", "03" ] -, [ 316, "B4E5CA65-8F5C-4A75-A68E-01CD98074B29", 316, 1464663786, "708543", 1464663786, "708543", null, "2016-05-30T00:00:00", "05 07 27 28 36", "04" ] -, [ 317, "E7E2C9F9-A64E-43EB-B9C7-BD6D8E4962C4", 317, 1464922887, "708543", 1464922887, "708543", null, "2016-06-02T00:00:00", "18 28 30 31 37", "02" ] -, [ 318, "C45FF1A8-7331-4DC6-9AB6-E4DE04A0B09C", 318, 1465268547, "708543", 1465268547, "708543", null, "2016-06-06T00:00:00", "18 25 35 41 57", "02" ] -, [ 319, "58BB5146-A70B-41DE-AFCF-5E024D26B38F", 319, 1465527708, "708543", 1465527708, "708543", null, "2016-06-09T00:00:00", "01 04 12 33 41", "02" ] -, [ 320, "68C6831F-536C-4009-BFB9-BC3A2B4AD625", 320, 1465873309, "708543", 1465873309, "708543", null, "2016-06-13T00:00:00", "35 40 51 55 60", "01" ] -, [ 321, "5C1548EC-0215-4D3E-87AA-8D807B4E60FB", 321, 1466132506, "708543", 1466132506, "708543", null, "2016-06-16T00:00:00", "03 17 22 57 59", "02" ] -, [ 322, "830DCC3A-6742-4948-89CC-82FBA203A36C", 322, 1466478145, "708543", 1466478145, "708543", null, "2016-06-20T00:00:00", "01 12 14 32 60", "03" ] -, [ 323, "5DF63F07-C89F-486B-8B29-7772ABEF0A92", 323, 1466737307, "708543", 1466737307, "708543", null, "2016-06-23T00:00:00", "01 09 36 38 46", "01" ] -, [ 324, "FC9292E2-8D42-4696-81F8-F5377A8C59D6", 324, 1467082985, "708543", 1467082985, "708543", null, "2016-06-27T00:00:00", "02 03 09 27 37", "01" ] -, [ 325, "1954E04D-32A1-45E0-9ACF-B47404D258DF", 325, 1467342107, "708543", 1467342107, "708543", null, "2016-06-30T00:00:00", "04 09 10 31 34", "03" ] -, [ 326, "7C56F803-F4B5-4DA0-8C97-9B7FA2ADC1F3", 326, 1467687725, "708543", 1467687725, "708543", null, "2016-07-04T00:00:00", "02 15 17 18 52", "01" ] -, [ 327, "4294E688-3864-491C-86C9-CA646EC2C49C", 327, 1467947025, "708543", 1467947025, "708543", null, "2016-07-07T00:00:00", "04 08 26 41 55", "03" ] -, [ 328, "066CD036-4708-429B-9B76-060E77753B4C", 328, 1468292515, "708543", 1468292515, "708543", null, "2016-07-11T00:00:00", "16 20 25 27 43", "03" ] -, [ 329, "AAA3A2F3-5860-4F9F-94D1-C28D152A2621", 329, 1468551706, "708543", 1468551706, "708543", null, "2016-07-14T00:00:00", "03 08 11 24 25", "02" ] -, [ 330, "FC5C2E01-2289-433A-88D1-50430851D90D", 330, 1468897350, "708543", 1468897350, "708543", null, "2016-07-18T00:00:00", "13 45 51 58 60", "01" ] -, [ 331, "7521FBF4-81E2-4DED-ADDD-74F693D0031D", 331, 1469156485, "708543", 1469156485, "708543", null, "2016-07-21T00:00:00", "01 04 18 29 32", "01" ] -, [ 332, "7153C695-63D1-49A3-91D2-082D09171CC0", 332, 1469502126, "708543", 1469502126, "708543", null, "2016-07-25T00:00:00", "11 12 23 26 43", "02" ] -, [ 333, "27681D0A-040F-4D9A-A119-13C4392622CF", 333, 1469761306, "708543", 1469761306, "708543", null, "2016-07-28T00:00:00", "13 19 32 36 41", "02" ] -, [ 334, "75246569-4982-4E24-81AA-45F9A9803C8D", 334, 1470106886, "708543", 1470106886, "708543", null, "2016-08-01T00:00:00", "32 34 36 39 46", "01" ] -, [ 335, "1382260F-0898-4945-AB2E-8DC51E11593A", 335, 1470366105, "708543", 1470366105, "708543", null, "2016-08-04T00:00:00", "08 22 41 54 56", "01" ] -, [ 336, "3ADD1C00-4497-450C-ADDD-300DA05C1BE8", 336, 1470711725, "708543", 1470711725, "708543", null, "2016-08-08T00:00:00", "04 07 08 12 23", "01" ] -, [ 337, "8AEC193F-651F-4C61-8F91-792211203FB9", 337, 1470970905, "708543", 1470970905, "708543", null, "2016-08-11T00:00:00", "03 34 44 53 55", "04" ] -, [ 338, "BFCE5235-8BFE-4DDB-B133-92787B11E6F1", 338, 1471316525, "708543", 1471316525, "708543", null, "2016-08-15T00:00:00", "13 40 48 50 57", "04" ] -, [ 339, "E69693B0-5EE1-4E00-80F8-5E3826BDF3C2", 339, 1471575706, "708543", 1471575706, "708543", null, "2016-08-18T00:00:00", "07 24 25 56 58", "03" ] -, [ 340, "866871A3-7952-4D0F-A557-86147F0FFABB", 340, 1472076169, "708543", 1472076169, "708543", null, "2016-08-22T00:00:00", "08 12 22 56 58", "01" ] -, [ 341, "542C6698-71F5-4698-84EC-06F2660FD6F8", 341, 1472205665, "708543", 1472205665, "708543", null, "2016-08-25T00:00:00", "10 17 24 47 59", "02" ] -, [ 342, "C51D55B6-5946-456C-A55F-D0AB8A2D4A21", 342, 1472551269, "708543", 1472551269, "708543", null, "2016-08-29T00:00:00", "05 21 25 31 55", "04" ] -, [ 343, "B6A9851F-B803-47E0-8049-8C2D87476A7F", 343, 1472810465, "708543", 1472810465, "708543", null, "2016-09-01T00:00:00", "17 45 46 51 53", "02" ] -, [ 344, "1AE0AF41-51F0-48B3-8843-EBEE145E8325", 344, 1473268891, "708543", 1473268891, "708543", null, "2016-09-05T00:00:00", "16 19 40 41 43", "03" ] -, [ 345, "21F27DE2-45CC-4D6B-9FD0-1D8CA8A20024", 345, 1473445246, "708543", 1473445246, "708543", null, "2016-09-08T00:00:00", "03 07 22 37 60", "02" ] -, [ 346, "9E61A94F-8971-4347-8E38-3505413BF359", 346, 1473760864, "708543", 1473760864, "708543", null, "2016-09-12T00:00:00", "01 32 39 55 58", "02" ] -, [ 347, "B18D0A66-3AC8-43B6-8E40-BD28B95874E9", 347, 1474020065, "708543", 1474020065, "708543", null, "2016-09-15T00:00:00", "11 20 54 59 60", "02" ] -, [ 348, "FF974006-3F5C-452D-8067-DB663B1E4070", 348, 1474365664, "708543", 1474365664, "708543", null, "2016-09-19T00:00:00", "19 40 49 54 56", "04" ] -, [ 349, "3A072E03-BC85-4F81-8ED9-436ED49F4DFA", 349, 1474624871, "708543", 1474624871, "708543", null, "2016-09-22T00:00:00", "01 03 24 42 59", "01" ] -, [ 350, "1C880DFC-09D3-4108-9038-721786886E91", 350, 1474970463, "708543", 1474970463, "708543", null, "2016-09-26T00:00:00", "36 44 50 54 60", "04" ] -, [ 351, "3A5F2AF8-1578-4EA2-93BD-D1AE9BB6605F", 351, 1475229663, "708543", 1475229663, "708543", null, "2016-09-29T00:00:00", "13 25 39 51 55", "03" ] -, [ 352, "2BC4E88D-7706-40B9-A71D-DCA1F37EED76", 352, 1475575263, "708543", 1475575263, "708543", null, "2016-10-03T00:00:00", "05 48 49 52 58", "02" ] -, [ 353, "5B7DD3A9-D218-4210-AA73-BCBEAFD8A807", 353, 1475834463, "708543", 1475834463, "708543", null, "2016-10-06T00:00:00", "05 07 09 12 43", "02" ] -, [ 354, "9203C4C9-9D90-47D5-8CEB-A1B92BBB6648", 354, 1476180084, "708543", 1476180084, "708543", null, "2016-10-10T00:00:00", "11 35 38 45 58", "01" ] -, [ 355, "BF36F047-2FBA-452E-911A-756F1D1BFE6A", 355, 1476439263, "708543", 1476439263, "708543", null, "2016-10-13T00:00:00", "03 19 21 26 43", "03" ] -, [ 356, "0E587093-37FA-40EE-AF54-B0BA90D3C41C", 356, 1476784863, "708543", 1476784863, "708543", null, "2016-10-17T00:00:00", "04 16 35 37 55", "04" ] -, [ 357, "E64FCA93-AD90-4C08-96F6-F5D3893F4864", 357, 1477044065, "708543", 1477044065, "708543", null, "2016-10-20T00:00:00", "06 38 40 48 57", "02" ] -, [ 358, "207063E0-B35C-47A9-B86A-29C9303F8C99", 358, 1477411657, "708543", 1477411657, "708543", null, "2016-10-24T00:00:00", "01 02 20 40 55", "04" ] -, [ 359, "12F517F0-6AB0-49AF-B3FD-60551DB5E71C", 359, 1477648862, "708543", 1477648862, "708543", null, "2016-10-27T00:00:00", "15 16 19 37 40", "04" ] -, [ 360, "BDFDD6D9-6C78-4ADD-9D8C-1BC306BF9D47", 360, 1477994484, "708543", 1477994484, "708543", null, "2016-10-31T00:00:00", "17 25 38 41 58", "03" ] -, [ 361, "0F8581C9-2308-4CF3-85AF-58997BAA6195", 361, 1478253663, "708543", 1478253663, "708543", null, "2016-11-03T00:00:00", "05 10 29 37 59", "04" ] -, [ 362, "B1A0DE7D-8653-4174-8165-6178E15DE970", 362, 1478602863, "708543", 1478602863, "708543", null, "2016-11-07T00:00:00", "09 11 20 37 60", "02" ] -, [ 363, "1881FB59-CACC-4DE1-811E-470ACEB648AA", 363, 1478862062, "708543", 1478862062, "708543", null, "2016-11-10T00:00:00", "06 07 17 20 44", "02" ] -, [ 364, "EA961E65-99E4-4534-8AD0-927FD4B33152", 364, 1479207685, "708543", 1479207685, "708543", null, "2016-11-14T00:00:00", "03 10 20 30 43", "01" ] -, [ 365, "444F25A6-0B87-4BFC-81F0-48169EB912CB", 365, 1479466863, "708543", 1479466863, "708543", null, "2016-11-17T00:00:00", "06 30 32 35 48", "01" ] -, [ 366, "A1B19B86-0101-422D-ACA5-6E0F257F9936", 366, 1479812595, "708543", 1479812595, "708543", null, "2016-11-21T00:00:00", "08 11 37 41 54", "04" ] -, [ 367, "F3666FC9-4209-46DC-A083-AAB50F49AE32", 367, 1480071815, "708543", 1480071815, "708543", null, "2016-11-24T00:00:00", "04 24 25 32 46", "01" ] -, [ 368, "4610C832-DE20-48B3-BC5C-4C599067F3DB", 368, 1480417262, "708543", 1480417262, "708543", null, "2016-11-28T00:00:00", "22 32 42 45 49", "04" ] -, [ 369, "1559BB20-317A-4092-8966-788A8265EEA5", 369, 1480676463, "708543", 1480676463, "708543", null, "2016-12-01T00:00:00", "17 23 30 49 55", "01" ] -, [ 370, "3B1D2CEB-0135-4AE2-A220-76D269851B3B", 370, 1481022063, "708543", 1481022063, "708543", null, "2016-12-05T00:00:00", "05 06 19 22 45", "04" ] -, [ 371, "A04FCBEE-20D1-43E9-8B8B-3367AED3A724", 371, 1481281263, "708543", 1481281263, "708543", null, "2016-12-08T00:00:00", "08 28 29 49 57", "03" ] -, [ 372, "34543D5E-6964-494C-B91E-E4CDF4DC14A3", 372, 1481626862, "708543", 1481626862, "708543", null, "2016-12-12T00:00:00", "14 19 48 53 54", "04" ] -, [ 373, "A1020F9A-D7C6-4CC3-AC05-AAA2D238DD55", 373, 1481886064, "708543", 1481886064, "708543", null, "2016-12-15T00:00:00", "05 07 21 44 57", "02" ] -, [ 374, "BDF2DA85-5CEB-48CC-B9E3-E2FBCEB23C2B", 374, 1482231662, "708543", 1482231662, "708543", null, "2016-12-19T00:00:00", "01 08 16 22 47", "03" ] -, [ 375, "FA3C3D28-FD22-4EC5-8336-7C846CAD2443", 375, 1482577419, "708543", 1482577419, "708543", null, "2016-12-22T00:00:00", "14 19 32 38 43", "03" ] -, [ 376, "4C35A52C-6907-43EC-86FF-4B4BEC6A5E49", 376, 1482836463, "708543", 1482836463, "708543", null, "2016-12-26T00:00:00", "04 12 29 31 36", "01" ] -, [ 377, "C6F39639-73F6-4154-BD6E-B132ED1105E8", 377, 1483095662, "708543", 1483095662, "708543", null, "2016-12-29T00:00:00", "11 16 19 29 34", "01" ] -, [ 378, "7AF97546-0AD7-40C7-BFE0-40A1E0BB1B33", 378, 1483441353, "708543", 1483441353, "708543", null, "2017-01-02T00:00:00", "26 31 37 38 41", "02" ] -, [ 379, "E983310B-B8AF-4A58-858F-0E9304EA8249", 379, 1483700569, "708543", 1483700569, "708543", null, "2017-01-05T00:00:00", "05 18 42 44 46", "04" ] -, [ 380, "103D6B62-39BE-4EA4-B534-08BB03C150C8", 380, 1484046133, "708543", 1484046133, "708543", null, "2017-01-09T00:00:00", "21 28 31 44 51", "01" ] -, [ 381, "7CD6CAB4-8153-4BB3-A27B-A542AB245036", 381, 1484305263, "708543", 1484305263, "708543", null, "2017-01-12T00:00:00", "06 32 37 50 56", "01" ] -, [ 382, "0BA4693E-BAB9-474B-AF77-E1167BC331B6", 382, 1484650863, "708543", 1484650863, "708543", null, "2017-01-16T00:00:00", "03 15 16 19 26", "01" ] -, [ 383, "F8E9EA6C-E90D-4747-9B9E-ABED48B51012", 383, 1484910064, "708543", 1484910064, "708543", null, "2017-01-19T00:00:00", "14 32 37 43 45", "02" ] -, [ 384, "933403B9-374D-4F52-9016-A366170C7B80", 384, 1485255703, "708543", 1485255703, "708543", null, "2017-01-23T00:00:00", "16 24 32 44 48", "01" ] -, [ 385, "1911AB83-55BF-41DA-9435-80647451B102", 385, 1485514863, "708543", 1485514863, "708543", null, "2017-01-26T00:00:00", "01 14 25 40 59", "02" ] -, [ 386, "C9A55462-3885-4282-B2F9-D81DF650BB2A", 386, 1485860463, "708543", 1485860463, "708543", null, "2017-01-30T00:00:00", "11 20 31 34 51", "03" ] -, [ 387, "0EBCE21B-9B55-455B-B50B-2C59071D79EB", 387, 1486119661, "708543", 1486119661, "708543", null, "2017-02-02T00:00:00", "13 20 24 37 58", "02" ] -, [ 388, "EB111070-EDC8-4551-9340-2591ECD7C2C8", 388, 1486465263, "708543", 1486465263, "708543", null, "2017-02-06T00:00:00", "06 24 48 54 59", "02" ] -, [ 389, "1AD26A0B-D5BA-4645-ACCF-F46113F2338C", 389, 1486724463, "708543", 1486724463, "708543", null, "2017-02-09T00:00:00", "02 28 37 38 48", "04" ] -, [ 390, "5F8E008F-6819-4537-A227-B1B6E17F91B5", 390, 1487070063, "708543", 1487070063, "708543", null, "2017-02-13T00:00:00", "17 18 24 25 41", "01" ] -, [ 391, "835E6675-3ED7-4366-A2C9-CBA14A2E2D21", 391, 1487329283, "708543", 1487329283, "708543", null, "2017-02-16T00:00:00", "08 12 19 35 42", "04" ] -, [ 392, "92ACF91E-7E18-4474-B9CE-1FF4A6CA254C", 392, 1487674863, "708543", 1487674863, "708543", null, "2017-02-20T00:00:00", "13 16 23 37 48", "03" ] -, [ 393, "8F0AA716-50CD-4F3A-8C03-A30502C50F12", 393, 1487934063, "708543", 1487934063, "708543", null, "2017-02-23T00:00:00", "03 24 38 43 52", "03" ] -, [ 394, "FC265525-1D9E-4446-8D16-2E7B274FEE39", 394, 1488279663, "708543", 1488279663, "708543", null, "2017-02-27T00:00:00", "06 19 28 57 60", "01" ] -, [ 395, "C83F7BA9-4D51-4162-BB6B-0D18AAA63D7A", 395, 1488538863, "708543", 1488538863, "708543", null, "2017-03-02T00:00:00", "03 07 11 30 42", "03" ] -, [ 396, "48273180-B95E-4577-A184-BC322612FD77", 396, 1488884464, "708543", 1488884464, "708543", null, "2017-03-06T00:00:00", "01 05 14 22 50", "02" ] -, [ 397, "E6EDD74A-BFA0-43ED-A0A8-89F9F297CBC8", 397, 1489143662, "708543", 1489143662, "708543", null, "2017-03-09T00:00:00", "01 08 23 56 58", "03" ] -, [ 398, "638B5ABD-5A49-4D49-8E65-0C80CD12C359", 398, 1489485665, "708543", 1489485665, "708543", null, "2017-03-13T00:00:00", "13 16 17 24 50", "02" ] -, [ 399, "CE4D7DBB-FA7E-4A9E-B690-69ACF26681C2", 399, 1489744863, "708543", 1489744863, "708543", null, "2017-03-16T00:00:00", "13 14 36 48 57", "02" ] -, [ 400, "A79B333A-4D79-46AB-876A-ED37FDA22179", 400, 1490090463, "708543", 1490090463, "708543", null, "2017-03-20T00:00:00", "13 22 41 46 56", "02" ] -, [ 401, "7E5D329D-8BA7-4F19-A9C4-B0C54C20470B", 401, 1490349662, "708543", 1490349662, "708543", null, "2017-03-23T00:00:00", "02 28 30 39 53", "04" ] -, [ 402, "1985AC19-100B-4AB7-9576-B6B8227EE8C2", 402, 1490695263, "708543", 1490695263, "708543", null, "2017-03-27T00:00:00", "32 42 58 59 60", "04" ] -, [ 403, "B253914E-565E-4CDA-A8F7-739D870195D6", 403, 1490954462, "708543", 1490954462, "708543", null, "2017-03-30T00:00:00", "24 38 40 44 49", "02" ] -, [ 404, "6C4EA2A4-B16E-4933-94E4-CC03D67C41F5", 404, 1491300064, "708543", 1491300064, "708543", null, "2017-04-03T00:00:00", "12 15 28 46 57", "02" ] -, [ 405, "0ABBB5BF-08B3-4106-8C0B-A7E4D3FFAB85", 405, 1491559263, "708543", 1491559263, "708543", null, "2017-04-06T00:00:00", "04 06 17 48 53", "04" ] -, [ 406, "13B8CAA5-E796-4524-BEE5-74C3B4CE0262", 406, 1491904864, "708543", 1491904864, "708543", null, "2017-04-10T00:00:00", "20 22 37 55 56", "03" ] -, [ 407, "7BCBE538-0B50-436D-9590-53E8C5D90F37", 407, 1492164063, "708543", 1492164063, "708543", null, "2017-04-13T00:00:00", "17 19 49 50 56", "04" ] -, [ 408, "5958B7B7-B596-4599-9AFC-3605927278C3", 408, 1492509663, "708543", 1492509663, "708543", null, "2017-04-17T00:00:00", "05 09 12 33 46", "04" ] -, [ 409, "38574FCC-C191-429E-BA01-6945C49FDA31", 409, 1492768863, "708543", 1492768863, "708543", null, "2017-04-20T00:00:00", "22 23 37 56 60", "04" ] -, [ 410, "88377B77-8DFB-4B28-8D7C-778AE0574761", 410, 1493114484, "708543", 1493114484, "708543", null, "2017-04-24T00:00:00", "19 33 35 36 48", "02" ] -, [ 411, "7B77E69F-1E58-4F9E-928F-31136AB6E344", 411, 1493373665, "708543", 1493373665, "708543", null, "2017-04-27T00:00:00", "02 20 27 29 53", "04" ] -, [ 412, "D1439024-FE00-4907-BB75-A017CAE2298B", 412, 1493762464, "708543", 1493762464, "708543", null, "2017-05-01T00:00:00", "07 19 23 24 40", "02" ] -, [ 413, "14FA8C72-6190-46D3-B86D-6B04643CC1F9", 413, 1493978463, "708543", 1493978463, "708543", null, "2017-05-04T00:00:00", "01 02 17 24 38", "04" ] -, [ 414, "45E0D1A0-D009-4F72-8A54-2164799E0405", 414, 1494324065, "708543", 1494324065, "708543", null, "2017-05-08T00:00:00", "22 34 42 46 57", "03" ] -, [ 415, "877064A5-1C75-4A14-8504-678698EA5CE5", 415, 1494583263, "708543", 1494583263, "708543", null, "2017-05-11T00:00:00", "06 20 30 34 36", "01" ] -, [ 416, "9F38DE70-E408-4705-BD7F-BBB6E66DA750", 416, 1494928884, "708543", 1494928884, "708543", null, "2017-05-15T00:00:00", "02 27 28 34 39", "03" ] -, [ 417, "E1E94E70-16BB-4D44-878A-D98B8B080DFD", 417, 1495188064, "708543", 1495188064, "708543", null, "2017-05-18T00:00:00", "04 29 30 55 58", "03" ] -, [ 418, "96667C9D-2FF0-450B-905F-21D1F7EDB7CD", 418, 1495533664, "708543", 1495533664, "708543", null, "2017-05-22T00:00:00", "04 06 25 31 47", "01" ] -, [ 419, "AF4400B9-8891-4605-9F13-51937F17B03B", 419, 1495792863, "708543", 1495792863, "708543", null, "2017-05-25T00:00:00", "06 07 13 16 30", "01" ] -, [ 420, "048E1CAE-2335-44CB-9A83-5182E1340DB7", 420, 1496138464, "708543", 1496138464, "708543", null, "2017-05-29T00:00:00", "18 22 23 25 49", "04" ] -, [ 421, "1DB24704-5C12-4A46-8E68-CD1DD147BDEC", 421, 1496397665, "708543", 1496397665, "708543", null, "2017-06-01T00:00:00", "05 09 46 55 58", "04" ] -, [ 422, "FEE6742F-1091-4CD5-B512-702D5A4EC2B0", 422, 1496743263, "708543", 1496743263, "708543", null, "2017-06-05T00:00:00", "03 29 32 48 56", "01" ] -, [ 423, "0A4E5275-85AB-47AF-BC6B-E0F20AFB16C2", 423, 1497002463, "708543", 1497002463, "708543", null, "2017-06-08T00:00:00", "24 27 43 50 60", "03" ] -, [ 424, "303C188D-FDBB-45DD-85AC-05713746DB00", 424, 1497348063, "708543", 1497348063, "708543", null, "2017-06-12T00:00:00", "10 11 44 53 57", "03" ] -, [ 425, "D5521A42-7B8E-4543-A679-7E8B30420AD2", 425, 1497607263, "708543", 1497607263, "708543", null, "2017-06-15T00:00:00", "01 09 17 26 55", "01" ] -, [ 426, "6B9C238D-2DAD-4893-A400-41EE87FAA507", 426, 1497952863, "708543", 1497952863, "708543", null, "2017-06-19T00:00:00", "02 10 15 33 58", "04" ] -, [ 427, "2F1D8176-05CC-42FD-9948-2DF7D2D17789", 427, 1498212065, "708543", 1498212065, "708543", null, "2017-06-22T00:00:00", "31 40 45 54 57", "03" ] -, [ 428, "9BD5890A-DDD6-4F6B-BCB0-E8958FE6A64E", 428, 1498557663, "708543", 1498557663, "708543", null, "2017-06-26T00:00:00", "08 33 39 40 49", "02" ] -, [ 429, "7A097BCB-1AE8-4F43-A54C-74F145E6EC89", 429, 1498816862, "708543", 1498816862, "708543", null, "2017-06-29T00:00:00", "07 08 13 18 48", "02" ] -, [ 430, "1378F87D-4AE2-4A2E-9C6F-B16E64B6F6AE", 430, 1499162463, "708543", 1499162463, "708543", null, "2017-07-03T00:00:00", "04 28 40 41 48", "03" ] -, [ 431, "DC076E67-B307-40C0-8542-B2137A9AE611", 431, 1499421663, "708543", 1499421663, "708543", null, "2017-07-06T00:00:00", "04 09 39 44 52", "02" ] -, [ 432, "3E109B20-AE12-42CB-9DB9-2915BDB33484", 432, 1499767263, "708543", 1499767263, "708543", null, "2017-07-10T00:00:00", "13 19 34 38 53", "01" ] -, [ 433, "D583AB29-686F-4C7C-A419-44BC8EDFF09C", 433, 1500026463, "708543", 1500026463, "708543", null, "2017-07-13T00:00:00", "06 17 32 45 59", "03" ] -, [ 434, "8D36A3EA-081C-43D6-BE99-5444EC524B8D", 434, 1500372063, "708543", 1500372063, "708543", null, "2017-07-17T00:00:00", "08 17 27 28 39", "02" ] -, [ 435, "5E8FA7B1-1811-4AD8-B38D-45AC8BD6892E", 435, 1500631263, "708543", 1500631263, "708543", null, "2017-07-20T00:00:00", "26 37 40 42 50", "01" ] -, [ 436, "2DE0CC06-BC82-40F7-9EC1-7D994914295F", 436, 1500976822, "708543", 1500976822, "708543", null, "2017-07-24T00:00:00", "07 20 21 41 59", "01" ] -, [ 437, "63D9B819-449D-4674-B015-B6C0DFE74DB2", 437, 1501236065, "708543", 1501236065, "708543", null, "2017-07-27T00:00:00", "32 37 38 42 43", "02" ] - ] -} \ No newline at end of file + }, + "data": [ + [ + 1, + "012CAE53-5033-48B4-BADA-E2EDB4C82D76", + 1, + 1403096267, + "707756", + 1403096267, + "707756", + "{\n}", + "2014-06-16T00:00:00Z", + "09 36 44 53 59", + "03" + ], + [ + 3, + "9A327854-2BA9-474A-B392-EBBDF0806559", + 3, + 1403233340, + "708543", + 1403233340, + "708543", + "{\n}", + "2014-06-19T00:00:00Z", + "08 13 43 56 60", + "02" + ], + [ + 5, + "B03A03EA-661A-452F-9084-6B95EDE9EFEA", + 5, + 1403578864, + "708543", + 1403578864, + "708543", + "{\n}", + "2014-06-23T00:00:00Z", + "05 16 21 33 47", + "04" + ], + [ + 7, + "205077A2-7F97-42B3-9BF8-592B6E314EC6", + 7, + 1403861033, + "708543", + 1403861033, + "708543", + "{\n}", + "2014-06-26T00:00:00Z", + "15 22 51 52 58", + "03" + ], + [ + 9, + "038EA5F2-C6F5-4DA9-B57A-EA185D8A609B", + 9, + 1404183739, + "708543", + 1404183739, + "708543", + "{\n}", + "2014-06-30T00:00:00Z", + "01 04 10 28 33", + "02" + ], + [ + 11, + "FB8E9108-DA9A-4D9C-9BDF-3727F7A862AA", + 11, + 1404442822, + "708543", + 1404442822, + "708543", + "{\n}", + "2014-07-03T00:00:00Z", + "08 10 25 28 31", + "02" + ], + [ + 13, + "49BC2CEE-8BEB-4A2B-9951-D0669FC80A57", + 13, + 1404788422, + "708543", + 1404788422, + "708543", + "{\n}", + "2014-07-07T00:00:00Z", + "11 13 23 54 55", + "02" + ], + [ + 15, + "81B00141-368C-4C89-A943-5512A585E9B6", + 15, + 1405047685, + "708543", + 1405047685, + "708543", + "{\n}", + "2014-07-10T00:00:00Z", + "11 12 31 54 59", + "03" + ], + [ + 17, + "B2217278-0DF2-4BD9-993B-CBF3E38005D8", + 17, + 1405393265, + "708543", + 1405393265, + "708543", + "{\n}", + "2014-07-14T00:00:00Z", + "09 19 34 37 49", + "02" + ], + [ + 19, + "7A02B89B-7A1E-41F6-A4DD-D25CE447B9DE", + 19, + 1405652467, + "708543", + 1405652467, + "708543", + "{\n}", + "2014-07-17T00:00:00Z", + "08 09 22 46 51", + "01" + ], + [ + 21, + "3BFADF1B-EDD6-415A-8790-05AAEECFB7C3", + 21, + 1405998064, + "708543", + 1405998064, + "708543", + "{\n}", + "2014-07-21T00:00:00Z", + "04 06 11 24 31", + "03" + ], + [ + 23, + "EAAAAB4F-C17E-4129-B18A-5A2197AFBEAC", + 23, + 1406257265, + "708543", + 1406257265, + "708543", + "{\n}", + "2014-07-24T00:00:00Z", + "05 20 35 43 48", + "03" + ], + [ + 25, + "68097553-6CC4-4787-865A-747B130D5EBE", + 25, + 1406602865, + "708543", + 1406602865, + "708543", + "{\n}", + "2014-07-28T00:00:00Z", + "06 15 31 51 53", + "02" + ], + [ + 27, + "76996EA0-DD54-4EB5-B5C2-7FF8FE6E6386", + 27, + 1406862065, + "708543", + 1406862065, + "708543", + "{\n}", + "2014-07-31T00:00:00Z", + "13 25 26 32 58", + "01" + ], + [ + 29, + "91616BD7-CD64-4F70-92AD-260AED90744E", + 29, + 1407207665, + "708543", + 1407207665, + "708543", + "{\n}", + "2014-08-04T00:00:00Z", + "17 21 36 48 60", + "03" + ], + [ + 31, + "DB3F3DF6-C19A-4970-9F76-060B7D1DD383", + 31, + 1407466895, + "708543", + 1407466895, + "708543", + "{\n}", + "2014-08-07T00:00:00Z", + "03 18 38 40 49", + "02" + ], + [ + 33, + "60819CBF-EA03-477B-ABF2-0BD2242A9438", + 33, + 1407812457, + "708543", + 1407812457, + "708543", + "{\n}", + "2014-08-11T00:00:00Z", + "05 10 33 48 57", + "03" + ], + [ + 35, + "0C13DB12-A55A-42A7-A2BB-66D0C7C50645", + 35, + 1408071655, + "708543", + 1408071655, + "708543", + "{\n}", + "2014-08-14T00:00:00Z", + "03 11 34 46 60", + "02" + ], + [ + 37, + "1839C767-92D9-4A0D-8897-02DB365BA7C7", + 37, + 1408417266, + "708543", + 1408417266, + "708543", + "{\n}", + "2014-08-18T00:00:00Z", + "06 10 29 44 57", + "02" + ], + [ + 39, + "774C4C27-7C65-48D1-89AA-89C3D9AF5C6B", + 39, + 1408676455, + "708543", + 1408676455, + "708543", + "{\n}", + "2014-08-21T00:00:00Z", + "11 24 40 43 47", + "02" + ], + [ + 41, + "C1877239-185A-4B3D-946E-F5512047707A", + 41, + 1409022066, + "708543", + 1409022066, + "708543", + "{\n}", + "2014-08-25T00:00:00Z", + "06 08 34 40 59", + "04" + ], + [ + 43, + "0BB0CCA8-09D9-475F-B97A-8084266C10C3", + 43, + 1409281275, + "708543", + 1409281275, + "708543", + "{\n}", + "2014-08-28T00:00:00Z", + "12 24 27 38 49", + "02" + ], + [ + 45, + "6DB0C8AB-5075-4BB1-9149-2A7BEC028612", + 45, + 1409626855, + "708543", + 1409626855, + "708543", + "{\n}", + "2014-09-01T00:00:00Z", + "09 21 27 45 53", + "02" + ], + [ + 47, + "0374F671-02F0-4D00-AB0F-689BD851BBFF", + 47, + 1409886057, + "708543", + 1409886057, + "708543", + "{\n}", + "2014-09-04T00:00:00Z", + "03 21 28 32 56", + "03" + ], + [ + 49, + "DA294964-7674-4E5A-BBBC-D5452940E330", + 49, + 1410249467, + "708543", + 1410249467, + "708543", + "{\n}", + "2014-09-08T00:00:00Z", + "01 17 23 44 45", + "02" + ], + [ + 51, + "60E229E5-B1B3-4EB3-B235-ECE3320C2151", + 51, + 1410490873, + "708543", + 1410490873, + "708543", + "{\n}", + "2014-09-11T00:00:00Z", + "12 44 56 58 59", + "02" + ], + [ + 53, + "AF1C8CC1-1FBA-4462-9314-ED07B787BEF7", + 53, + 1410857335, + "708543", + 1410857335, + "708543", + "{\n}", + "2014-09-15T00:00:00Z", + "03 05 09 32 56", + "01" + ], + [ + 55, + "C7EB51A3-93B2-4A41-9CB7-E19F2294C189", + 55, + 1411138891, + "708543", + 1411138891, + "708543", + "{\n}", + "2014-09-18T00:00:00Z", + "05 10 11 24 28", + "03" + ], + [ + 57, + "AF5594CC-74AE-4B25-8D3A-E75AB61F320C", + 57, + 1411484595, + "708543", + 1411484595, + "708543", + "{\n}", + "2014-09-22T00:00:00Z", + "28 39 40 53 54", + "01" + ], + [ + 59, + "A5A781A5-5521-4B22-B514-F5DFA3F6D25A", + 59, + 1411741475, + "708543", + 1411741475, + "708543", + "{\n}", + "2014-09-25T00:00:00Z", + "09 11 28 30 41", + "04" + ], + [ + 61, + "6942D491-BAE6-4106-BBFF-9692E675D407", + 61, + 1412089290, + "708543", + 1412089290, + "708543", + "{\n}", + "2014-09-29T00:00:00Z", + "19 36 37 43 50", + "01" + ], + [ + 63, + "756710CC-B5F0-4283-8BA0-3689222F93BC", + 63, + 1412348485, + "708543", + 1412348485, + "708543", + "{\n}", + "2014-10-02T00:00:00Z", + "23 34 35 44 52", + "01" + ], + [ + 65, + "EFC086DD-DE15-4DD8-9310-16911270BB89", + 65, + 1412737309, + "708543", + 1412737309, + "708543", + "{\n}", + "2014-10-06T00:00:00Z", + "16 30 37 52 55", + "03" + ], + [ + 67, + "AA1A6D71-13B5-44E0-9B81-0BB34DAE7EA4", + 67, + 1412910109, + "708543", + 1412910109, + "708543", + "{\n}", + "2014-10-09T00:00:00Z", + "23 26 32 50 57", + "04" + ], + [ + 69, + "1335B8F0-D3F5-4F48-B286-3F798CBC701D", + 69, + 1413255710, + "708543", + 1413255710, + "708543", + "{\n}", + "2014-10-13T00:00:00Z", + "10 13 49 54 57", + "04" + ], + [ + 71, + "46182F8D-360D-488B-A4F9-05514FA57EFB", + 71, + 1413514894, + "708543", + 1413514894, + "708543", + "{\n}", + "2014-10-16T00:00:00Z", + "12 13 20 28 45", + "04" + ], + [ + 73, + "0EBA077B-BE4A-4D7C-9944-8741019B368E", + 73, + 1413860491, + "708543", + 1413860491, + "708543", + "{\n}", + "2014-10-20T00:00:00Z", + "08 16 43 52 59", + "03" + ], + [ + 75, + "4E97E80D-7E86-48D3-A356-461BDC559E2D", + 75, + 1414119691, + "708543", + 1414119691, + "708543", + "{\n}", + "2014-10-23T00:00:00Z", + "09 22 24 36 54", + "01" + ], + [ + 77, + "D79ED4C9-E736-4503-9F8F-44E814128A11", + 77, + 1414465287, + "708543", + 1414465287, + "708543", + "{\n}", + "2014-10-27T00:00:00Z", + "06 09 28 40 41", + "01" + ], + [ + 79, + "792BD778-BFDB-4778-A82C-FC9A225D944F", + 79, + 1414724491, + "708543", + 1414724491, + "708543", + "{\n}", + "2014-10-30T00:00:00Z", + "19 22 29 38 53", + "01" + ], + [ + 81, + "896D69B7-9696-4D2F-9534-540A5EFF5C46", + 81, + 1415113288, + "708543", + 1415113288, + "708543", + "{\n}", + "2014-11-03T00:00:00Z", + "03 27 28 49 52", + "04" + ], + [ + 83, + "0D294751-4AF6-47C1-A95E-9D9709CC0F7F", + 83, + 1415329353, + "708543", + 1415329353, + "708543", + "{\n}", + "2014-11-06T00:00:00Z", + "03 07 14 20 32", + "03" + ], + [ + 85, + "9FA03830-2A74-4DD2-85A0-0ABDDA81D1D1", + 85, + 1415804550, + "708543", + 1415804550, + "708543", + "{\n}", + "2014-11-10T00:00:00Z", + "07 21 30 53 55", + "02" + ], + [ + 87, + "38EC3289-915B-4D7B-8B5A-6C70EC890078", + 87, + 1415934097, + "708543", + 1415934097, + "708543", + "{\n}", + "2014-11-13T00:00:00Z", + "07 08 16 49 56", + "04" + ], + [ + 89, + "4BB65C7D-C7AE-4B3B-B97B-04AB4F0F8837", + 89, + 1416279689, + "708543", + 1416279689, + "708543", + "{\n}", + "2014-11-17T00:00:00Z", + "08 23 37 38 58", + "01" + ], + [ + 91, + "AACF639A-77E9-4D8C-8998-75A1A9279F42", + 91, + 1416538890, + "708543", + 1416538890, + "708543", + "{\n}", + "2014-11-20T00:00:00Z", + "02 40 46 59 60", + "02" + ], + [ + 93, + "E4FBC55A-B4ED-468A-A44C-CE5445C21A1B", + 93, + 1416884510, + "708543", + 1416884510, + "708543", + "{\n}", + "2014-11-24T00:00:00Z", + "08 25 26 33 56", + "01" + ], + [ + 95, + "776BD8AD-7BBC-45E0-8E90-39811986C977", + 95, + 1417143689, + "708543", + 1417143689, + "708543", + "{\n}", + "2014-11-27T00:00:00Z", + "09 30 43 51 55", + "03" + ], + [ + 97, + "EBF6ECC5-0B85-438D-8A46-9FCE5E519E29", + 97, + 1417489289, + "708543", + 1417489289, + "708543", + "{\n}", + "2014-12-01T00:00:00Z", + "04 07 33 50 55", + "01" + ], + [ + 99, + "33276E54-A25A-4344-9522-952660A46FC6", + 99, + 1417748490, + "708543", + 1417748490, + "708543", + "{\n}", + "2014-12-04T00:00:00Z", + "01 15 21 41 60", + "04" + ], + [ + 101, + "1A59B642-300B-4971-97A2-2EEB3B617A96", + 101, + 1418094070, + "708543", + 1418094070, + "708543", + "{\n}", + "2014-12-08T00:00:00Z", + "04 11 14 46 59", + "04" + ], + [ + 103, + "A9B2120A-45B0-4B5A-91A6-2CD14B6CB804", + 103, + 1418353294, + "708543", + 1418353294, + "708543", + "{\n}", + "2014-12-11T00:00:00Z", + "12 22 27 35 49", + "04" + ], + [ + 105, + "BF8D8512-533A-47D8-B958-1D53A359D5F6", + 105, + 1418698895, + "708543", + 1418698895, + "708543", + "{\n}", + "2014-12-15T00:00:00Z", + "08 22 31 38 40", + "03" + ], + [ + 107, + "520953D2-4DFD-404D-8D61-713CBDD641E5", + 107, + 1418958101, + "708543", + 1418958101, + "708543", + "{\n}", + "2014-12-18T00:00:00Z", + "20 22 26 27 43", + "02" + ], + [ + 109, + "5A0507CF-B794-43A6-A30D-9B830091D8A3", + 109, + 1419303692, + "708543", + 1419303692, + "708543", + "{\n}", + "2014-12-22T00:00:00Z", + "03 17 30 50 55", + "03" + ], + [ + 111, + "E12FA573-ED28-4726-8E80-9783452BECA0", + 111, + 1419562871, + "708543", + 1419562871, + "708543", + "{\n}", + "2014-12-25T00:00:00Z", + "05 14 22 37 60", + "02" + ], + [ + 113, + "E194E4AF-152C-4229-88F9-45F7629E0ABF", + 113, + 1419908521, + "708543", + 1419908521, + "708543", + "{\n}", + "2014-12-29T00:00:00Z", + "08 09 35 37 41", + "04" + ], + [ + 115, + "BBB2C4CC-93DE-4015-B820-FB007F1CB762", + 115, + 1420167754, + "708543", + 1420167754, + "708543", + "{\n}", + "2015-01-01T00:00:00Z", + "13 19 20 21 35", + "02" + ], + [ + 117, + "ED96AB53-FCDB-46E9-8440-3655AC3FB34C", + 117, + 1420513290, + "708543", + 1420513290, + "708543", + "{\n}", + "2015-01-05T00:00:00Z", + "12 23 29 38 43", + "03" + ], + [ + 119, + "0C5A0B65-8D2D-4839-8786-5081A47668C8", + 119, + 1420772494, + "708543", + 1420772494, + "708543", + "{\n}", + "2015-01-08T00:00:00Z", + "16 28 38 43 45", + "03" + ], + [ + 121, + "D42D2EBF-7700-4F5B-9BC0-FD5637A19FD9", + 121, + 1421118090, + "708543", + 1421118090, + "708543", + "{\n}", + "2015-01-12T00:00:00Z", + "01 05 11 39 47", + "01" + ], + [ + 123, + "008F206D-92EB-4A20-B887-E6689B25E3E2", + 123, + 1421377288, + "708543", + 1421377288, + "708543", + "{\n}", + "2015-01-15T00:00:00Z", + "12 15 22 25 27", + "03" + ], + [ + 125, + "0E8CB1B4-823F-4E60-A773-1A939E96DC06", + 125, + 1421722893, + "708543", + 1421722893, + "708543", + "{\n}", + "2015-01-19T00:00:00Z", + "18 29 47 52 53", + "03" + ], + [ + 127, + "2AA47495-72C5-4086-98EF-CDE64374946E", + 127, + 1421982100, + "708543", + 1421982100, + "708543", + "{\n}", + "2015-01-22T00:00:00Z", + "08 11 35 47 60", + "02" + ], + [ + 129, + "60873354-72B3-48C2-8CB3-13BD630B4DBC", + 129, + 1422327709, + "708543", + 1422327709, + "708543", + "{\n}", + "2015-01-26T00:00:00Z", + "01 20 24 46 57", + "01" + ], + [ + 131, + "9E0C5355-4E03-477D-A073-4BED0B3A24C1", + 131, + 1422586894, + "708543", + 1422586894, + "708543", + "{\n}", + "2015-01-29T00:00:00Z", + "08 24 28 57 60", + "02" + ], + [ + 133, + "EFA8A999-2C71-4357-81B8-DD1FBBBEDB2A", + 133, + 1422932500, + "708543", + 1422932500, + "708543", + "{\n}", + "2015-02-02T00:00:00Z", + "04 08 17 20 21", + "04" + ], + [ + 135, + "42FB45D1-A071-4F57-9CE2-08A01CDDF478", + 135, + 1423191694, + "708543", + 1423191694, + "708543", + "{\n}", + "2015-02-05T00:00:00Z", + "14 17 38 40 45", + "02" + ], + [ + 137, + "11ECE352-720D-42CC-9205-4CDF6500FA83", + 137, + 1423537294, + "708543", + 1423537294, + "708543", + "{\n}", + "2015-02-09T00:00:00Z", + "09 17 36 38 53", + "04" + ], + [ + 139, + "93BCF5A7-5C23-4672-AC03-40720ED5F22B", + 139, + 1423796489, + "708543", + 1423796489, + "708543", + "{\n}", + "2015-02-12T00:00:00Z", + "06 11 32 56 60", + "02" + ], + [ + 141, + "D322B0C0-56A8-4374-A29A-80CFDE1D6543", + 141, + 1424142113, + "708543", + 1424142113, + "708543", + "{\n}", + "2015-02-16T00:00:00Z", + "06 26 35 40 43", + "02" + ], + [ + 143, + "DC6AD720-4BF5-4C4F-95A0-752F916BBEFF", + 143, + 1424401290, + "708543", + 1424401290, + "708543", + "{\n}", + "2015-02-19T00:00:00Z", + "18 43 51 52 60", + "04" + ], + [ + 145, + "9E251D18-D632-4E4E-BE91-389DAC1E83EF", + 145, + 1424746886, + "708543", + 1424746886, + "708543", + "{\n}", + "2015-02-23T00:00:00Z", + "01 14 20 21 43", + "04" + ], + [ + 147, + "E4F2CA88-3B82-48DF-8BCC-0F48ED01025E", + 147, + 1425049289, + "708543", + 1425049289, + "708543", + "{\n}", + "2015-02-26T00:00:00Z", + "03 16 20 38 49", + "03" + ], + [ + 149, + "A0BC2444-1A83-4EC9-A5C7-DD4BEBEC8BAC", + 149, + 1425351687, + "708543", + 1425351687, + "708543", + "{\n}", + "2015-03-02T00:00:00Z", + "08 23 27 38 47", + "04" + ], + [ + 151, + "DEA71FE8-C1A6-4822-AFAA-21E11860F30E", + 151, + 1425610898, + "708543", + 1425610898, + "708543", + "{\n}", + "2015-03-05T00:00:00Z", + "10 22 46 47 48", + "04" + ], + [ + 153, + "7CDE1F9C-B37A-4688-B430-4B876FF1E3AC", + 153, + 1425956488, + "708543", + 1425956488, + "708543", + "{\n}", + "2015-03-09T00:00:00Z", + "19 34 35 54 57", + "03" + ], + [ + 155, + "05A29298-CC69-4E09-BEA3-5A2C9BA94CAA", + 155, + 1426561286, + "708543", + 1426561286, + "708543", + "{\n}", + "2015-03-16T00:00:00Z", + "12 18 33 44 46", + "01" + ], + [ + 157, + "6CCFF205-6249-4098-BCEE-133280F60530", + 157, + 1426820509, + "708543", + 1426820509, + "708543", + "{\n}", + "2015-03-19T00:00:00Z", + "02 12 28 51 54", + "01" + ], + [ + 159, + "E1D85EB5-A7E8-419E-9BBC-4FC4E30128A1", + 159, + 1427166105, + "708543", + 1427166105, + "708543", + "{\n}", + "2015-03-23T00:00:00Z", + "18 26 28 35 36", + "04" + ], + [ + 161, + "F4F2FB7D-6BD3-4DF3-A3BB-A8572B4F99DA", + 161, + 1427425305, + "708543", + 1427425305, + "708543", + "{\n}", + "2015-03-26T00:00:00Z", + "06 35 36 47 53", + "02" + ], + [ + 163, + "5BCAA6C8-600B-42A8-AE34-259DC41EC39B", + 163, + 1427770905, + "708543", + 1427770905, + "708543", + "{\n}", + "2015-03-30T00:00:00Z", + "09 23 43 45 52", + "02" + ], + [ + 165, + "845ECC12-550A-4E48-B410-47AE380B0456", + 165, + 1428030106, + "708543", + 1428030106, + "708543", + "{\n}", + "2015-04-02T00:00:00Z", + "15 22 29 34 37", + "03" + ], + [ + 167, + "2B936DE6-6D4B-4FA1-9F98-CF5C39A7A0B6", + 167, + 1428375707, + "708543", + 1428375707, + "708543", + "{\n}", + "2015-04-06T00:00:00Z", + "02 16 20 25 50", + "03" + ], + [ + 169, + "ABA57A21-845C-43BD-A750-462A07940823", + 169, + 1428634907, + "708543", + 1428634907, + "708543", + "{\n}", + "2015-04-09T00:00:00Z", + "05 07 27 43 50", + "03" + ], + [ + 171, + "8A3DF170-CB4F-4B1C-882D-A91384A892FA", + 171, + 1428980487, + "708543", + 1428980487, + "708543", + "{\n}", + "2015-04-13T00:00:00Z", + "07 17 26 34 60", + "04" + ], + [ + 173, + "C8CE05E3-B5CA-4289-8704-6652FE4DB081", + 173, + 1429239707, + "708543", + 1429239707, + "708543", + "{\n}", + "2015-04-16T00:00:00Z", + "01 06 11 13 23", + "01" + ], + [ + 175, + "67068049-9182-466F-841B-191C0C834971", + 175, + 1429585286, + "708543", + 1429585286, + "708543", + "{\n}", + "2015-04-20T00:00:00Z", + "35 36 37 53 56", + "04" + ], + [ + 177, + "2B244FB4-5148-42BB-8C0F-18F72302A072", + 177, + 1429844487, + "708543", + 1429844487, + "708543", + "{\n}", + "2015-04-23T00:00:00Z", + "03 12 30 40 56", + "02" + ], + [ + 179, + "BE06E4D1-AE96-40F3-97A5-5A937E0983D5", + 179, + 1430190127, + "708543", + 1430190127, + "708543", + "{\n}", + "2015-04-27T00:00:00Z", + "13 14 29 46 47", + "01" + ], + [ + 181, + "5FC39380-1949-40E6-B9DD-5FB1648901D7", + 181, + 1430449308, + "708543", + 1430449308, + "708543", + "{\n}", + "2015-04-30T00:00:00Z", + "09 26 29 46 58", + "02" + ], + [ + 183, + "12EA4AE4-F823-427B-9DF7-AAE2BB7DCA08", + 183, + 1430794909, + "708543", + 1430794909, + "708543", + "{\n}", + "2015-05-04T00:00:00Z", + "03 05 21 30 60", + "04" + ], + [ + 185, + "D9E721A6-B28A-4811-BC5D-D2BDAABA692F", + 185, + 1431054131, + "708543", + 1431054131, + "708543", + "{\n}", + "2015-05-07T00:00:00Z", + "04 11 44 47 53", + "02" + ], + [ + 187, + "5BF8802C-A0CE-4DA2-B482-3133F62C4B77", + 187, + 1431399749, + "708543", + 1431399749, + "708543", + "{\n}", + "2015-05-11T00:00:00Z", + "07 08 14 18 52", + "01" + ], + [ + 189, + "90482458-111E-4B10-B506-3D3B50C5013D", + 189, + 1431659009, + "708543", + 1431659009, + "708543", + "{\n}", + "2015-05-14T00:00:00Z", + "06 28 34 39 43", + "02" + ], + [ + 191, + "DD2AF2B3-DBB3-44ED-A0D6-1E1BE8D10624", + 191, + 1432004548, + "708543", + 1432004548, + "708543", + "{\n}", + "2015-05-18T00:00:00Z", + "16 30 35 38 51", + "01" + ], + [ + 193, + "41866238-C5D3-4CC9-9E88-A15076EA3C50", + 193, + 1432263708, + "708543", + 1432263708, + "708543", + "{\n}", + "2015-05-21T00:00:00Z", + "18 22 24 29 56", + "04" + ], + [ + 195, + "86C4BD79-F837-4B0E-A2D7-FB8EA3623DC8", + 195, + 1432609440, + "708543", + 1432609440, + "708543", + "{\n}", + "2015-05-25T00:00:00Z", + "15 40 48 59 60", + "01" + ], + [ + 197, + "88A989DB-863E-481F-825E-632FEE7BF997", + 197, + 1432868513, + "708543", + 1432868513, + "708543", + "{\n}", + "2015-05-28T00:00:00Z", + "08 25 28 33 47", + "01" + ], + [ + 199, + "168810EE-D7D4-4CA0-B514-2F78BFBC2CA4", + 199, + 1433214108, + "708543", + 1433214108, + "708543", + "{\n}", + "2015-06-01T00:00:00Z", + "07 10 23 37 56", + "03" + ], + [ + 201, + "D5E3EC37-3306-41FE-99C9-9A6C18983111", + 201, + 1433473306, + "708543", + 1433473306, + "708543", + "{\n}", + "2015-06-04T00:00:00Z", + "04 09 32 41 43", + "02" + ], + [ + 203, + "BE6B2BA7-5F95-4A31-9DF3-8BF03DFCA091", + 203, + 1433818929, + "708543", + 1433818929, + "708543", + "{\n}", + "2015-06-08T00:00:00Z", + "33 39 43 49 52", + "03" + ], + [ + 205, + "FC34C3C6-2380-4FE3-8D7E-5913155A26C9", + 205, + 1434078114, + "708543", + 1434078114, + "708543", + "{\n}", + "2015-06-11T00:00:00Z", + "17 24 43 49 57", + "02" + ], + [ + 207, + "CD40F120-C2CB-48C5-A139-622DEB4F65B6", + 207, + 1434423759, + "708543", + 1434423759, + "708543", + "{\n}", + "2015-06-15T00:00:00Z", + "10 14 16 32 34", + "03" + ], + [ + 209, + "E983452E-64EC-400E-93D1-70D70F5F20E2", + 209, + 1434682981, + "708543", + 1434682981, + "708543", + "{\n}", + "2015-06-18T00:00:00Z", + "01 02 14 29 59", + "03" + ], + [ + 211, + "9656A33A-C34E-4F34-A928-5010D8584C0C", + 211, + 1435028542, + "708543", + 1435028542, + "708543", + "{\n}", + "2015-06-22T00:00:00Z", + "05 26 27 51 59", + "02" + ], + [ + 213, + "EBF6F368-12B2-4DA9-941C-9A1CD9982750", + 213, + 1435287707, + "708543", + 1435287707, + "708543", + "{\n}", + "2015-06-25T00:00:00Z", + "03 26 27 29 58", + "01" + ], + [ + 215, + "C95EA299-841C-470A-A919-660D41CB7A19", + 215, + 1435633286, + "708543", + 1435633286, + "708543", + "{\n}", + "2015-06-29T00:00:00Z", + "01 19 37 49 56", + "03" + ], + [ + 217, + "8E894D24-2D77-4E0C-ADFE-39BC258A29DC", + 217, + 1435892551, + "708543", + 1435892551, + "708543", + "{\n}", + "2015-07-02T00:00:00Z", + "18 19 31 43 54", + "03" + ], + [ + 219, + "8536A4D2-1AD1-4009-A572-3E5A6162C627", + 219, + 1436238167, + "708543", + 1436238167, + "708543", + "{\n}", + "2015-07-06T00:00:00Z", + "03 10 30 33 40", + "01" + ], + [ + 221, + "C46245BD-9AE0-441F-B363-E17E984A3CFA", + 221, + 1436497289, + "708543", + 1436497289, + "708543", + "{\n}", + "2015-07-09T00:00:00Z", + "19 34 36 54 55", + "01" + ], + [ + 223, + "4BDC3777-34BD-4258-8E5C-A964D265E8A6", + 223, + 1436842990, + "708543", + 1436842990, + "708543", + null, + "2015-07-13T00:00:00Z", + "05 23 27 55 57", + "01" + ], + [ + 224, + "10889320-B901-47FC-AFD6-75BDE9356FF7", + 224, + 1437102065, + "708543", + 1437102065, + "708543", + null, + "2015-07-16T00:00:00Z", + "22 29 47 53 54", + "03" + ], + [ + 225, + "9A754F78-F807-4021-B9A7-035BA2C6CBE1", + 225, + 1437447725, + "708543", + 1437447725, + "708543", + null, + "2015-07-20T00:00:00Z", + "10 29 47 48 55", + "04" + ], + [ + 226, + "8EA5F297-5030-4AA2-AE0E-9A71375EE66B", + 226, + 1437706890, + "708543", + 1437706890, + "708543", + null, + "2015-07-23T00:00:00Z", + "08 26 28 41 52", + "04" + ], + [ + 227, + "6373AF9F-31E8-4346-9422-1994C4DE879D", + 227, + 1438052506, + "708543", + 1438052506, + "708543", + null, + "2015-07-27T00:00:00Z", + "03 05 36 43 53", + "03" + ], + [ + 228, + "498DEED9-EFBF-4296-B13B-AEC0017F3135", + 228, + 1438311725, + "708543", + 1438311725, + "708543", + null, + "2015-07-30T00:00:00Z", + "15 16 26 27 51", + "02" + ], + [ + 229, + "9E06C3EA-C137-4F17-A67F-C8CE28D8BEF8", + 229, + 1438657327, + "708543", + 1438657327, + "708543", + null, + "2015-08-03T00:00:00Z", + "25 29 30 38 39", + "03" + ], + [ + 230, + "05461696-20D9-417B-90D2-4351469BBA1F", + 230, + 1438916529, + "708543", + 1438916529, + "708543", + null, + "2015-08-06T00:00:00Z", + "04 05 24 31 42", + "02" + ], + [ + 231, + "DF0DB2F5-0C4E-4953-B716-B95ADAE9A742", + 231, + 1439262152, + "708543", + 1439262152, + "708543", + null, + "2015-08-10T00:00:00Z", + "02 07 11 33 47", + "02" + ], + [ + 232, + "74954961-473B-4546-8C15-42BBDD81C47B", + 232, + 1439564546, + "708543", + 1439564546, + "708543", + null, + "2015-08-13T00:00:00Z", + "08 12 50 51 56", + "04" + ], + [ + 233, + "CAC3EB9F-5BF5-454A-86BD-68A3F18DBDB6", + 233, + 1439866949, + "708543", + 1439866949, + "708543", + null, + "2015-08-17T00:00:00Z", + "05 19 21 24 27", + "03" + ], + [ + 234, + "910E19A6-4152-4BDE-9BF1-60AA55BED6F3", + 234, + 1440126149, + "708543", + 1440126149, + "708543", + null, + "2015-08-20T00:00:00Z", + "06 14 25 39 56", + "04" + ], + [ + 235, + "03CF6AAE-2276-4DC4-AC2D-7F9A038AA615", + 235, + 1440471749, + "708543", + 1440471749, + "708543", + null, + "2015-08-24T00:00:00Z", + "02 19 35 37 44", + "03" + ], + [ + 236, + "21833935-DBB4-4A8C-ACEB-8C28EC36AD6B", + 236, + 1440730943, + "708543", + 1440730943, + "708543", + null, + "2015-08-27T00:00:00Z", + "05 29 37 55 58", + "02" + ], + [ + 237, + "05804F56-7B0A-4227-9EF4-2E98CA8B9129", + 237, + 1441076532, + "708543", + 1441076532, + "708543", + null, + "2015-08-31T00:00:00Z", + "12 15 44 45 47", + "01" + ], + [ + 238, + "69159851-6432-4A78-83D8-4D47C1871671", + 238, + 1441335740, + "708543", + 1441335740, + "708543", + null, + "2015-09-03T00:00:00Z", + "20 33 46 49 51", + "04" + ], + [ + 239, + "C1500EE4-EB00-4C95-B624-88DC44D43872", + 239, + 1441681331, + "708543", + 1441681331, + "708543", + null, + "2015-09-07T00:00:00Z", + "04 21 26 45 46", + "04" + ], + [ + 240, + "D7558560-CCF8-430B-A516-6A02D1C6C6BC", + 240, + 1442286105, + "708543", + 1442286105, + "708543", + null, + "2015-09-14T00:00:00Z", + "03 07 14 19 25", + "02" + ], + [ + 241, + "819B7082-516B-4A46-94ED-CD29F5AFF3AF", + 241, + 1442545304, + "708543", + 1442545304, + "708543", + null, + "2015-09-17T00:00:00Z", + "14 15 17 35 56", + "02" + ], + [ + 242, + "9F4B80B3-0FC2-41CA-A394-E1FD348C43D5", + 242, + 1442890890, + "708543", + 1442890890, + "708543", + null, + "2015-09-21T00:00:00Z", + "17 27 39 44 49", + "01" + ], + [ + 243, + "3D22C9B7-519E-4549-BCF9-7DD9B46A441A", + 243, + 1442934107, + "708543", + 1442934107, + "708543", + null, + "2015-09-10T00:00:00Z", + "11 16 50 55 56", + "04" + ], + [ + 244, + "46D6D1F4-BD73-4959-9240-FEC3E7D0F0CF", + 244, + 1443150147, + "708543", + 1443150147, + "708543", + null, + "2015-09-24T00:00:00Z", + "14 17 29 39 50", + "03" + ], + [ + 245, + "49D625D0-79BE-4144-A9BE-F1BE234D202D", + 245, + 1443495706, + "708543", + 1443495706, + "708543", + null, + "2015-09-28T00:00:00Z", + "01 25 29 43 54", + "02" + ], + [ + 246, + "DC858348-F3ED-4D7C-858C-E914015E5E6A", + 246, + 1443754927, + "708543", + 1443754927, + "708543", + null, + "2015-10-01T00:00:00Z", + "25 37 39 47 55", + "03" + ], + [ + 247, + "81C2B637-F49A-41B4-800F-1D6DDC3ACF3E", + 247, + 1444100546, + "708543", + 1444100546, + "708543", + null, + "2015-10-05T00:00:00Z", + "08 20 34 41 43", + "03" + ], + [ + 248, + "9013BCB6-CE28-4C96-ADC8-25C2329E6653", + 248, + 1444359767, + "708543", + 1444359767, + "708543", + null, + "2015-10-08T00:00:00Z", + "25 27 28 42 53", + "02" + ], + [ + 249, + "8B2BA24A-545E-4453-939D-7B9AF5A82F1B", + 249, + 1444705326, + "708543", + 1444705326, + "708543", + null, + "2015-10-12T00:00:00Z", + "28 30 36 38 39", + "04" + ], + [ + 250, + "F0E3B49C-EF02-4205-8C7C-06B79D869EB0", + 250, + 1444964525, + "708543", + 1444964525, + "708543", + null, + "2015-10-15T00:00:00Z", + "07 11 39 40 45", + "02" + ], + [ + 251, + "BDAA2D7D-27B1-45EA-A1FB-7A5D0F0FCED2", + 251, + 1445310125, + "708543", + 1445310125, + "708543", + null, + "2015-10-19T00:00:00Z", + "04 08 31 46 54", + "03" + ], + [ + 252, + "7423590E-8D14-45A2-9820-0AA6E0F39573", + 252, + 1445569305, + "708543", + 1445569305, + "708543", + null, + "2015-10-22T00:00:00Z", + "05 18 45 52 57", + "02" + ], + [ + 253, + "40D07FF0-0812-4BA8-96CC-777F1BE5CC81", + 253, + 1445914946, + "708543", + 1445914946, + "708543", + null, + "2015-10-26T00:00:00Z", + "17 20 45 49 58", + "02" + ], + [ + 254, + "70C6BBEF-E408-489E-8944-F99F53CA4108", + 254, + 1446174085, + "708543", + 1446174085, + "708543", + null, + "2015-10-29T00:00:00Z", + "10 31 32 34 51", + "04" + ], + [ + 255, + "CD77860A-B40A-4809-8C24-3FA2360ED81A", + 255, + 1446519796, + "708543", + 1446519796, + "708543", + null, + "2015-11-02T00:00:00Z", + "01 07 12 34 44", + "01" + ], + [ + 256, + "C558D5E5-22CC-43EA-BDA7-D44CCFB7F83A", + 256, + 1446778887, + "708543", + 1446778887, + "708543", + null, + "2015-11-05T00:00:00Z", + "13 20 25 31 51", + "03" + ], + [ + 257, + "7461A9DC-4A7C-4E6F-90A2-AD8B7D5797D4", + 257, + 1447124506, + "708543", + 1447124506, + "708543", + null, + "2015-11-09T00:00:00Z", + "06 09 11 27 37", + "03" + ], + [ + 258, + "F49A1AEC-852B-4F80-A7B4-8A1C92B3DE82", + 258, + 1447383624, + "708543", + 1447383624, + "708543", + null, + "2015-11-12T00:00:00Z", + "06 41 44 49 56", + "04" + ], + [ + 259, + "4E5D11CB-2D6A-4221-A4C4-3ABC18F9FB46", + 259, + 1447729327, + "708543", + 1447729327, + "708543", + null, + "2015-11-16T00:00:00Z", + "06 20 28 34 40", + "03" + ], + [ + 260, + "416BEBC5-580E-4D05-9749-C0F135231E80", + 260, + 1447988529, + "708543", + 1447988529, + "708543", + null, + "2015-11-19T00:00:00Z", + "02 07 21 38 48", + "04" + ], + [ + 261, + "B1D35BFE-94AC-424B-868F-0F6F15AD4EB4", + 261, + 1448334106, + "708543", + 1448334106, + "708543", + null, + "2015-11-23T00:00:00Z", + "04 21 42 43 59", + "04" + ], + [ + 262, + "14B39058-519A-4E79-9012-BE289B006246", + 262, + 1448593285, + "708543", + 1448593285, + "708543", + null, + "2015-11-26T00:00:00Z", + "13 23 43 47 59", + "03" + ], + [ + 263, + "0511598D-7453-4CFF-BA2C-E58525A8AFF0", + 263, + 1448938966, + "708543", + 1448938966, + "708543", + null, + "2015-11-30T00:00:00Z", + "04 07 08 19 53", + "04" + ], + [ + 264, + "BA08DC3D-1F1A-4F33-B8DC-1EAD043EDA4A", + 264, + 1449198126, + "708543", + 1449198126, + "708543", + null, + "2015-12-03T00:00:00Z", + "08 10 27 37 39", + "01" + ], + [ + 265, + "E6957ED1-4C85-42E5-B20F-A413B19E9AD9", + 265, + 1449543688, + "708543", + 1449543688, + "708543", + null, + "2015-12-07T00:00:00Z", + "03 05 36 40 44", + "02" + ], + [ + 266, + "9CE576B4-F88C-4AEB-905F-6EAF7F29C942", + 266, + 1449802936, + "708543", + 1449802936, + "708543", + null, + "2015-12-10T00:00:00Z", + "10 47 48 53 58", + "02" + ], + [ + 267, + "76C71A89-020A-4154-89CB-E7E8FFFE597A", + 267, + 1450148626, + "708543", + 1450148626, + "708543", + null, + "2015-12-14T00:00:00Z", + "46 50 56 57 58", + "01" + ], + [ + 268, + "90567CD2-57B0-4436-84FB-9FFB867E870F", + 268, + 1450407725, + "708543", + 1450407725, + "708543", + null, + "2015-12-17T00:00:00Z", + "26 49 52 54 56", + "01" + ], + [ + 269, + "8B379FC0-AF52-437C-99E5-7F12F4F92213", + 269, + 1450753388, + "708543", + 1450753388, + "708543", + null, + "2015-12-21T00:00:00Z", + "09 27 33 40 49", + "03" + ], + [ + 270, + "74367FD8-49EB-40D0-B411-210103794D50", + 270, + 1451012527, + "708543", + 1451012527, + "708543", + null, + "2015-12-24T00:00:00Z", + "05 19 36 41 55", + "02" + ], + [ + 271, + "93018B4E-8B54-45CC-B998-A5BF858BDC9F", + 271, + 1451358229, + "708543", + 1451358229, + "708543", + null, + "2015-12-28T00:00:00Z", + "07 11 16 23 24", + "02" + ], + [ + 272, + "A295AB45-D532-44E4-BACA-AC0A70587F5E", + 272, + 1451617326, + "708543", + 1451617326, + "708543", + null, + "2015-12-31T00:00:00Z", + "01 05 24 47 55", + "01" + ], + [ + 273, + "B8E84552-9E0A-4B17-836B-AAE4079BC556", + 273, + 1451962965, + "708543", + 1451962965, + "708543", + null, + "2016-01-04T00:00:00Z", + "08 19 25 51 52", + "03" + ], + [ + 274, + "BE18BC72-52BE-4033-B8A9-4626A8CF0EEB", + 274, + 1451963067, + "708543", + 1451963067, + "708543", + null, + "2015-03-12T00:00:00Z", + "03 06 17 47 48", + "01" + ], + [ + 275, + "2E040FA4-DBA5-4784-9B4D-2876309578F3", + 275, + 1452222146, + "708543", + 1452222146, + "708543", + null, + "2016-01-07T00:00:00Z", + "14 31 37 54 56", + "01" + ], + [ + 276, + "4FDFAA43-4862-4F0A-B041-BC3ADA834F35", + 276, + 1452567745, + "708543", + 1452567745, + "708543", + null, + "2016-01-11T00:00:00Z", + "04 20 30 34 36", + "02" + ], + [ + 277, + "CFAA63BC-0EA2-4CB5-9E1A-AB5D99D0DB67", + 277, + 1452826946, + "708543", + 1452826946, + "708543", + null, + "2016-01-14T00:00:00Z", + "23 27 29 36 60", + "04" + ], + [ + 278, + "2A929F8D-6EF6-4468-8AAE-FB650C9C0575", + 278, + 1453172605, + "708543", + 1453172605, + "708543", + null, + "2016-01-18T00:00:00Z", + "14 17 39 43 51", + "03" + ], + [ + 279, + "713D5E49-AB48-49B7-9E0A-983831BA98B9", + 279, + 1453431707, + "708543", + 1453431707, + "708543", + null, + "2016-01-21T00:00:00Z", + "11 13 36 46 48", + "04" + ], + [ + 280, + "87722842-E694-462C-BCE2-33F27977EAFF", + 280, + 1453777406, + "708543", + 1453777406, + "708543", + null, + "2016-01-25T00:00:00Z", + "19 24 38 55 56", + "04" + ], + [ + 281, + "47C6704D-9200-4B34-B220-05C000CF8FA0", + 281, + 1454036487, + "708543", + 1454036487, + "708543", + null, + "2016-01-28T00:00:00Z", + "04 05 15 25 59", + "02" + ], + [ + 282, + "7BBFAE55-5759-4C8C-957A-6B492291B6A8", + 282, + 1454382227, + "708543", + 1454382227, + "708543", + null, + "2016-02-01T00:00:00Z", + "02 09 22 43 44", + "01" + ], + [ + 283, + "C121AB49-5B80-494E-8F1A-BFBD4A303F77", + 283, + 1454641306, + "708543", + 1454641306, + "708543", + null, + "2016-02-04T00:00:00Z", + "08 12 23 40 54", + "01" + ], + [ + 284, + "7B04BDF0-3D43-48EA-ADE6-9CD4834A07CB", + 284, + 1454987128, + "708543", + 1454987128, + "708543", + null, + "2016-02-08T00:00:00Z", + "13 23 48 57 59", + "02" + ], + [ + 285, + "82C7F79A-D888-4ADF-9588-E26CEFBECCDD", + 285, + 1455246328, + "708543", + 1455246328, + "708543", + null, + "2016-02-11T00:00:00Z", + "06 31 35 40 55", + "02" + ], + [ + 286, + "8EC5B96F-C188-4465-89EB-F887EB3D0EE1", + 286, + 1455591808, + "708543", + 1455591808, + "708543", + null, + "2016-02-15T00:00:00Z", + "02 09 30 37 42", + "02" + ], + [ + 287, + "C8975BF7-2707-4128-B038-CA24C6479AC6", + 287, + 1455850911, + "708543", + 1455850911, + "708543", + null, + "2016-02-18T00:00:00Z", + "21 24 37 38 49", + "04" + ], + [ + 288, + "C2C83C0F-110F-48DF-BB4B-5FA814445E21", + 288, + 1456196566, + "708543", + 1456196566, + "708543", + null, + "2016-02-22T00:00:00Z", + "08 09 10 11 27", + "04" + ], + [ + 289, + "70EA9E33-5346-4356-8B0D-BB5D4994D0C2", + 289, + 1456455707, + "708543", + 1456455707, + "708543", + null, + "2016-02-25T00:00:00Z", + "02 16 19 33 39", + "03" + ], + [ + 290, + "77747333-4D77-461B-91BE-321169F75BBE", + 290, + 1456801366, + "708543", + 1456801366, + "708543", + null, + "2016-02-29T00:00:00Z", + "03 17 26 47 58", + "01" + ], + [ + 291, + "8B5BFF9C-D3B5-4363-8919-9920B32B5972", + 291, + 1457060507, + "708543", + 1457060507, + "708543", + null, + "2016-03-03T00:00:00Z", + "07 13 35 40 45", + "04" + ], + [ + 292, + "0A190D1C-A984-4C3B-85A3-7888E3EB6AFB", + 292, + 1457406146, + "708543", + 1457406146, + "708543", + null, + "2016-03-07T00:00:00Z", + "09 21 24 37 38", + "02" + ], + [ + 293, + "D5CF7DBD-F742-46B5-933B-0461C4AF35BD", + 293, + 1457665307, + "708543", + 1457665307, + "708543", + null, + "2016-03-10T00:00:00Z", + "06 12 21 40 57", + "01" + ], + [ + 294, + "438D098F-0FD7-4AE4-ABE1-5F3B627598A6", + 294, + 1458010948, + "708543", + 1458010948, + "708543", + null, + "2016-03-14T00:00:00Z", + "17 28 37 38 41", + "01" + ], + [ + 295, + "3753CF29-DD5E-4E34-B0B2-DCE5A4705745", + 295, + 1458270085, + "708543", + 1458270085, + "708543", + null, + "2016-03-17T00:00:00Z", + "11 16 34 44 56", + "01" + ], + [ + 296, + "D72F0087-09BE-49E2-AC57-6745208BFD3A", + 296, + 1458615706, + "708543", + 1458615706, + "708543", + null, + "2016-03-21T00:00:00Z", + "13 30 41 50 55", + "01" + ], + [ + 297, + "E3AA41F1-C4D0-4868-AB15-115FC538A42D", + 297, + 1458874906, + "708543", + 1458874906, + "708543", + null, + "2016-03-24T00:00:00Z", + "17 24 30 45 48", + "03" + ], + [ + 298, + "C2BF8733-16B5-4227-8C6A-B844DB98C50C", + 298, + 1459220505, + "708543", + 1459220505, + "708543", + null, + "2016-03-28T00:00:00Z", + "20 33 49 53 56", + "04" + ], + [ + 299, + "4F49FA6F-1798-4D53-A584-C20494804316", + 299, + 1459479705, + "708543", + 1459479705, + "708543", + null, + "2016-03-31T00:00:00Z", + "09 17 28 38 45", + "01" + ], + [ + 300, + "A447AD72-8550-482E-97C7-3C99DF68E0CF", + 300, + 1459825329, + "708543", + 1459825329, + "708543", + null, + "2016-04-04T00:00:00Z", + "05 26 32 36 58", + "04" + ], + [ + 301, + "58B023C5-98DF-40D0-83E0-F59455C54A22", + 301, + 1460084526, + "708543", + 1460084526, + "708543", + null, + "2016-04-07T00:00:00Z", + "02 11 32 50 54", + "02" + ], + [ + 302, + "EF0612D5-4C76-415B-B319-6AEC5556CF37", + 302, + 1460430128, + "708543", + 1460430128, + "708543", + null, + "2016-04-11T00:00:00Z", + "15 30 34 38 55", + "02" + ], + [ + 303, + "A97F5813-253E-4260-8574-D345AFC22F9D", + 303, + 1460689307, + "708543", + 1460689307, + "708543", + null, + "2016-04-14T00:00:00Z", + "24 25 48 55 56", + "02" + ], + [ + 304, + "3C793ED7-C910-471F-B618-B402368054AE", + 304, + 1461034930, + "708543", + 1461034930, + "708543", + null, + "2016-04-18T00:00:00Z", + "06 25 29 33 44", + "02" + ], + [ + 305, + "36F1E6A8-801D-4403-A665-5EEAB32626AB", + 305, + 1461294107, + "708543", + 1461294107, + "708543", + null, + "2016-04-21T00:00:00Z", + "06 12 20 40 53", + "04" + ], + [ + 306, + "EADE786A-269F-400F-8C33-89F4B0AD1942", + 306, + 1461639766, + "708543", + 1461639766, + "708543", + null, + "2016-04-25T00:00:00Z", + "02 18 27 52 57", + "04" + ], + [ + 307, + "AB171349-0D36-4C32-AA59-4FBBC152CAF8", + 307, + 1461898908, + "708543", + 1461898908, + "708543", + null, + "2016-04-28T00:00:00Z", + "04 14 22 47 58", + "03" + ], + [ + 308, + "CCF28D0A-BF2A-493D-AB70-A9FF0030A0D8", + 308, + 1462244607, + "708543", + 1462244607, + "708543", + null, + "2016-05-02T00:00:00Z", + "10 14 30 55 56", + "01" + ], + [ + 309, + "4B2467EE-76B5-4234-93AF-08DA874D2C97", + 309, + 1462503706, + "708543", + 1462503706, + "708543", + null, + "2016-05-05T00:00:00Z", + "17 18 30 43 49", + "04" + ], + [ + 310, + "D1703DB4-0C48-4EE1-9143-EE7D721F51E0", + 310, + 1462849327, + "708543", + 1462849327, + "708543", + null, + "2016-05-09T00:00:00Z", + "20 23 38 48 56", + "03" + ], + [ + 311, + "A92AB3F1-4B91-4DAD-9B0B-ED02022D66E2", + 311, + 1463108526, + "708543", + 1463108526, + "708543", + null, + "2016-05-12T00:00:00Z", + "04 13 15 16 32", + "04" + ], + [ + 312, + "50F030BF-4F12-4CB4-927F-5CAFDF89C31E", + 312, + 1463454165, + "708543", + 1463454165, + "708543", + null, + "2016-05-16T00:00:00Z", + "04 20 25 32 45", + "03" + ], + [ + 313, + "FA8A7822-FDF4-4388-8AF3-6E9D045D78B8", + 313, + 1463713286, + "708543", + 1463713286, + "708543", + null, + "2016-05-19T00:00:00Z", + "10 18 37 40 57", + "04" + ], + [ + 314, + "D6178B28-AE42-4CA4-9FF0-D9B878E98335", + 314, + 1464058906, + "708543", + 1464058906, + "708543", + null, + "2016-05-23T00:00:00Z", + "04 19 26 33 58", + "02" + ], + [ + 315, + "551DFBDF-EC8E-456D-A09D-5A9B8B42BD9D", + 315, + 1464318105, + "708543", + 1464318105, + "708543", + null, + "2016-05-26T00:00:00Z", + "04 13 26 34 43", + "03" + ], + [ + 316, + "B4E5CA65-8F5C-4A75-A68E-01CD98074B29", + 316, + 1464663786, + "708543", + 1464663786, + "708543", + null, + "2016-05-30T00:00:00Z", + "05 07 27 28 36", + "04" + ], + [ + 317, + "E7E2C9F9-A64E-43EB-B9C7-BD6D8E4962C4", + 317, + 1464922887, + "708543", + 1464922887, + "708543", + null, + "2016-06-02T00:00:00Z", + "18 28 30 31 37", + "02" + ], + [ + 318, + "C45FF1A8-7331-4DC6-9AB6-E4DE04A0B09C", + 318, + 1465268547, + "708543", + 1465268547, + "708543", + null, + "2016-06-06T00:00:00Z", + "18 25 35 41 57", + "02" + ], + [ + 319, + "58BB5146-A70B-41DE-AFCF-5E024D26B38F", + 319, + 1465527708, + "708543", + 1465527708, + "708543", + null, + "2016-06-09T00:00:00Z", + "01 04 12 33 41", + "02" + ], + [ + 320, + "68C6831F-536C-4009-BFB9-BC3A2B4AD625", + 320, + 1465873309, + "708543", + 1465873309, + "708543", + null, + "2016-06-13T00:00:00Z", + "35 40 51 55 60", + "01" + ], + [ + 321, + "5C1548EC-0215-4D3E-87AA-8D807B4E60FB", + 321, + 1466132506, + "708543", + 1466132506, + "708543", + null, + "2016-06-16T00:00:00Z", + "03 17 22 57 59", + "02" + ], + [ + 322, + "830DCC3A-6742-4948-89CC-82FBA203A36C", + 322, + 1466478145, + "708543", + 1466478145, + "708543", + null, + "2016-06-20T00:00:00Z", + "01 12 14 32 60", + "03" + ], + [ + 323, + "5DF63F07-C89F-486B-8B29-7772ABEF0A92", + 323, + 1466737307, + "708543", + 1466737307, + "708543", + null, + "2016-06-23T00:00:00Z", + "01 09 36 38 46", + "01" + ], + [ + 324, + "FC9292E2-8D42-4696-81F8-F5377A8C59D6", + 324, + 1467082985, + "708543", + 1467082985, + "708543", + null, + "2016-06-27T00:00:00Z", + "02 03 09 27 37", + "01" + ], + [ + 325, + "1954E04D-32A1-45E0-9ACF-B47404D258DF", + 325, + 1467342107, + "708543", + 1467342107, + "708543", + null, + "2016-06-30T00:00:00Z", + "04 09 10 31 34", + "03" + ], + [ + 326, + "7C56F803-F4B5-4DA0-8C97-9B7FA2ADC1F3", + 326, + 1467687725, + "708543", + 1467687725, + "708543", + null, + "2016-07-04T00:00:00Z", + "02 15 17 18 52", + "01" + ], + [ + 327, + "4294E688-3864-491C-86C9-CA646EC2C49C", + 327, + 1467947025, + "708543", + 1467947025, + "708543", + null, + "2016-07-07T00:00:00Z", + "04 08 26 41 55", + "03" + ], + [ + 328, + "066CD036-4708-429B-9B76-060E77753B4C", + 328, + 1468292515, + "708543", + 1468292515, + "708543", + null, + "2016-07-11T00:00:00Z", + "16 20 25 27 43", + "03" + ], + [ + 329, + "AAA3A2F3-5860-4F9F-94D1-C28D152A2621", + 329, + 1468551706, + "708543", + 1468551706, + "708543", + null, + "2016-07-14T00:00:00Z", + "03 08 11 24 25", + "02" + ], + [ + 330, + "FC5C2E01-2289-433A-88D1-50430851D90D", + 330, + 1468897350, + "708543", + 1468897350, + "708543", + null, + "2016-07-18T00:00:00Z", + "13 45 51 58 60", + "01" + ], + [ + 331, + "7521FBF4-81E2-4DED-ADDD-74F693D0031D", + 331, + 1469156485, + "708543", + 1469156485, + "708543", + null, + "2016-07-21T00:00:00Z", + "01 04 18 29 32", + "01" + ], + [ + 332, + "7153C695-63D1-49A3-91D2-082D09171CC0", + 332, + 1469502126, + "708543", + 1469502126, + "708543", + null, + "2016-07-25T00:00:00Z", + "11 12 23 26 43", + "02" + ], + [ + 333, + "27681D0A-040F-4D9A-A119-13C4392622CF", + 333, + 1469761306, + "708543", + 1469761306, + "708543", + null, + "2016-07-28T00:00:00Z", + "13 19 32 36 41", + "02" + ], + [ + 334, + "75246569-4982-4E24-81AA-45F9A9803C8D", + 334, + 1470106886, + "708543", + 1470106886, + "708543", + null, + "2016-08-01T00:00:00Z", + "32 34 36 39 46", + "01" + ], + [ + 335, + "1382260F-0898-4945-AB2E-8DC51E11593A", + 335, + 1470366105, + "708543", + 1470366105, + "708543", + null, + "2016-08-04T00:00:00Z", + "08 22 41 54 56", + "01" + ], + [ + 336, + "3ADD1C00-4497-450C-ADDD-300DA05C1BE8", + 336, + 1470711725, + "708543", + 1470711725, + "708543", + null, + "2016-08-08T00:00:00Z", + "04 07 08 12 23", + "01" + ], + [ + 337, + "8AEC193F-651F-4C61-8F91-792211203FB9", + 337, + 1470970905, + "708543", + 1470970905, + "708543", + null, + "2016-08-11T00:00:00Z", + "03 34 44 53 55", + "04" + ], + [ + 338, + "BFCE5235-8BFE-4DDB-B133-92787B11E6F1", + 338, + 1471316525, + "708543", + 1471316525, + "708543", + null, + "2016-08-15T00:00:00Z", + "13 40 48 50 57", + "04" + ], + [ + 339, + "E69693B0-5EE1-4E00-80F8-5E3826BDF3C2", + 339, + 1471575706, + "708543", + 1471575706, + "708543", + null, + "2016-08-18T00:00:00Z", + "07 24 25 56 58", + "03" + ], + [ + 340, + "866871A3-7952-4D0F-A557-86147F0FFABB", + 340, + 1472076169, + "708543", + 1472076169, + "708543", + null, + "2016-08-22T00:00:00Z", + "08 12 22 56 58", + "01" + ], + [ + 341, + "542C6698-71F5-4698-84EC-06F2660FD6F8", + 341, + 1472205665, + "708543", + 1472205665, + "708543", + null, + "2016-08-25T00:00:00Z", + "10 17 24 47 59", + "02" + ], + [ + 342, + "C51D55B6-5946-456C-A55F-D0AB8A2D4A21", + 342, + 1472551269, + "708543", + 1472551269, + "708543", + null, + "2016-08-29T00:00:00Z", + "05 21 25 31 55", + "04" + ], + [ + 343, + "B6A9851F-B803-47E0-8049-8C2D87476A7F", + 343, + 1472810465, + "708543", + 1472810465, + "708543", + null, + "2016-09-01T00:00:00Z", + "17 45 46 51 53", + "02" + ], + [ + 344, + "1AE0AF41-51F0-48B3-8843-EBEE145E8325", + 344, + 1473268891, + "708543", + 1473268891, + "708543", + null, + "2016-09-05T00:00:00Z", + "16 19 40 41 43", + "03" + ], + [ + 345, + "21F27DE2-45CC-4D6B-9FD0-1D8CA8A20024", + 345, + 1473445246, + "708543", + 1473445246, + "708543", + null, + "2016-09-08T00:00:00Z", + "03 07 22 37 60", + "02" + ], + [ + 346, + "9E61A94F-8971-4347-8E38-3505413BF359", + 346, + 1473760864, + "708543", + 1473760864, + "708543", + null, + "2016-09-12T00:00:00Z", + "01 32 39 55 58", + "02" + ], + [ + 347, + "B18D0A66-3AC8-43B6-8E40-BD28B95874E9", + 347, + 1474020065, + "708543", + 1474020065, + "708543", + null, + "2016-09-15T00:00:00Z", + "11 20 54 59 60", + "02" + ], + [ + 348, + "FF974006-3F5C-452D-8067-DB663B1E4070", + 348, + 1474365664, + "708543", + 1474365664, + "708543", + null, + "2016-09-19T00:00:00Z", + "19 40 49 54 56", + "04" + ], + [ + 349, + "3A072E03-BC85-4F81-8ED9-436ED49F4DFA", + 349, + 1474624871, + "708543", + 1474624871, + "708543", + null, + "2016-09-22T00:00:00Z", + "01 03 24 42 59", + "01" + ], + [ + 350, + "1C880DFC-09D3-4108-9038-721786886E91", + 350, + 1474970463, + "708543", + 1474970463, + "708543", + null, + "2016-09-26T00:00:00Z", + "36 44 50 54 60", + "04" + ], + [ + 351, + "3A5F2AF8-1578-4EA2-93BD-D1AE9BB6605F", + 351, + 1475229663, + "708543", + 1475229663, + "708543", + null, + "2016-09-29T00:00:00Z", + "13 25 39 51 55", + "03" + ], + [ + 352, + "2BC4E88D-7706-40B9-A71D-DCA1F37EED76", + 352, + 1475575263, + "708543", + 1475575263, + "708543", + null, + "2016-10-03T00:00:00Z", + "05 48 49 52 58", + "02" + ], + [ + 353, + "5B7DD3A9-D218-4210-AA73-BCBEAFD8A807", + 353, + 1475834463, + "708543", + 1475834463, + "708543", + null, + "2016-10-06T00:00:00Z", + "05 07 09 12 43", + "02" + ], + [ + 354, + "9203C4C9-9D90-47D5-8CEB-A1B92BBB6648", + 354, + 1476180084, + "708543", + 1476180084, + "708543", + null, + "2016-10-10T00:00:00Z", + "11 35 38 45 58", + "01" + ], + [ + 355, + "BF36F047-2FBA-452E-911A-756F1D1BFE6A", + 355, + 1476439263, + "708543", + 1476439263, + "708543", + null, + "2016-10-13T00:00:00Z", + "03 19 21 26 43", + "03" + ], + [ + 356, + "0E587093-37FA-40EE-AF54-B0BA90D3C41C", + 356, + 1476784863, + "708543", + 1476784863, + "708543", + null, + "2016-10-17T00:00:00Z", + "04 16 35 37 55", + "04" + ], + [ + 357, + "E64FCA93-AD90-4C08-96F6-F5D3893F4864", + 357, + 1477044065, + "708543", + 1477044065, + "708543", + null, + "2016-10-20T00:00:00Z", + "06 38 40 48 57", + "02" + ], + [ + 358, + "207063E0-B35C-47A9-B86A-29C9303F8C99", + 358, + 1477411657, + "708543", + 1477411657, + "708543", + null, + "2016-10-24T00:00:00Z", + "01 02 20 40 55", + "04" + ], + [ + 359, + "12F517F0-6AB0-49AF-B3FD-60551DB5E71C", + 359, + 1477648862, + "708543", + 1477648862, + "708543", + null, + "2016-10-27T00:00:00Z", + "15 16 19 37 40", + "04" + ], + [ + 360, + "BDFDD6D9-6C78-4ADD-9D8C-1BC306BF9D47", + 360, + 1477994484, + "708543", + 1477994484, + "708543", + null, + "2016-10-31T00:00:00Z", + "17 25 38 41 58", + "03" + ], + [ + 361, + "0F8581C9-2308-4CF3-85AF-58997BAA6195", + 361, + 1478253663, + "708543", + 1478253663, + "708543", + null, + "2016-11-03T00:00:00Z", + "05 10 29 37 59", + "04" + ], + [ + 362, + "B1A0DE7D-8653-4174-8165-6178E15DE970", + 362, + 1478602863, + "708543", + 1478602863, + "708543", + null, + "2016-11-07T00:00:00Z", + "09 11 20 37 60", + "02" + ], + [ + 363, + "1881FB59-CACC-4DE1-811E-470ACEB648AA", + 363, + 1478862062, + "708543", + 1478862062, + "708543", + null, + "2016-11-10T00:00:00Z", + "06 07 17 20 44", + "02" + ], + [ + 364, + "EA961E65-99E4-4534-8AD0-927FD4B33152", + 364, + 1479207685, + "708543", + 1479207685, + "708543", + null, + "2016-11-14T00:00:00Z", + "03 10 20 30 43", + "01" + ], + [ + 365, + "444F25A6-0B87-4BFC-81F0-48169EB912CB", + 365, + 1479466863, + "708543", + 1479466863, + "708543", + null, + "2016-11-17T00:00:00Z", + "06 30 32 35 48", + "01" + ], + [ + 366, + "A1B19B86-0101-422D-ACA5-6E0F257F9936", + 366, + 1479812595, + "708543", + 1479812595, + "708543", + null, + "2016-11-21T00:00:00Z", + "08 11 37 41 54", + "04" + ], + [ + 367, + "F3666FC9-4209-46DC-A083-AAB50F49AE32", + 367, + 1480071815, + "708543", + 1480071815, + "708543", + null, + "2016-11-24T00:00:00Z", + "04 24 25 32 46", + "01" + ], + [ + 368, + "4610C832-DE20-48B3-BC5C-4C599067F3DB", + 368, + 1480417262, + "708543", + 1480417262, + "708543", + null, + "2016-11-28T00:00:00Z", + "22 32 42 45 49", + "04" + ], + [ + 369, + "1559BB20-317A-4092-8966-788A8265EEA5", + 369, + 1480676463, + "708543", + 1480676463, + "708543", + null, + "2016-12-01T00:00:00Z", + "17 23 30 49 55", + "01" + ], + [ + 370, + "3B1D2CEB-0135-4AE2-A220-76D269851B3B", + 370, + 1481022063, + "708543", + 1481022063, + "708543", + null, + "2016-12-05T00:00:00Z", + "05 06 19 22 45", + "04" + ], + [ + 371, + "A04FCBEE-20D1-43E9-8B8B-3367AED3A724", + 371, + 1481281263, + "708543", + 1481281263, + "708543", + null, + "2016-12-08T00:00:00Z", + "08 28 29 49 57", + "03" + ], + [ + 372, + "34543D5E-6964-494C-B91E-E4CDF4DC14A3", + 372, + 1481626862, + "708543", + 1481626862, + "708543", + null, + "2016-12-12T00:00:00Z", + "14 19 48 53 54", + "04" + ], + [ + 373, + "A1020F9A-D7C6-4CC3-AC05-AAA2D238DD55", + 373, + 1481886064, + "708543", + 1481886064, + "708543", + null, + "2016-12-15T00:00:00Z", + "05 07 21 44 57", + "02" + ], + [ + 374, + "BDF2DA85-5CEB-48CC-B9E3-E2FBCEB23C2B", + 374, + 1482231662, + "708543", + 1482231662, + "708543", + null, + "2016-12-19T00:00:00Z", + "01 08 16 22 47", + "03" + ], + [ + 375, + "FA3C3D28-FD22-4EC5-8336-7C846CAD2443", + 375, + 1482577419, + "708543", + 1482577419, + "708543", + null, + "2016-12-22T00:00:00Z", + "14 19 32 38 43", + "03" + ], + [ + 376, + "4C35A52C-6907-43EC-86FF-4B4BEC6A5E49", + 376, + 1482836463, + "708543", + 1482836463, + "708543", + null, + "2016-12-26T00:00:00Z", + "04 12 29 31 36", + "01" + ], + [ + 377, + "C6F39639-73F6-4154-BD6E-B132ED1105E8", + 377, + 1483095662, + "708543", + 1483095662, + "708543", + null, + "2016-12-29T00:00:00Z", + "11 16 19 29 34", + "01" + ], + [ + 378, + "7AF97546-0AD7-40C7-BFE0-40A1E0BB1B33", + 378, + 1483441353, + "708543", + 1483441353, + "708543", + null, + "2017-01-02T00:00:00Z", + "26 31 37 38 41", + "02" + ], + [ + 379, + "E983310B-B8AF-4A58-858F-0E9304EA8249", + 379, + 1483700569, + "708543", + 1483700569, + "708543", + null, + "2017-01-05T00:00:00Z", + "05 18 42 44 46", + "04" + ], + [ + 380, + "103D6B62-39BE-4EA4-B534-08BB03C150C8", + 380, + 1484046133, + "708543", + 1484046133, + "708543", + null, + "2017-01-09T00:00:00Z", + "21 28 31 44 51", + "01" + ], + [ + 381, + "7CD6CAB4-8153-4BB3-A27B-A542AB245036", + 381, + 1484305263, + "708543", + 1484305263, + "708543", + null, + "2017-01-12T00:00:00Z", + "06 32 37 50 56", + "01" + ], + [ + 382, + "0BA4693E-BAB9-474B-AF77-E1167BC331B6", + 382, + 1484650863, + "708543", + 1484650863, + "708543", + null, + "2017-01-16T00:00:00Z", + "03 15 16 19 26", + "01" + ], + [ + 383, + "F8E9EA6C-E90D-4747-9B9E-ABED48B51012", + 383, + 1484910064, + "708543", + 1484910064, + "708543", + null, + "2017-01-19T00:00:00Z", + "14 32 37 43 45", + "02" + ], + [ + 384, + "933403B9-374D-4F52-9016-A366170C7B80", + 384, + 1485255703, + "708543", + 1485255703, + "708543", + null, + "2017-01-23T00:00:00Z", + "16 24 32 44 48", + "01" + ], + [ + 385, + "1911AB83-55BF-41DA-9435-80647451B102", + 385, + 1485514863, + "708543", + 1485514863, + "708543", + null, + "2017-01-26T00:00:00Z", + "01 14 25 40 59", + "02" + ], + [ + 386, + "C9A55462-3885-4282-B2F9-D81DF650BB2A", + 386, + 1485860463, + "708543", + 1485860463, + "708543", + null, + "2017-01-30T00:00:00Z", + "11 20 31 34 51", + "03" + ], + [ + 387, + "0EBCE21B-9B55-455B-B50B-2C59071D79EB", + 387, + 1486119661, + "708543", + 1486119661, + "708543", + null, + "2017-02-02T00:00:00Z", + "13 20 24 37 58", + "02" + ], + [ + 388, + "EB111070-EDC8-4551-9340-2591ECD7C2C8", + 388, + 1486465263, + "708543", + 1486465263, + "708543", + null, + "2017-02-06T00:00:00Z", + "06 24 48 54 59", + "02" + ], + [ + 389, + "1AD26A0B-D5BA-4645-ACCF-F46113F2338C", + 389, + 1486724463, + "708543", + 1486724463, + "708543", + null, + "2017-02-09T00:00:00Z", + "02 28 37 38 48", + "04" + ], + [ + 390, + "5F8E008F-6819-4537-A227-B1B6E17F91B5", + 390, + 1487070063, + "708543", + 1487070063, + "708543", + null, + "2017-02-13T00:00:00Z", + "17 18 24 25 41", + "01" + ], + [ + 391, + "835E6675-3ED7-4366-A2C9-CBA14A2E2D21", + 391, + 1487329283, + "708543", + 1487329283, + "708543", + null, + "2017-02-16T00:00:00Z", + "08 12 19 35 42", + "04" + ], + [ + 392, + "92ACF91E-7E18-4474-B9CE-1FF4A6CA254C", + 392, + 1487674863, + "708543", + 1487674863, + "708543", + null, + "2017-02-20T00:00:00Z", + "13 16 23 37 48", + "03" + ], + [ + 393, + "8F0AA716-50CD-4F3A-8C03-A30502C50F12", + 393, + 1487934063, + "708543", + 1487934063, + "708543", + null, + "2017-02-23T00:00:00Z", + "03 24 38 43 52", + "03" + ], + [ + 394, + "FC265525-1D9E-4446-8D16-2E7B274FEE39", + 394, + 1488279663, + "708543", + 1488279663, + "708543", + null, + "2017-02-27T00:00:00Z", + "06 19 28 57 60", + "01" + ], + [ + 395, + "C83F7BA9-4D51-4162-BB6B-0D18AAA63D7A", + 395, + 1488538863, + "708543", + 1488538863, + "708543", + null, + "2017-03-02T00:00:00Z", + "03 07 11 30 42", + "03" + ], + [ + 396, + "48273180-B95E-4577-A184-BC322612FD77", + 396, + 1488884464, + "708543", + 1488884464, + "708543", + null, + "2017-03-06T00:00:00Z", + "01 05 14 22 50", + "02" + ], + [ + 397, + "E6EDD74A-BFA0-43ED-A0A8-89F9F297CBC8", + 397, + 1489143662, + "708543", + 1489143662, + "708543", + null, + "2017-03-09T00:00:00Z", + "01 08 23 56 58", + "03" + ], + [ + 398, + "638B5ABD-5A49-4D49-8E65-0C80CD12C359", + 398, + 1489485665, + "708543", + 1489485665, + "708543", + null, + "2017-03-13T00:00:00Z", + "13 16 17 24 50", + "02" + ], + [ + 399, + "CE4D7DBB-FA7E-4A9E-B690-69ACF26681C2", + 399, + 1489744863, + "708543", + 1489744863, + "708543", + null, + "2017-03-16T00:00:00Z", + "13 14 36 48 57", + "02" + ], + [ + 400, + "A79B333A-4D79-46AB-876A-ED37FDA22179", + 400, + 1490090463, + "708543", + 1490090463, + "708543", + null, + "2017-03-20T00:00:00Z", + "13 22 41 46 56", + "02" + ], + [ + 401, + "7E5D329D-8BA7-4F19-A9C4-B0C54C20470B", + 401, + 1490349662, + "708543", + 1490349662, + "708543", + null, + "2017-03-23T00:00:00Z", + "02 28 30 39 53", + "04" + ], + [ + 402, + "1985AC19-100B-4AB7-9576-B6B8227EE8C2", + 402, + 1490695263, + "708543", + 1490695263, + "708543", + null, + "2017-03-27T00:00:00Z", + "32 42 58 59 60", + "04" + ], + [ + 403, + "B253914E-565E-4CDA-A8F7-739D870195D6", + 403, + 1490954462, + "708543", + 1490954462, + "708543", + null, + "2017-03-30T00:00:00Z", + "24 38 40 44 49", + "02" + ], + [ + 404, + "6C4EA2A4-B16E-4933-94E4-CC03D67C41F5", + 404, + 1491300064, + "708543", + 1491300064, + "708543", + null, + "2017-04-03T00:00:00Z", + "12 15 28 46 57", + "02" + ], + [ + 405, + "0ABBB5BF-08B3-4106-8C0B-A7E4D3FFAB85", + 405, + 1491559263, + "708543", + 1491559263, + "708543", + null, + "2017-04-06T00:00:00Z", + "04 06 17 48 53", + "04" + ], + [ + 406, + "13B8CAA5-E796-4524-BEE5-74C3B4CE0262", + 406, + 1491904864, + "708543", + 1491904864, + "708543", + null, + "2017-04-10T00:00:00Z", + "20 22 37 55 56", + "03" + ], + [ + 407, + "7BCBE538-0B50-436D-9590-53E8C5D90F37", + 407, + 1492164063, + "708543", + 1492164063, + "708543", + null, + "2017-04-13T00:00:00Z", + "17 19 49 50 56", + "04" + ], + [ + 408, + "5958B7B7-B596-4599-9AFC-3605927278C3", + 408, + 1492509663, + "708543", + 1492509663, + "708543", + null, + "2017-04-17T00:00:00Z", + "05 09 12 33 46", + "04" + ], + [ + 409, + "38574FCC-C191-429E-BA01-6945C49FDA31", + 409, + 1492768863, + "708543", + 1492768863, + "708543", + null, + "2017-04-20T00:00:00Z", + "22 23 37 56 60", + "04" + ], + [ + 410, + "88377B77-8DFB-4B28-8D7C-778AE0574761", + 410, + 1493114484, + "708543", + 1493114484, + "708543", + null, + "2017-04-24T00:00:00Z", + "19 33 35 36 48", + "02" + ], + [ + 411, + "7B77E69F-1E58-4F9E-928F-31136AB6E344", + 411, + 1493373665, + "708543", + 1493373665, + "708543", + null, + "2017-04-27T00:00:00Z", + "02 20 27 29 53", + "04" + ], + [ + 412, + "D1439024-FE00-4907-BB75-A017CAE2298B", + 412, + 1493762464, + "708543", + 1493762464, + "708543", + null, + "2017-05-01T00:00:00Z", + "07 19 23 24 40", + "02" + ], + [ + 413, + "14FA8C72-6190-46D3-B86D-6B04643CC1F9", + 413, + 1493978463, + "708543", + 1493978463, + "708543", + null, + "2017-05-04T00:00:00Z", + "01 02 17 24 38", + "04" + ], + [ + 414, + "45E0D1A0-D009-4F72-8A54-2164799E0405", + 414, + 1494324065, + "708543", + 1494324065, + "708543", + null, + "2017-05-08T00:00:00Z", + "22 34 42 46 57", + "03" + ], + [ + 415, + "877064A5-1C75-4A14-8504-678698EA5CE5", + 415, + 1494583263, + "708543", + 1494583263, + "708543", + null, + "2017-05-11T00:00:00Z", + "06 20 30 34 36", + "01" + ], + [ + 416, + "9F38DE70-E408-4705-BD7F-BBB6E66DA750", + 416, + 1494928884, + "708543", + 1494928884, + "708543", + null, + "2017-05-15T00:00:00Z", + "02 27 28 34 39", + "03" + ], + [ + 417, + "E1E94E70-16BB-4D44-878A-D98B8B080DFD", + 417, + 1495188064, + "708543", + 1495188064, + "708543", + null, + "2017-05-18T00:00:00Z", + "04 29 30 55 58", + "03" + ], + [ + 418, + "96667C9D-2FF0-450B-905F-21D1F7EDB7CD", + 418, + 1495533664, + "708543", + 1495533664, + "708543", + null, + "2017-05-22T00:00:00Z", + "04 06 25 31 47", + "01" + ], + [ + 419, + "AF4400B9-8891-4605-9F13-51937F17B03B", + 419, + 1495792863, + "708543", + 1495792863, + "708543", + null, + "2017-05-25T00:00:00Z", + "06 07 13 16 30", + "01" + ], + [ + 420, + "048E1CAE-2335-44CB-9A83-5182E1340DB7", + 420, + 1496138464, + "708543", + 1496138464, + "708543", + null, + "2017-05-29T00:00:00Z", + "18 22 23 25 49", + "04" + ], + [ + 421, + "1DB24704-5C12-4A46-8E68-CD1DD147BDEC", + 421, + 1496397665, + "708543", + 1496397665, + "708543", + null, + "2017-06-01T00:00:00Z", + "05 09 46 55 58", + "04" + ], + [ + 422, + "FEE6742F-1091-4CD5-B512-702D5A4EC2B0", + 422, + 1496743263, + "708543", + 1496743263, + "708543", + null, + "2017-06-05T00:00:00Z", + "03 29 32 48 56", + "01" + ], + [ + 423, + "0A4E5275-85AB-47AF-BC6B-E0F20AFB16C2", + 423, + 1497002463, + "708543", + 1497002463, + "708543", + null, + "2017-06-08T00:00:00Z", + "24 27 43 50 60", + "03" + ], + [ + 424, + "303C188D-FDBB-45DD-85AC-05713746DB00", + 424, + 1497348063, + "708543", + 1497348063, + "708543", + null, + "2017-06-12T00:00:00Z", + "10 11 44 53 57", + "03" + ], + [ + 425, + "D5521A42-7B8E-4543-A679-7E8B30420AD2", + 425, + 1497607263, + "708543", + 1497607263, + "708543", + null, + "2017-06-15T00:00:00Z", + "01 09 17 26 55", + "01" + ], + [ + 426, + "6B9C238D-2DAD-4893-A400-41EE87FAA507", + 426, + 1497952863, + "708543", + 1497952863, + "708543", + null, + "2017-06-19T00:00:00Z", + "02 10 15 33 58", + "04" + ], + [ + 427, + "2F1D8176-05CC-42FD-9948-2DF7D2D17789", + 427, + 1498212065, + "708543", + 1498212065, + "708543", + null, + "2017-06-22T00:00:00Z", + "31 40 45 54 57", + "03" + ], + [ + 428, + "9BD5890A-DDD6-4F6B-BCB0-E8958FE6A64E", + 428, + 1498557663, + "708543", + 1498557663, + "708543", + null, + "2017-06-26T00:00:00Z", + "08 33 39 40 49", + "02" + ], + [ + 429, + "7A097BCB-1AE8-4F43-A54C-74F145E6EC89", + 429, + 1498816862, + "708543", + 1498816862, + "708543", + null, + "2017-06-29T00:00:00Z", + "07 08 13 18 48", + "02" + ], + [ + 430, + "1378F87D-4AE2-4A2E-9C6F-B16E64B6F6AE", + 430, + 1499162463, + "708543", + 1499162463, + "708543", + null, + "2017-07-03T00:00:00Z", + "04 28 40 41 48", + "03" + ], + [ + 431, + "DC076E67-B307-40C0-8542-B2137A9AE611", + 431, + 1499421663, + "708543", + 1499421663, + "708543", + null, + "2017-07-06T00:00:00Z", + "04 09 39 44 52", + "02" + ], + [ + 432, + "3E109B20-AE12-42CB-9DB9-2915BDB33484", + 432, + 1499767263, + "708543", + 1499767263, + "708543", + null, + "2017-07-10T00:00:00Z", + "13 19 34 38 53", + "01" + ], + [ + 433, + "D583AB29-686F-4C7C-A419-44BC8EDFF09C", + 433, + 1500026463, + "708543", + 1500026463, + "708543", + null, + "2017-07-13T00:00:00Z", + "06 17 32 45 59", + "03" + ], + [ + 434, + "8D36A3EA-081C-43D6-BE99-5444EC524B8D", + 434, + 1500372063, + "708543", + 1500372063, + "708543", + null, + "2017-07-17T00:00:00Z", + "08 17 27 28 39", + "02" + ], + [ + 435, + "5E8FA7B1-1811-4AD8-B38D-45AC8BD6892E", + 435, + 1500631263, + "708543", + 1500631263, + "708543", + null, + "2017-07-20T00:00:00Z", + "26 37 40 42 50", + "01" + ], + [ + 436, + "2DE0CC06-BC82-40F7-9EC1-7D994914295F", + 436, + 1500976822, + "708543", + 1500976822, + "708543", + null, + "2017-07-24T00:00:00Z", + "07 20 21 41 59", + "01" + ], + [ + 437, + "63D9B819-449D-4674-B015-B6C0DFE74DB2", + 437, + 1501236065, + "708543", + 1501236065, + "708543", + null, + "2017-07-27T00:00:00Z", + "32 37 38 42 43", + "02" + ] + ] +} diff --git a/test/inputs/json/misc/734ad.json b/test/inputs/json/misc/734ad.json index abd9e98c0..656757a51 100644 --- a/test/inputs/json/misc/734ad.json +++ b/test/inputs/json/misc/734ad.json @@ -1 +1,2642 @@ -{"count": 12129, "facets": {}, "results": [{"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-04-21T00:36:51.167919", "entity": "f68eebed3ca14d66aeb9be6e5680cdcd", "number_of_natural_persons": null, "legal": "8e8b73cc70d241e5bb32c8907cd042ba", "native_name": null, "head_office_country": "Denmark", "id": "fffebd3272294bb0a38d0347b0e0c4df", "activity_industry_forums": "None", "contact_country": 59, "head_office_postbox": null, "networking": "The European Federation of Building and Woodworkers (EFBWW) is the European Industry Federation for the construction industry, the building materials industry, the wood and furniture industry and the forestry industry. The EFBWW has 76 affiliated unions in 34 countries and represents a total of 2,000,000 members, see\r\nhttp://www.efbww.org/default.asp?Language=EN", "members_75": null, "main_category": 2, "members_50": 4, "activity_expert_groups": "None", "sub_category_title": "Trade unions and professional associations", "other_code_of_conduct": null, "head_office_town": "K\u00f8benhavn V", "info_members": "", "head": "8e8b73cc70d241e5bb32c8907cd042ba", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Kampmannsgade 4, 70300300 ", "activity_inter_groups": "None", "acronym": "BAT", "activity_eu_legislative": "Policies in the fields of the construction industry, employment and labour market, posting of workers, migrant workers, energy savings, works councils, occupational health and safety", "registration_date": "2012-09-19T14:07:17.947000", "activity_relevant_comm": "None", "head_office_post_code": "1790", "goals": "BAT coordinates and represents the member organisations' (3F, Blik & R\u00f8rarbejderforbundet, El-forbundet, HK/Privat, Malerforbundet, Dansk Metal og Teknisk Landsforbund) interests on working environment, co-determination, AS, Works Councils and EWC, industrial policy, housing policy and labour market polity , international work, posted workers, foreign companies and Greenland.", "members": 4, "last_update_date": "2016-04-12T08:34:24.029000", "members_fte": 2.0, "head_office_phone": "45 70300300", "members_25": null, "web_site_url": "http://www.batkartellet.dk", "sub_category": 26, "activity_other": "BAT coordinates the member organisations' interest on an european level through compilation and dialogue with the decision-makers. Further, BAT is the proponent for the Danish collective agreement model.", "name": "Bygge-, Anl\u00e6gs- og Tr\u00e6kartellet", "created_at": "2015-04-24T02:06:02.588289", "uri": "http://api.lobbyfacts.eu/api/1/representative/fffebd3272294bb0a38d0347b0e0c4df", "identification_code": "18539199654-93", "legal_status": "Faglig organisation (association; trade union federation)", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 45.5893459, "updated_at": "2016-02-17T01:42:44.613826", "entity": "c476460f5e8243a8b16b75ae1cfafa41", "number_of_natural_persons": 390, "legal": "e9918b3c28ed4f1197e97c17a59e4703", "native_name": null, "head_office_country": "Italy", "id": "ffdb86d0032b4bdf8682ff4cc908bf48", "activity_industry_forums": "None", "contact_country": 108, "head_office_postbox": null, "networking": "* wikimedia.org\r\n* https://meta.wikimedia.org/wiki/Wikimedia_chapters\r\n* https://meta.wikimedia.org/wiki/EU_policy\r\n* frontieredigitali.it\r\n* beniculturaliaperti.it", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Monza (MB)", "info_members": "Only volunteer work, mostly by members Federico Leva and Lorenzo Losa.\r\n\r\nWe also contribute a small share of the costs for the Free Knowledge Advocacy Group EU representative in Brussels.", "head": "e9918b3c28ed4f1197e97c17a59e4703", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "via Bergamo, 18 ", "activity_inter_groups": "None", "acronym": "WMI", "activity_eu_legislative": "Net neutrality, InfoSoc directive; anything related to public domain, copyright, free knowledge, free/libre open source software, open data, cultural heritage, digital divide, wikis, collaboration and sharing on the internet.", "registration_date": "2014-01-27T13:07:45.787000", "activity_relevant_comm": "http://wiki.wikimedia.it/wiki/Consultazione_europea_sul_diritto_d%27autore", "head_office_post_code": "20900", "goals": "Wikimedia Italia persegue esclusivamente finalit\u00e0 di solidariet\u00e0 sociale nel campo della promozione della cultura. L'Associazione ha per obiettivo di contribuire attivamente a diffusione, miglioramento e avanzamento del sapere e della cultura promuovendo la produzione, raccolta e diffusione gratuita di contenuti liberi (Open Content) per incentivare le possibilit\u00e0 di accesso alla conoscenza e alla formazione. Sono definiti \"contenuti liberi\" nel senso inteso dall'associazione tutte le opere che sono state contrassegnate dai loro autori con una licenza che ne permetta l'elaborazione e/o la diffusione gratuita. In aggiunta a ci\u00f2 sar\u00e0 approfondita anche la conoscenza e la consapevolezza delle questioni sociali e filosofiche correlate.\r\n\r\nIn particolare Wikimedia Italia si d\u00e0 come obiettivo di promuovere e sostenere, direttamente o indirettamente, gli sviluppi, i trasferimenti, le traduzioni in lingua italiana dei progetti della Wikimedia Foundation, Inc.\r\n\r\nAnche se Wikimedia Italia \u00e8 soggetta alla legge italiana, i suoi obiettivi includono il sostegno ai progetti di Wikimedia Foundation, Inc. nel suo complesso e non solamente a quelli in lingua italiana. Wikimedia Italia non ha interesse a intervenire nella gestione dei siti di Wikimedia Foundation, Inc.\r\n\r\n----\r\n\r\n\"Wikimedia italiana\" has no profit purpose. It intends to operate in the field of the culture and knowledge. In order to actively contribute to the diffusion, the improvement and the progress of the knowledge and culture in the world, Wikimedia italiana aims at supporting the development of encyclopedias, quote collections, educational books and collections of other documents, information and electronic databases having the following characteristics:\r\n\r\n they are completely free\r\n they are available on-line through the internet technologies and their derivatives\r\n they have a content editable by the user\r\n they have a free content, that can be distributed freely under the conditions of licenses like the GNU Free Documentation License, issued by the Free Software Association Inc., and particularly by its European branch on the site http://www.fsfeurope.org/.\r\n\r\nParticularly, Wikimedia italiana intends to promote and support, directly and indirectly, the developments, the transfers, the translations in Italian language of the projects of the Wikimedia Foundation, Inc.\r\n\r\nEven though Wikimedia italiana is subject to the Italian laws, its purposes include the support to the projects of the Association on the whole, and not only to the ones in Italian language. The usage of the Italian language is functional to the work of the association but it does not mean a definition of the association purposes on a national basis.", "members": 1, "last_update_date": "2016-02-16T16:19:57.030000", "members_fte": 0.25, "head_office_phone": "39 0395962256", "members_25": 1, "web_site_url": "http://wikimedia.it/", "sub_category": 31, "activity_other": "* Joined the https://meta.wikimedia.org/wiki/EU_policy/Statement_of_Intent\r\n* Helped draft https://meta.wikimedia.org/wiki/European_Commission_copyright_consultation\r\n* Submitted http://wiki.wikimedia.it/wiki/Consultazione_europea_sul_diritto_d%27autore and partecipating in InfoSoc directive review debate.\r\n* Joined Italian activities by multiple organisations, like beniculturaliaperti.it and fotoliberebbcc.wordpress.com, aimed at free culture promotion in Italy, also with an EU-level scope.", "name": "Associazione Wikimedia Italia", "created_at": "2015-04-24T02:33:36.659656", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffdb86d0032b4bdf8682ff4cc908bf48", "identification_code": "070762412733-39", "legal_status": "Associazione di promozione sociale", "members_100": null, "head_office_lon": 9.289427, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-06-28T02:12:35.246192", "entity": "2c67100610be42cd8f3573a08c677329", "number_of_natural_persons": null, "legal": "4cb1b6f7ae6944c1afc30fb37e0cb5e6", "native_name": null, "head_office_country": "Switzerland", "id": "ffc66947e9214c91ad50ca1f21879084", "activity_industry_forums": "None", "contact_country": 215, "head_office_postbox": null, "networking": "Advanced Medical Technology Association (AdvaMed) - advamed.org; European Society for Radiotherapy and Oncology (ESTRO) - estro.org; European Coordination Committee of the Radiological Electromedical and Healthcare IT Industry (COCIR) - cocir.org; Global Diagnostic Imaging, Healthcare IT and Radiation Therapy Trade Association (DITTA) - globalditta.org; Union for International Cancer Control (UICC) - uicc.org", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Cham", "info_members": "All Varian employees involved in activities described under heading 9 are based in Cham, Switzerland. Varian does maintain a small office in Belgium, but this office and all of its employees are entirely excluded from any activities described under heading 9, and is thus not applicable for the purpose of this registration.", "head": "b6b2bc34195647919988bdc66a928041", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Varian Medical Systems International AG Hinterbergstrasse 14 Hinterbergstrasse 14", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "Varian Medical Systems primarily follows EU initiatives, policies and legislative files relating to public health and/or research and innovation (e.g., Horizon 2020).", "registration_date": "2016-06-27T17:53:26.204000", "activity_relevant_comm": "Horizon 2020; Europe 2020 Strategy", "head_office_post_code": "6330", "goals": "Varian's mission is to focus energy on saving lives. Varian pioneered the use of high-energy X-rays for cancer treatments and developed the first linear accelerators to deliver radiotherapy. Today, Varian is the world's leading supplier of radiotherapy treatment solutions, continually improving delivery systems and advancing the field with new technologies, such as radiosurgery and proton therapy.", "members": 2, "last_update_date": "2016-06-27T17:53:56.186000", "members_fte": 0.5, "head_office_phone": "41 417498844", "members_25": 2, "web_site_url": "http://varian.com", "sub_category": 21, "activity_other": "Varian Medical Systems is currently a member of the Innovative Medicines Initiative 2 (IMI2).", "name": "Varian Medical Systems International AG", "created_at": "2016-06-28T02:12:35.253532", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffc66947e9214c91ad50ca1f21879084", "identification_code": "185216022477-29", "legal_status": "public limited company", "members_100": null, "head_office_lon": null, "structure_members": "N/A", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-05-18T01:55:12.188289", "entity": "58e648b6c5f84e7385d918a130930e8e", "number_of_natural_persons": null, "legal": "3919868fa8014565a1d1c5a3a805178b", "native_name": null, "head_office_country": "United Kingdom", "id": "ffc559aded2d4379915fe024267d5399", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": "ECCO\r\nESSO\r\nESO\r\nECPC\r\nESMO\r\nEPF\r\nUEG\r\nESDO", "members_75": 1, "main_category": 3, "members_50": 3, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Salisbury", "info_members": "", "head": "a7b6d02d614b4e98a40e35a9246facd4", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "5 Deans Yard Phillips Lane Phillips Lane", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "Wo work with our 40 partner groups in Europe to support patients, raise awareness of colorectal cancer and to advocate for the best treatment care and screening across all EU countries", "registration_date": "2016-05-16T18:01:23.910000", "activity_relevant_comm": "White Paper on colorectal cancer treatment\r\nAnnual review\r\nMeetings in the EU Parliament \r\nCollaboration with other NGO and clinical stakeholders in Europe on health issues", "head_office_post_code": "SP1 3YP", "goals": "EuropaColon is committed to preventing deaths from colorectal cancer and improving the quality of life and support for those affected by the disease\r\n\r\nOur 4 Key Goals\r\nTo reduce the numbers of European citizens affected by colorectal cancer\r\nTo identify colorectal cancer at an early stage\r\nTo ensure access\r\nto best treatment and care for all European patients\r\nTo support novel and innovative research into colorectal cancer", "members": 5, "last_update_date": "2016-05-17T10:41:19.666000", "members_fte": 3.25, "head_office_phone": "44 1772333587", "members_25": null, "web_site_url": "http://www.europacolon.com", "sub_category": 31, "activity_other": "We are not involved in these groups at present", "name": "Europacolon", "created_at": "2016-05-17T01:52:12.447290", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffc559aded2d4379915fe024267d5399", "identification_code": "509496521674-06", "legal_status": "not for profit", "members_100": 1, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "be_office_lat": null, "updated_at": "2016-08-12T02:07:20.156460", "entity": "1b95406c5f8c486fbad9295c26f6e201", "number_of_natural_persons": null, "legal": "4499ffdcc0744c59914a27084dbe7d22", "native_name": null, "head_office_country": "Italy", "id": "ffb255f6e8004fe88b4593048bae9c6f", "activity_industry_forums": "Nell'ambito della realizzazione di ETIS (European Tourism Indicator System) la Dott.ssa Bresciani, consulente specializzato nel Turismo ha partecipato a tutti i Forum sulla materia organizzati dalla Commissione dagli anni 2009 ed ha concluso l'iter partecipativo con la relazione tenuta presso la Commissione lo scorso Gennaio 2016 durante la premiazione per le 100 destinazioni di turismo europeo di cui ha fatto parte con l'Unione dei Comuni TERRAE ANIO IUBENSANAE come coordinatore del progetto.", "contact_country": 108, "head_office_postbox": "00027", "networking": "www.lazio.coldiretti.it\r\nwww.confcooperative.it\r\nwww.jlag.com\r\nwww.festfoundation.eu\r\nwww.pm4esd.eu\r\nwww.ccitabel.com", "members_75": null, "main_category": 1, "members_50": 100, "activity_expert_groups": "None", "sub_category_title": "Self-employed consultants", "other_code_of_conduct": "nessuno", "head_office_town": "ROVIANO", "info_members": "La costruzione di PRESS il nuovo gruppo associativo di progettisti europei fa pensare ad un aumento del gruppo di interesse intorno al proponente MB&PARTNERS", "head": "4499ffdcc0744c59914a27084dbe7d22", "status": "inactive", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "Viale Alessandro Manzoni 13 13", "be_office_post_code": null, "activity_inter_groups": "None", "acronym": "MB&P", "activity_eu_legislative": "Le principali iniziative sono state nell'ambito del turismo in collaborazione con la attuale DG GROWTH con cui si \u00e8 percorso il cammino dei label territoriali ETIS sui piccoli comuni del Lazio. La societ\u00e0 ha anche partecipato a riunioni del Consiglio d'Europa sui Cammini e il Presidente \u00e8 divenuto Manager di Routes presso l'Istituto Culturale di Lussemburgo per il riconoscimento dei Cammini Certificati.\r\nIniziative sono state svolte di seminari relativi alle opportunit\u00e0 della Commissione per la convergenza tra turismo e agricoltura.\r\nNell'ambito formativo si \u00e8 ottenuta la certificazione PM4SD in Bruxelles per le certificazioni di Project Management e si sono organizzati seminari in Roma per il trasferimento di competenza e informazione sulle opportunit\u00e0 europee all'interno di Fondazione Italia Sostenibile per Azioni. \r\nAttualmente MB&PARTNERS \u00e8 proponente di una petizione europea per il riconoscimento della figura professionale del progettista europeo seguendo i regolamenti comunitari 1025/2012, la Direttiva 123/2006 sui Servizi e le attivit\u00e0 di controllo e sorveglianza, EQF (European Qualification Framework), Reg. CE n.765/2008 in materia di sorveglianza del mercato.", "registration_date": "2016-07-26T07:50:53.829000", "activity_relevant_comm": "MB&PARTNERS ha svolto attivit\u00e0 di comunicazione sia a livello locale , regionale e nazionale , che a livello internazionale. In ambito locale \u00e8 attiva con animazione territoriale per la conoscenza delle linee programmatiche europee di sviluppo dei territori rurali con attivit\u00e0 eventistiche per il miglior posizionamento dei temi. Con un evento di rilevanza europea \u00e8 stata la societ\u00e0 proponente dell'evento INCOUNTRY (www.incountry.eu), patrocinato dalla rappresentanza italiana della Commissione Europea. Il Presidente Dott.ssa Marina Bresciani ha partecipato al panel di ETIS (European Tourism Indicator System) come una tra le 100 destinazioni selezionate in Europa per il turismo sostenibile (marina bresciani-youtube-ETIS PANEL CONFERENCE). Il Presidente \u00e8 presente a tutti gli INFODAY sul turismo e alle discussioni correlate per il benessere e la qualit\u00e0 della vita con forti connotazioni e correlazioni con l'agricoltura (Coldiretti). Il Presidente \u00e8 attualmente anche rappresentante della Associazione Europea PRESS che ha realizzato il primo evento lo scorso 8 luglio per la certificazione degli skills del progettista europeo e i criteri di valutazione della figura professionale per una regolamentazione europea (pagina facebook PRESS - Progettisti Europei Associati).", "head_office_post_code": "00027", "goals": "MB&PARTNERS nasce dall'idea di creare un network di aziende e professionisti accomunati da un unico obiettivo, in cui ciascuno possa consolidare e condividere le proprie esperienze professionali maturate nel marketing territoriale, del turismo, strizzando l'occhio all'agricoltura, all'arte, alla cultura ed all'ambiente in generale.\r\nIl network non nasce come semplice aggregazione di aziende e professionisti che si occupano delle stesse cose, ma di entit\u00e0 che hanno effettivamente lavorato insieme, cooperato in progetti europei o nazionali o regionali, creato valore aggiunto per il proprio territorio ed abbiano, effettivamente, consolidato la propria collaborazione, collaudandola e fondandola sui risultati effettivamente raggiunti.\r\nMarina Bresciani \u00e8 l'elemento di coordinamento e raccordo tra le competenze verticali e specifiche dei singoli partner, grazie alle molteplici competenze sviluppate nel coordinare progetti integrati dal 2003 ad oggi. Lo spirito aggregativo e cooperativo nasce dalla qualit\u00e0 e solidit\u00e0 delle relazioni professionali che si sono create nel tempo tra i diversi soggetti coinvolti.", "members": 100, "last_update_date": "2016-07-26T08:01:19.825000", "members_fte": 50.0, "head_office_phone": "39 3274089916", "be_office_town": "Bruxelles", "members_25": null, "web_site_url": "http://mbandpartners.it", "sub_category": 13, "activity_other": null, "be_office_postbox": null, "name": "MB&PARTNERS di BRESCIANI MARINA", "be_office_street": "Rue de la Loi 26 ", "created_at": "2016-07-27T02:05:12.456085", "be_office_country": "Belgium", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffb255f6e8004fe88b4593048bae9c6f", "identification_code": "346207322801-08", "legal_status": "DITTA INDIVIDUALE", "members_100": null, "be_office_phone": "32 33185868", "be_office_lon": null, "head_office_lon": null, "structure_members": "www.studiomorandini.net\r\nwww.italiaspa.org\r\nwww.unionegiovenzano.rm.it\r\nwww.comune.mentana.rm.it", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "Standing Committee on Agricultural Research (SCAR) Brusel, Belgicko\r\nInternational Committee for Animal Recording, Rome Italy (Medzin\u00e1rodn\u00e1 komisia pre evidenciu zvierat)\r\nInternational Committee on Food Microbiology and Hygiene (ICFMH) of International Union of Microbiological Societes (IUMS), Monells, \u0160panielsko (pracovn\u00edci NPPC \u2013 V\u00daP s\u00fa zodpovedn\u00ed za rie\u0161enie jednotliv\u00fdch oblast\u00ed potravin\u00e1rskej mikrobiol\u00f3gie pri zabezpe\u010dovan\u00ed bezpe\u010dnos\u0165 potrav\u00edn.", "activity_high_level_groups": "Akt\u00edvna \u010dinnos\u0165 NPPC je v pracovnej skupine Rady EU pre medzin\u00e1rodn\u00e9 environment\u00e1lne z\u00e1le\u017eitosti \u2013 dezertifik\u00e1cia k problematike Dohovoru OSN o boji proti dezertifik\u00e1cii,\r\n\r\n\tEuropean Soil Bureau Network \u2013 Eur\u00f3psky \u00farad pre p\u00f4du, EK/JRC/IES/Ispra,(Zvy\u0161ovanie povedomia o p\u00f4de \u2013 pr\u00edprava podkladov, spracov\u00e1vanie p\u00f4dnych \u00fadajov)\r\n\r\nEuropean Commission, Directorate General for Health and Consumer Protection, Brusel, Belgicko\r\nNPPC \u2013 V\u00daP spolupracuje s komisiou v oblastiach zdravia a ochrany spotrebite\u013eov a zaober\u00e1 sa ochranou a zlep\u0161ovan\u00edm zdravia obyvate\u013eov, bezpe\u010dnos\u0165ou a ne\u0161kodnos\u0165ou potrav\u00edn,", "head_office_lat": null, "updated_at": "2016-08-31T02:17:50.588053", "entity": "15af1f49221b4eafba575eca7e3d371e", "number_of_natural_persons": null, "legal": "6513b50e074640aaae1de8a9622abfa2", "native_name": null, "head_office_country": "Slovakia", "id": "ffae9158758a410391d34d6831f01b86", "activity_industry_forums": "Medzivl\u00e1dny technick\u00fd panel Glob\u00e1lneho partnerstva o p\u00f4de v r\u00e1mci FAO (ITPS-GSP FAO) \u2013 NPPC - V\u00daPOP akt\u00edvna spolupr\u00e1ca\r\n\r\nFarm Accountancy Data Network Committee (\u00da\u010das\u0165 na zasadnutiach v\u00fdboru FADN 3-4x ro\u010dne. Prerokovan\u00e9 s\u00fa: predpisy a nariadenia Eur\u00f3pskej Komisie, Rady a Parlamentu, s\u00favisiace s informa\u010dnou sie\u0165ou po\u013enohospod\u00e1rskeho \u00fa\u010dtovn\u00edctva E\u00da, form\u00e1t v\u00fdkazu pre zber d\u00e1t.)\r\n\r\nInternational Commission of Agricultural and Biosystems Engineering (CIGR), Brusel, Belgicko\r\nThe Organisation for Economic Co-operation and Development, Par\u00ed\u017e, Franc\u00fazsko (OECD)", "contact_country": 201, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 4, "members_50": null, "activity_expert_groups": "DG SANTE - Health and Food Safety, Unit E2 Plant Health, WG Plant Genetic Resources, Brusel, Belgicko (Expertn\u00e1 pracovn\u00e1 skupina genetick\u00fdch zdrojov rastl\u00edn pri E\u00da).\r\n\r\nKomisia E\u00da COPA/COGECA pracovn\u00e1 skupina pre ovce, kozy, te\u013eacie a hov\u00e4dzie m\u00e4so, Brusel, Belgicko (Organiz\u00e1cia EU zastre\u0161uj\u00faca potravin\u00e1rske a po\u013enohospod\u00e1rske organiz\u00e1cie a zv\u00e4zy. NPPC-V\u00da\u017dV Nitra m\u00e1 \u010dlenov v pracovnej skupine Ovce a kozy (poradensk\u00e1 skupina te\u013eacie a hov\u00e4dzie m\u00e4so).\r\n\tEuropean Food Safety Authority (EFSA), Parma, Taliansko\r\n\r\nEuropean Federation of Animal Science (EAAP)\r\nR\u00edm, Taliansko", "sub_category_title": "Think tanks and research institutions", "other_code_of_conduct": null, "head_office_town": "Lu\u017eianky", "info_members": "", "head": "6513b50e074640aaae1de8a9622abfa2", "status": "active", "main_category_title": "IV - Think tanks, research and academic institutions", "head_office_street": "Hlohoveck\u00e1 2 ", "activity_inter_groups": "European Regional Focal Point for ANGR (Eur\u00f3psky region\u00e1lny kontaktn\u00fd bod pre genetick\u00e9 \u017eivo\u010d\u00ed\u0161ne zdroje)\r\n\tEuropean Association for Research on Plant Breeding (EUCARPIA), Z\u00fcrich, \u0160vaj\u010diarsko (Eur\u00f3pska asoci\u00e1cia pre v\u00fdskum v \u0161\u013eachten\u00ed rastl\u00edn (V\u00daRV sa podie\u013ea na pr\u00e1ci viacer\u00fdch sekci\u00ed, najm\u00e4 GZ, krmov\u00edn a obiln\u00edn a zabezpe\u010duje pokusy s tritikale, pr\u00ednosom je mo\u017enos\u0165 z\u00edskavania najnov\u0161\u00edch inform\u00e1ci\u00ed v oblasti geneticko-\u0161\u013eachtite\u013esk\u00e9ho v\u00fdskumu)\r\n\r\nDAGENE (Dunamenti \u00c1llatfajt\u00e1k G\u00e9nmeg\u00f6rz\u00f6 Nemzetk\u00f6zi Egyes\u00fclete), Budape\u0161\u0165, Ma\u010farsko\r\nMedzin\u00e1rodn\u00e1 organiz\u00e1cia pre vini\u010d a v\u00edno v Par\u00ed\u017ei, O.I.V.", "acronym": "NPPC", "activity_eu_legislative": "V zmysle plnenia Nariadenia Eur\u00f3pskeho parlamentu a Rady \u010d. 1107/2009 o uv\u00e1dzan\u00ed pr\u00edpravkov na ochranu rastl\u00edn na trh a Smernice Eur\u00f3pskeho Parlamentu a Rady 2009/128/ES,ktorou sa ustanovuje r\u00e1mec pre \u010dinnos\u0165 Spolo\u010denstva na dosiahnutie trvalo udr\u017eate\u013en\u00e9ho pou\u017e\u00edvania pestic\u00eddov NPPC v s\u00fa\u010dasnosti rie\u0161i \u00falohu \u201eHodnotenie riz\u00edk pr\u00edpravkov na ochranu rastl\u00edn pre ope\u013eova\u010de a spravovanie toxikologicko-informa\u010dn\u00e9ho centra pre v\u010dely a pestic\u00eddy\u201c\r\n-\tSpracov\u00e1vaj\u00fa sa odborn\u00e9 stanovisk\u00e1 pre St\u00e1ly v\u00fdbor pre bezpe\u010dnos\u0165 potrav\u00edn pri EK oh\u013eadom rizika aplik\u00e1cie pr\u00edpravkov na ochranu rastl\u00edn", "registration_date": "2016-08-23T14:54:09.690000", "activity_relevant_comm": "V zmysle rozhodnutia EUR\u00d3PSKEHO PARLAMENTU A RADY \u010d. 529/2013/E\u00da z 21. m\u00e1ja 2013 o pravidl\u00e1ch zapo\u010d\u00edtavania pre emisie a z\u00e1chyty sklen\u00edkov\u00fdch plynov vypl\u00fdvaj\u00face z \u010dinnost\u00ed s\u00favisiacich s vyu\u017e\u00edvan\u00edm p\u00f4dy, so zmenami vo vyu\u017e\u00edvan\u00ed p\u00f4dy a s lesn\u00fdm hospod\u00e1rstvom a o inform\u00e1ci\u00e1ch t\u00fdkaj\u00facich sa opatren\u00ed s\u00favisiacich s t\u00fdmito \u010dinnos\u0165ami sa NPPC zaober\u00e1 sledovan\u00edm a inventariz\u00e1ciou emisi\u00ed z po\u013enohospod\u00e1rskej p\u00f4dy a zmien vyu\u017e\u00edvania p\u00f4dy ako aj anal\u00fdzou emisn\u00fdch faktorov a emisi\u00ed amoniaku a sklen\u00edkov\u00fdch plynov (CH4 , N2O) z chovu hospod\u00e1rskych zvierat\r\n\r\nV zmysle Smernice Eur\u00f3pskeho parlamentu a Rady 2009/28/ES o podpore obnovite\u013en\u00fdch zdrojov energie sa rie\u0161i \u00faloha \u201eVypracovanie krit\u00e9ri\u00ed udr\u017eate\u013en\u00e9ho vyu\u017e\u00edvania biomasy\u201c\r\n\r\nV r\u00e1mci programu programu HORIZONT 2020 je NPPC zapojen\u00e9 do rie\u0161enia projektu BIOSKOH\u2019s Innovation Stepping Stones for a novel European Second Generation BioEconomy. \r\nZ\u00e1merom projektu BIOSKOH je podpora rie\u0161en\u00ed pre unik\u00e1tne spracovanie a vyu\u017eitie fytomasy na v\u00fdrobu bioetanolu technol\u00f3giou druhej gener\u00e1cie.", "head_office_post_code": "95141", "goals": "The National Agricultural and Food Centre focuses on comprehensive research and gathering of knowledge in the sustainable use and protection of natural resources, especially soil and water resources for crop production and animal husbandry, quality and safety, innovation and competitiveness of food and non-food products of agricultural origin, productive and non-productive impact of agriculture on the environment and rural development and the transfer of knowledge from agricultural and food research to end users.", "members": 10, "last_update_date": "2016-08-23T15:15:53.294000", "members_fte": 2.5, "head_office_phone": "421 376546122", "members_25": 10, "web_site_url": "http://www.nppc.sk/index.php/sk/", "sub_category": 41, "activity_other": null, "name": "N\u00e1rodn\u00e9 po\u013enohospod\u00e1rske a potravin\u00e1rske centrum", "created_at": "2016-08-31T02:17:50.591701", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffae9158758a410391d34d6831f01b86", "identification_code": "509308323113-13", "legal_status": "\u0161t\u00e1tna pr\u00edspevkov\u00e1 organiz\u00e1cia", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-04-07T00:03:42.963618", "entity": "4c94c490da1e48a6af5d409dad93d2cc", "number_of_natural_persons": null, "legal": "923468e984824eb0a525f369e8e03dca", "native_name": null, "head_office_country": "Italy", "id": "ffaa55befc9b477bb35bd635bf458c3c", "activity_industry_forums": "None", "contact_country": 108, "head_office_postbox": null, "networking": "COPA : Committee of Professional Agricultural Organisations\r\nthrough Confagricoltura", "members_75": null, "main_category": 2, "members_50": 2, "activity_expert_groups": "None", "sub_category_title": "Trade unions and professional associations", "other_code_of_conduct": null, "head_office_town": "BOLOGNA", "info_members": "", "head": "ba011dd23b5240af8f980775e88609a6", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "via del monte 10 ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "PAC", "registration_date": "2010-04-08T11:17:31.076000", "activity_relevant_comm": "None", "head_office_post_code": "40126", "goals": "Confagricoltura Emilia- Romagna is a regional branch of the national organisation representative of agricultural interests, which safeguards local farmer structures, all the associated members and every professional group, trade union and economic category linked to those members.", "members": 2, "last_update_date": "2016-04-06T16:35:51.728000", "members_fte": 1.0, "head_office_phone": "39 051 251866", "members_25": null, "web_site_url": "http://www.confagricoltura.org/it/", "sub_category": 26, "activity_other": "-Response to Consultations published by European Commission\r\n\r\n- Forwarding of position papers / statements to MEPS \r\n\r\n- Participation in the elaboration of agricultural position papers on the European level", "name": "CONFAGRICOLTURA EMILIA-ROMAGNA", "created_at": "2015-04-24T01:53:02.429922", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffaa55befc9b477bb35bd635bf458c3c", "identification_code": "36395803420-35", "legal_status": "ASSOCIAZIONE SINDACALE", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-02-11T02:56:07.336686", "entity": "dd0024740d7141a0870688d2aaafe8f6", "number_of_natural_persons": 12, "legal": "1cde557356d944059919483fca786984", "native_name": null, "head_office_country": "Greece", "id": "ffa463c6b2d24eb281d08ce34f369730", "activity_industry_forums": "None", "contact_country": 85, "head_office_postbox": null, "networking": "Member of the INGO network of the Council of Europe", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Thessaloniki", "info_members": "", "head": "db7eb8bab6d347b68fea1312a38f3db0", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Krispou 9, Ano Poli Ano Poli", "activity_inter_groups": "None", "acronym": "CDRSEE", "activity_eu_legislative": "DG for Neighbourhood and Enlargement Negotiations\r\nDG for Education and Culture\r\nDG for International Cooperation and Development\r\nDG for Justice and Consumers\r\nDG for Migration and Home Affairs", "registration_date": "2016-02-10T15:31:14.791000", "activity_relevant_comm": "Joint History Project -- The CDRSEE's flagship project, the JHP is an educational programme that aims to change the way history is taught in high schools across Southeast Europe. The programme, currently in its second phase, provides teachers with workbooks and training so they can offer coursework with multiple perspectives, encouraging students to consider the many aspects of an event and to think critically about information provided. There are currently four workbooks, in 11 languages, covering history up to the Second World War. The next two workbooks, which will address the Cold War and the Wars of the 1990s, are due to be published in July 2016 and launched in September 2016. The programme enjoys the support of nearly all the Ministries of Education across the region, and is considered the gold standard in history teaching.\r\n \r\nOkruzenje (Vicinities) -- The CDRSEE has done what no one thought possible just a few years ago -- created an informative, engaging talk show especially for the Western Balkans that deals with divisive issues in the region. The same programme is broadcast on 10 national television channels and scores of regional channels across the Western Balkans, including all the countries of the former Yugoslavia and Albania. The show, kicking off its fifth season, brings together guests from different countries and backgrounds on the same set. Okruzenje made history at the Western Balkans Summit Vienna 2015 in August when for the first time ever, the Prime Ministers of Albania and Serbia were both guests in a single studio, in this case advocating regional cooperation. \r\n\r\nNetucate -- The CDRSEE is partnering with EUROCLIO for a three-year project on education reform in Southeast Europe. The project leverages the \"Teaching for Learning\" methodology manual produced by the CDRSEE, providing teacher training and materials. Overall the project includes a major education evaluation, a pilot project and a project plan, as well as teacher training and a strengthening of the network of key actors, all focused on enhancing the education system to deal with a global, interactive society. The process will be followed via a special episode series of the \"Okruzenje\" TV talk show. The ultimate goal is educational reform in order to help sustain the democratisation process and enhance sensitivity and understanding, through reforms and changes in the formal school system.\r\n \r\nVicinities Europe -- Vicinities Europe has taken the proven Okruzenje (Vicinities) model and applied it to Europe, where there are certainly ample divisive issues. The idea surfaced from a presentation of Okruzenje in the European Parliament, where MEPs suggested widening the show to Europe, noting its power in fostering reconciliation and understanding among the people. Two pilot shows were produced in October 2015 -- one on the migrant and refugee crisis, and another on the future of the European idea. CIRCOM, the European Association of Regional Televisions, featured Vicinities Europe on its website and offered it to all of its members. So far, the shows have been broadcast in at least nine countries.", "head_office_post_code": "54634", "goals": "The Center for Democracy and Reconciliation in Southeast Europe is a non-governmental, non-profit organisation that seeks to foster democratic, pluralist, and peaceful societies in Southeast Europe. We advocate principles of social responsibility, sustainable development, and reconciliation among the peoples in the region. We accomplish these goals via media activities, educational programmes, seminars, publications, conferences, research projects, exchange programmes, and opinion polls.", "members": 1, "last_update_date": "2016-02-10T15:32:51.296000", "members_fte": 0.25, "head_office_phone": "30 2310960820", "members_25": 1, "web_site_url": "http://www.cdrsee.org", "sub_category": 31, "activity_other": null, "name": "Stichting Center for Democracy and Reconciliation in Southeast Europe", "created_at": "2016-02-11T02:56:07.343619", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffa463c6b2d24eb281d08ce34f369730", "identification_code": "660781520586-28", "legal_status": "Foundation non-governmental and non-profit", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-07-21T02:08:37.366704", "entity": "8325771f162b45498135a098dfb51cb8", "number_of_natural_persons": 39582, "legal": "77b4e80e645c4eb88d42acae1f4fd430", "native_name": null, "head_office_country": "United Kingdom", "id": "ffa09f73d35640b788cf26e335b50d84", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 4, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Academic institutions", "other_code_of_conduct": null, "head_office_town": "London", "info_members": "", "head": "4d1f631078c3459689f9115858f83163", "status": "active", "main_category_title": "IV - Think tanks, research and academic institutions", "head_office_street": "The Strand ", "activity_inter_groups": "None", "acronym": "KCL", "activity_eu_legislative": "Contribution to consultation and written correspondence", "registration_date": "2016-07-20T13:28:48.646000", "activity_relevant_comm": "None", "head_office_post_code": "WC2R 2LS", "goals": "King's College London is dedicated to the advancement of knowledge, learning and understanding in the service of society.\r\n\r\nThe college's mission is articulated in the College's Strategic Plan 2006 - 2016 (http://www.kcl.ac.uk/aboutkings/strategy/PDFs--Resources/2006-16StrategicPlan.pdf) and in the accompanying suite of linked strategies", "members": 1, "last_update_date": "2016-07-20T13:29:14.656000", "members_fte": 0.25, "head_office_phone": "44 78365454", "members_25": 1, "web_site_url": "http://www.kcl.ac.uk", "sub_category": 42, "activity_other": "Contribution to consultation and written correspondence", "name": "King's College London", "created_at": "2016-07-21T02:08:37.373983", "uri": "http://api.lobbyfacts.eu/api/1/representative/ffa09f73d35640b788cf26e335b50d84", "identification_code": "335281522747-30", "legal_status": "'Exempt' charity under Schedule 3 of the Charities Act 2011 for the purposes of UK charity legislation", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-06-18T01:59:10.877902", "entity": "ea23cc779051402da25cfd080b2a83c4", "number_of_natural_persons": null, "legal": "7efa8b08a3d14ea9bce46dda642837da", "native_name": null, "head_office_country": "Germany", "id": "ff95562e4f774e7ba0c4a8ee98403c18", "activity_industry_forums": "None", "contact_country": 82, "head_office_postbox": null, "networking": "B\u00f6rsenverein des Deutschen Buchhandels.\r\nhttp://www.boersenverein.de/de/portal/index.html", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Berlin", "info_members": "", "head": "7efa8b08a3d14ea9bce46dda642837da", "status": "inactive", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Fredericiastrasse 8 ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "Urheberrecht\r\nVerlagsrecht", "registration_date": "2016-05-31T15:28:20.995000", "activity_relevant_comm": "None", "head_office_post_code": "14050", "goals": "Das Publizieren von B\u00fcchern. Schwerpunkte: Theater, Film und Literatur.", "members": 3, "last_update_date": "2016-05-31T15:30:48.897000", "members_fte": 3.0, "head_office_phone": "49 303021826", "members_25": null, "web_site_url": "http://www.alexander-verlag.com", "sub_category": 21, "activity_other": null, "name": "Alexander Verlag Berlin", "created_at": "2016-06-01T01:55:05.349179", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff95562e4f774e7ba0c4a8ee98403c18", "identification_code": "052108522024-86", "legal_status": "Einzelfirma", "members_100": 3, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-17T01:39:21.520955", "entity": "e736f0e4a6d149459c5a1da0d62af8ec", "number_of_natural_persons": 1, "legal": "55203a1b62914a8a8033a633b2a3a2a3", "native_name": null, "head_office_country": "Canada", "id": "ff919bf968eb498bb7af62a1494a49d1", "activity_industry_forums": "None", "contact_country": 39, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 3, "members_50": 1, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": "Michel Georges Abdelahad", "head_office_town": "St-Jean-sur-Richelieu", "info_members": "De 1989 \u00e0 2004, nous avons \u00e9t\u00e9 tr\u00e8s actif au Canada. Des raisons personnelles ont conduit un ancien organisme de charit\u00e9 canadien \u00e0 se retir\u00e9.\r\n\r\n( Les Habitations Organisationnelles Mondiales pour la Famille )\r\n\r\nMichel Abdelahad, fondateur et ex-pr\u00e9sident de cet organisme reprendra les activit\u00e9es.", "head": "0ae64e61a73a431580ea1cb456740bdd", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "1392 Jacques-Cartier Sud ", "activity_inter_groups": "None", "acronym": "Michel Abdelahad", "activity_eu_legislative": "Nous avons les m\u00eames buts que l'Union europ\u00e9enne ou les Nations Unies, soit: C\u2019est en 2000 au sommet du mill\u00e9naire organis\u00e9 par les Nations Unies que les Chefs d\u2019\u00c9tats de 189 pays et des gouvernements du monde entier, se sont mis d\u2019accord pour n\u2019\u00e9pargner aucun effort pour lib\u00e9rer leurs semblables, hommes, femmes et enfants des conditions abjectes et d\u00e9shumanisantes de l\u2019extr\u00eame pauvret\u00e9. L\u2019objectif de l\u2019Union europ\u00e9enne, avec plus de 80 millions de personnes menac\u00e9es de pauvret\u00e9, consistait \u00e0 sortir au moins 20 millions de personnes de la pauvret\u00e9 et de l\u2019exclusion sociale d\u2019ici l\u2019an 2020.", "registration_date": "2012-04-06T18:28:15.430000", "activity_relevant_comm": "None", "head_office_post_code": "J3B 6Y8", "goals": "Une solution \u00e0 la pauvret\u00e9 et au ch\u00f4mage\r\n\r\nNotre projet vise \u00e0 garantir la s\u00e9curit\u00e9 de l\u2019habitation et de l\u2019alimentation de la famille vivant sous le seuil de pauvret\u00e9 \u00e0 la classe moyenne, telle garantie n\u2019\u00e9tant actuellement qu\u2019un avantage de la classes plus nantie. \r\n\r\nEn solvant les probl\u00e8mes de pauvret\u00e9, ce projet va cr\u00e9er un \u00e9quilibre entre ces classes. L\u2019une d\u00e9pendra de l\u2019autre, mais dans des conditions ou contextes diff\u00e9rents.\r\n\r\nL\u2019\u00e9quilibre ainsi cr\u00e9\u00e9 mettra un terme \u00e0 la lutte des classes et aux conflits qui, depuis trop longtemps,\r\nperdurent \u00e0 faire tant de victimes.\r\n\r\nNous consid\u00e9rons que nous avons tous un travail \u00e9galement valable, essentiel et indispensable dans la soci\u00e9t\u00e9. L\u2019habitation et l\u2019alimentation sont des besoins essentiels autant pour le plus bas salari\u00e9 que pour le plus nanti. Pourtant, ces besoins ne sont pas toujours ad\u00e9quatement\r\ncombl\u00e9s.\r\n\r\nLes travailleurs moins salari\u00e9s n\u2019auraient-ils pas droits \u00e0 aux m\u00eames avantages que leur employeur qui s\u2019enrichira \u00e0 leurs d\u00e9pends ?\r\n\r\nNotre projet cr\u00e9era cette \u00e9quilibre\r\n\r\nUne solution concr\u00e8te et r\u00e9aliste \u00e0 ce probl\u00e8me, c\u2019est l\u2019acc\u00e8s \u00e0 l\u2019habitation unifamiliale priv\u00e9e et l\u2019alimentation pour le travailleur soutien de famille bas salari\u00e9 ainsi que pour la classe moyenne. Ce projet a \u00e9t\u00e9 con\u00e7u pour r\u00e9tablir un \u00e9quilibre entres ces classes.\r\n\r\nLe 27 octobre 2014, nous avons fait parvenir une lettre \u00e0 Monsieur Martin Schultz, Pr\u00e9sident du Parlement europ\u00e9en. \u00c9tant canadiens, nous lui demandions dans notre correspondance, le processus afin d\u2019obtenir un ou une d\u00e9put\u00e9(e), dans le but de pr\u00e9senter officiellement notre projet aux membres de l\u2019Union europ\u00e9enne.", "members": 1, "last_update_date": "2016-03-15T12:32:49.855000", "members_fte": 0.5, "head_office_phone": "438 8376023", "members_25": null, "web_site_url": "http://www.michelabdelahad.ca", "sub_category": 31, "activity_other": "Nous avons fait parvenir une lettre de sensibilisation \u00e0 plus de 120 pays, \u00e0 des milliers de personnes dont des leaders, des administrateurs, des commer\u00e7ants, des industries.\r\n\r\nVoici la Lettre de sensibilisation:\r\n\r\nobjet:Le Projet , une solution \u00e0 la pauvret\u00e9 et au ch\u00f4mage\r\n\r\nMadame, Monsieur,\r\n \r\nCe projet, une solution \u00e0 la pauvret\u00e9 et au ch\u00f4mage, vise \u00e0 s\u00e9curiser l\u2019habitation et l\u2019alimentation pour la classe moyenne, une garantie qui n\u2019est actuellement qu\u2019un avantage de la classes plus nantie. \r\nNous consid\u00e9rons que, l'habitation et l'alimentation ne vont pas au m\u00e9rite, mais sont acquises et essentielles pour l'\u00eatre humain et nous y avons tous droit.\r\nEn apportant une solution aux probl\u00e8mes de pauvret\u00e9 dans le monde, ce projet cr\u00e9era un \u00e9quilibre entre ces classes. L\u2019une d\u00e9pendra de l\u2019autre, mais dans des conditions ou contextes diff\u00e9rents.\r\nL\u2019\u00e9quilibre ainsi cr\u00e9\u00e9 mettra un terme \u00e0 la lutte des classes, aux injustices et aux conflits qui, depuis trop longtemps, perdurent \u00e0 faire tant de victimes.\r\nNous consid\u00e9rons que nous avons tous un travail \u00e9galement valable, essentiel et indispensable dans la soci\u00e9t\u00e9. L\u2019habitation et l\u2019alimentation sont des besoins essentiels autant pour le plus bas salari\u00e9 que pour le plus nanti. Pourtant, ces besoins ne sont pas toujours ad\u00e9quatement combl\u00e9s.\r\nLes travailleurs moins salari\u00e9s n\u2019auraient-ils pas droits aux m\u00eames avantages que leur employeur qui s\u2019enrichira \u00e0 leurs d\u00e9pends ?\r\nNotre projet cr\u00e9era cet \u00e9quilibre. \r\nNous vous invitons \u00e0 venir visiter notre site internet au www.michelabdelahad.ca\r\nNous avons besoin de votre aide.\r\nAu plaisir de vous rencontrer.\r\nVeuillez, agr\u00e9er, Madame, Monsieur, l'expression de nos sentiments les meilleurs.\r\nMichel Abdelahad", "name": "Michel Abdelahad", "created_at": "2015-04-24T02:03:29.575210", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff919bf968eb498bb7af62a1494a49d1", "identification_code": "90135938437-51", "legal_status": "\u00c9tudiant / retrait\u00e9", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-08-18T02:05:39.164064", "entity": "93355a2361e94cdca6c3109c22d5c021", "number_of_natural_persons": null, "legal": "b1ca1ea84ce34faa8cdc85a44adc6532", "native_name": null, "head_office_country": "Belgium", "id": "ff8bf95428b24bfbb473f10d41580e0e", "activity_industry_forums": "None", "contact_country": 21, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "Sustainable Transport Forum\r\nMotorcycle Working Group", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Brussel", "info_members": "", "head": "ae93dd141fee4dd4b8e52c2ffd293e3e", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Boulevard de la Plaine 2 ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "- Type-approval\r\n- Transport policy\r\n- Energy policy\r\n- Communication on decarbonization of transport\r\n- Review Transport Criteria Green Public Procurement", "registration_date": "2016-08-17T15:32:40.727000", "activity_relevant_comm": "- Coordinator European Alternative Fuels' Observatory\r\n- Partner in Solutions\r\n- Partner in REE4EU\r\n- Co-organizor EVS", "head_office_post_code": "1050", "goals": "AVERE \u2013 founded in 1978 - is a European network comprised of members including Users, NGO\u2019s, Associations, Interest groups, Public Bodies, Research & Development entities, Vehicle and Equipment Manufacturers, Electricity Utilities.\r\n\r\nIts main objective is to promote the use of electric mobility in order to achieve greener mobility for cities and countries.\r\n\r\nThe main activities to achieve these objectives are related to dissemination, networking, monitoring, participation in European and multilateral projects, lobbying, research and development, among other. In public policy, AVERE presents the electric drive industry\u2019s and R&D bodies\u2019 concerns to the European Commission.", "members": 3, "last_update_date": "2016-08-17T15:39:52.710000", "members_fte": 0.75, "head_office_phone": "32 477633923", "members_25": 3, "web_site_url": "http://www.avere.org", "sub_category": 31, "activity_other": null, "name": "AVERE", "created_at": "2016-08-18T02:05:39.168461", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff8bf95428b24bfbb473f10d41580e0e", "identification_code": "269727723042-29", "legal_status": "VZW", "members_100": null, "head_office_lon": null, "structure_members": "All AVERE members can be found here:\r\n\r\nhttps://averelev.wordpress.com/avere-lev-task-force-participants/", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-05-20T01:56:04.459713", "entity": "8483b8617edf495ba3a0c548efd0d036", "number_of_natural_persons": 4, "legal": "ba47d71f97c6415a95f7adb15969660c", "native_name": null, "head_office_country": "Belgium", "id": "ff8b766c3874481596465f39a7374139", "activity_industry_forums": "None", "contact_country": 21, "head_office_postbox": null, "networking": null, "members_75": 0, "main_category": 3, "members_50": 3, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Bruxelles", "info_members": "", "head": "4a9a2409fc7543b8ab2c7de45cbcbf25", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Boulevard Saint Lazare 11 ", "activity_inter_groups": "None", "acronym": "ABF", "activity_eu_legislative": "EU activities in the field of education", "registration_date": "2016-05-16T17:32:32.443000", "activity_relevant_comm": "Erasmus+", "head_office_post_code": "1210", "goals": "Alphabet Formation, ABF, is a network of European organizations in the field of human capital development. This investment in knowledge, skills and competences will benefit individuals, institutions, organisations and society as a whole by contributing to growth and ensuring equity, prosperity and social inclusion in Europe and beyond.", "members": 3, "last_update_date": "2016-05-19T19:24:35.963000", "members_fte": 1.5, "head_office_phone": "32 488326305", "members_25": 0, "web_site_url": "http://www.alphabetformation.org", "sub_category": 31, "activity_other": null, "name": "Alphabet Formation", "created_at": "2016-05-17T01:52:14.441021", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff8b766c3874481596465f39a7374139", "identification_code": "348324921710-79", "legal_status": "ASBL", "members_100": 0, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "Horizon H2020", "head_office_lat": null, "updated_at": "2016-09-18T20:36:33.419121", "entity": "fb567d6ec94d40c7844a2bb9a324b727", "number_of_natural_persons": null, "legal": "c9244b6262854fe481ab829974aa01a4", "native_name": null, "head_office_country": "France", "id": "ff893be893604f0e9959c6bb774a97e4", "activity_industry_forums": "None", "contact_country": 75, "head_office_postbox": "34830", "networking": null, "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Professional consultancies", "other_code_of_conduct": null, "head_office_town": "CLAPIERS", "info_members": "", "head": "c9244b6262854fe481ab829974aa01a4", "status": "active", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "45 all\u00e9e Yves Stourdz\u00e9 ", "activity_inter_groups": "None", "acronym": "IDATE", "activity_eu_legislative": "MetisII\r\nEuro5G\r\nCreate-IOT\r\nMagicII\r\nFinancement FEDER", "registration_date": "2016-09-09T15:48:56.517000", "activity_relevant_comm": "None", "head_office_post_code": null, "goals": "IDATE DigiWorld, l\u2019un des instituts europ\u00e9ens de l\u2019\u00e9conomie num\u00e9rique les plus renomm\u00e9s, est sp\u00e9cialis\u00e9 sur les march\u00e9s t\u00e9l\u00e9coms, Internet, m\u00e9dias et les territoires num\u00e9riques. Depuis 1977, nos \u00e9quipes proposent des missions de conseil, des services de veille des march\u00e9s et un programme de d\u00e9bats et de rencontres afin de d\u00e9crypter les enjeux de l\u2019\u00e9conomie num\u00e9rique et d\u2019\u00e9clairer les d\u00e9cisions strat\u00e9giques de nos clients. Nous sommes fiers de travailler chaque ann\u00e9e avec plus de 400 d\u00e9cideurs publics et grandes entreprises qui renouvellent leur confiance dans nos services, au travers de nos trois lignes d\u2019activit\u00e9s :\r\n\u2022\tDigiWorld Research, une offre de prestations d\u2019\u00e9tudes et de conseil\r\n\u2022\tIDATE Consulting, un observatoire ind\u00e9pendant des march\u00e9s et de l\u2019innovation num\u00e9rique\r\n\u2022\tDigiWorld Institute, un think tank europ\u00e9en ouvert sur le monde", "members": 13, "last_update_date": "2016-09-09T15:52:37.466000", "members_fte": 3.25, "head_office_phone": "33 467144444", "members_25": 13, "web_site_url": "http://www.idate.org", "sub_category": 11, "activity_other": null, "name": "Institut de l'Audiovisuel et des T\u00e9l\u00e9communications en Europe", "created_at": "2016-09-18T20:36:33.426290", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff893be893604f0e9959c6bb774a97e4", "identification_code": "713335923349-24", "legal_status": "Association Loi 1901", "members_100": null, "head_office_lon": null, "structure_members": "http://www.idate.org/en/Forum/Members/Members-List_42_.html", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 37.5197479, "updated_at": "2016-03-26T01:50:56.435389", "entity": "241e762235884644aad9cd2ca1b4e4d9", "number_of_natural_persons": null, "legal": "ddcefa2c6ed84403a79cf581ef8ae649", "native_name": null, "head_office_country": "Italy", "id": "ff802d6280874fb08e132d662e46f18e", "activity_industry_forums": "None", "contact_country": 108, "head_office_postbox": null, "networking": null, "members_75": 1, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "CATANIA", "info_members": "", "head": "af5aa34046b24aa79be61c468362d592", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "CORSO DELLE PROVINCE, 203 ", "activity_inter_groups": "None", "acronym": "FIPI", "activity_eu_legislative": "Mobilit\u00e0 lavoratori", "registration_date": "2015-01-01T13:14:34.261000", "activity_relevant_comm": "None", "head_office_post_code": "95128", "goals": "1) la rappresentanza sindacale degli associati, tutelandone gli interessi in tutte le sedi;\r\n2) la promozione dell\u2019attivit\u00e0 di formazione dei lavoratori autonomi e degli imprenditori, a tutela dei valori morali, civili e per la qualificazione;\r\n3) la rappresentanza e tutela dei lavoratori autonomi e delle imprese, nei rapporti con le istituzioni pubbliche e private, la Pubblica Amministrazione, le organizzazioni politiche, sociali, economiche a livello nazionale ed internazionale intervenendo anche attraverso le proprie organizzazioni territoriali e di settore per garantire la tutela e rappresentanza a tutti i livelli;\r\n4) la stipula, anche attraverso organizzazioni di settore, di accordi e contratti collettivi di lavoro fornendo la relativa assistenza alle associazioni territoriali e di settore interessato;\r\n5) l\u2019assistenza sociale e previdenziale di Patronato in Italia ed all\u2019estero, anche in convenzione;\r\n6) la rappresentanza, l\u2019assistenza e la consulenza di ogni aspetto dell\u2019attivit\u00e0 aziendale anche sotto i profili: contabile, amministrativo, legale, tecnico, tributario-fiscale, assicurativo-finanziario, sindacale e di consulenza del lavoro;\r\n7) la costituzione e la promozione di agenzie per l\u2019impiego secondo le norme vigenti, in attuazione del disposto di cui all\u2019art.78 della Legge n. 413 del 30.12.1991 e s.m.i,;\r\n8) la promozione ed assistenza alla creazione di nuove imprese con azioni specifiche, anche nel quadro degli appositi programmi della U.E.;\r\n9) la formazione professionale e continua dei lavoratori autonomi, degli imprenditori della piccola impresa, degli apprendisti, dei dipendenti e quanti operano nelle imprese o che intendano inserirsi nelle attivit\u00e0 aziendali, anche ai sensi del comma 3, art. 8 bis, D.lgs. 626/94 e s.m.i.;\r\n10) la costituzione, il potenziamento e l\u2019organizzazione anche sindacale di organismi economici, cooperativistici, mutualistici e consortili;\r\n11) attivit\u00e0 in materia di immigrazione e formazione interculturale con l\u2019obiettivo di elaborare strategie progettuali che permettano alla comunit\u00e0 locale di relazionarsi in maniera consapevole, aperta e dialogica con il fenomeno migratorio, contribuendo alla formazione di una societ\u00e0 multiculturale retta dalla valorizzazione delle differenze in un contesto di civile e pacifica convivenza.", "members": 2, "last_update_date": "2016-03-23T12:09:35.589000", "members_fte": 1.75, "head_office_phone": "095 449778", "members_25": null, "web_site_url": "http://www.fipi.it", "sub_category": 31, "activity_other": "Mobilit\u00e0 di persone a scopo lavorativo all'interno della Comunit\u00e0 europea.", "name": "FEDERAZIONE ITALIANA PICCOLE IMPRESE", "created_at": "2015-04-24T02:26:23.530723", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff802d6280874fb08e132d662e46f18e", "identification_code": "681912015411-37", "legal_status": "ASSOCIAZIONE", "members_100": 1, "head_office_lon": 15.0910225, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-04-07T00:37:19.553399", "entity": "a6ec27aa087f4d17afcd58832b92d3a7", "number_of_natural_persons": 51, "legal": "2dbc3ce9673b4989b73632e346f8dbf2", "native_name": null, "head_office_country": "Ireland", "id": "ff724deeeaf8408a9ff65a58e605d552", "activity_industry_forums": "None", "contact_country": 105, "head_office_postbox": null, "networking": "Health and Environment Alliance\r\nInternational Society of Doctors for the Environment\r\nInternational Physicians for the Prevention of Nuclear War\r\nInternational Campaign to Abolish Nuclear Weapons\r\nIrish Environmental Network\r\nIrish Environmental Pillar", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Bandon", "info_members": "All persons are volunteers (Unpaid)", "head": "2dbc3ce9673b4989b73632e346f8dbf2", "status": "inactive", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Castlebernard ", "activity_inter_groups": "None", "acronym": "IDEA", "activity_eu_legislative": "We are involved in many EU environmental issues through our affiliation to the Health and Environment Alliance (HEAL) based in Brussels, and with UN (UNEP) issues, mainly Climate Change, through the International Society of Doctors for the Environment (ISDE).", "registration_date": "2015-03-31T19:35:05.471000", "activity_relevant_comm": "Letters and articles in the lay and medical press, speaking on local and national radio and on TV when the opportunity arises. Attending various relevant meetings.", "head_office_post_code": "xxxxx", "goals": "To highlight the risks of environmental degradation and loss of biodiversity to human health including chemical contamination of the biosphere and climate change to medical professionals, the public and government. To advocate for a better and more sustainable way of life by holding public meetings, writing in lay and medical press/journals, speaking at public meetings, liasing with other NGOs, official organisations and government departments, the EU and the UN.", "members": 10, "last_update_date": "2015-04-20T19:17:38.830000", "members_fte": 2.5, "head_office_phone": "353 23 8844697", "members_25": 10, "web_site_url": "http://www.ideaireland.org", "sub_category": 31, "activity_other": null, "name": "Irish Doctors Environmental Association", "created_at": "2015-04-24T02:20:30.597430", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff724deeeaf8408a9ff65a58e605d552", "identification_code": "115584716819-62", "legal_status": "Registered charity", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 52.5151735, "updated_at": "2016-05-20T00:29:19.114087", "entity": "19db79249b454902a639066e1ec8b07c", "number_of_natural_persons": null, "legal": "d5f231312f2644a5b7c8e6983f983ee1", "native_name": null, "head_office_country": "Germany", "id": "ff6ce8c03aee44788ce83a6544cdbb4c", "activity_industry_forums": "None", "contact_country": 82, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "MDEG\r\nBorderline Classification Group", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "Berlin", "info_members": "", "head": "3cd888fb06694df0b59bdfaf9559a27f", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Werderscher Markt 15 ", "activity_inter_groups": "None", "acronym": "EUROM", "activity_eu_legislative": "Medical Devices Regulation\r\nTTIP\r\nUDI\r\nREACH and RoHS", "registration_date": "2013-09-27T10:09:10.979000", "activity_relevant_comm": "None", "head_office_post_code": "10117", "goals": "The object of EUROM is to represent the joint interests of the precision mechanical and optical industries and to promote cooperation amongst the members.\r\n\r\nMembers of EUROM are the professional organizations which represent the precision mechanical and optical industries in their respective countries (member states of the EU).", "members": 2, "last_update_date": "2016-05-19T12:57:55.693000", "members_fte": 0.5, "head_office_phone": "49 3041402156", "members_25": 2, "web_site_url": "http://eurom.org/", "sub_category": 25, "activity_other": null, "name": "European Federation of Precision, Mechanical and Optical Industries", "created_at": "2015-04-24T02:04:35.541629", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff6ce8c03aee44788ce83a6544cdbb4c", "identification_code": "585778511937-68", "legal_status": "nicht-rechtsf\u00e4higer Verein im Sinne des \u00a7 54 BGB", "members_100": null, "head_office_lon": 13.3971302, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-04-07T01:00:14.924104", "entity": "abf0273d6186405bac6432a67fd01921", "number_of_natural_persons": 3, "legal": "09a75790dd0e4bbfa6b1d043f2cf38ed", "native_name": null, "head_office_country": "Netherlands", "id": "ff6ba0bcb497410fa406c9794206bf37", "activity_industry_forums": "None", "contact_country": 177, "head_office_postbox": "1000-119", "networking": "ECNAIS is active in an informal platform called European Meeting of Independent Education. EMIE is an informal platform that binds together, once a year all organizations with similar purposes.", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": "Ana Sofia Fialho Coelho dos Reis", "head_office_town": "Den Haag", "info_members": "The members of the Company shall be such persons nominated pursuant to the principles of the following named bodies (together referred to as \u201cthe Constituent Associations\u201d) shall so long as they remain in membership have the right to nominate a member for election of the Company. \r\n\r\nIn addition such other National Associations of Independent Schools as the Management Committee shall from time to time approve may each nominate 1 person as a member of the Company.", "head": "90fdf56cff874f0bb8a213be45db6d2c", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Bezuidenhoutseweg, 251-253 32-1E 32-1E", "activity_inter_groups": "None", "acronym": "ECNAIS", "activity_eu_legislative": "Collaboration between national associations of Independent Schools. \r\n\r\nTo function as a network of National Associations To exchange ideas and information. To hold meetings at which to discuss new initiatives in order to strength the European dimension in independent schools. \r\nTo provide information about European education and to disseminate more knowledge about different educational systems. To assist the establishment of E.U. educational projects. \r\nTo organize in service training for headmasters and teachers. To promote participation in international teacher\u00b4s training progammes. To help mobility and network for teachers, students and educational personnel. \r\n\r\nCoordination of National Associations of Independent Schools. To monitor the changing trends towards the Independent Schools in the different European countries. To monitor the political environment with regard to the Independent Schools in European countries. \r\nTo discuss different educational solutions. To audit both governmental and parliamentary documents. To support EU education organisations. To promote understanding of the rights of pluralism in the national systems of education. \r\n\r\nTo be a Forum for working together to establish a common understanding of freedom of education as well as of parental choice. To illuminate public opinion and the EU instances regarding freedom of education and freedom of parental choice. To promote understanding of the rights of parental choice. \r\nTo promote understanding of the vital role of independent schools in a modern democratic society. To further the interest of a all kinds of independent education whose principles conform to those set out in the Universal Declaration of Human Rights. \r\n\r\nTo be a source of contacts for other European countries (Western, Central and Eastern Europe). To be a meeting point with other National Associations of Independent Schools that share the same principles of freedom of education and freedom of parental choice. \r\nTo make agreed representation to the Council of Europe, the European Parliament and the European Union authorities.", "registration_date": "2015-01-16T17:29:52.689000", "activity_relevant_comm": "None", "head_office_post_code": "2594 AM", "goals": "ECNAIS is a non-political, non-confessional, international association for collaboration between national associations of independent schools in European countries. \r\n\r\nECNAIS Supports and pursues the values embedded in a democratic approach to pluralism in the national educational systems, and the respect of the parental choice. \r\nPROMOTES the interests of all kinds of Independent education, confessional and lay, whose principles conform to those set out in the Universal Declaration of Human rights. \r\nDEVELOPS political statements that promote the understanding of the values of the independent sector, and improve their acceptance and financial support in national legislation. \r\nTARGETS policy makers at an international level by representing the Independent sector at the Council of Europe, the European Parliament, The Commission of the European Union and other international organisations, on matters of common concern, based on an agreed programme. ASSISTS current and potential members in their efforts to promote the understanding of the value of a democratic attitude in a plural society.", "members": 1, "last_update_date": "2016-04-06T12:42:40.840000", "members_fte": 0.25, "head_office_phone": "31 70 3315252", "members_25": 1, "web_site_url": "http://www.ecnais.org", "sub_category": 31, "activity_other": "ECNAIS is a non-political, non-confessional, international association for collaboration between national associations of independent schools in European countries.\r\n\r\nECNAIS is recognized by the Council of Europe and the European Union Commission as a non-government organisation with consultavie status.\r\nIts principal objects are:\r\n\r\n-To bring together national associations of independent schools in European countries.\r\n-To assist its members in promoting understanding of the rights of pluralism in the national systems, of education and of parental choice of education for their children and of the vital role of independent schools in a modern democratic society.\r\n-To further the interests of all kinds of independent education, confessional and lay, whose principles conform to those set out in the Universal Declaration of Human Rights.\r\n- When so requested, to make agreed representation to the Council of Europe, the European Parliament, the European Union Commission and other international organisations on matters of joint concern.", "name": "European Council of National Associations of Independent Schools", "created_at": "2015-04-24T02:33:38.686042", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff6ba0bcb497410fa406c9794206bf37", "identification_code": "153452315640-05", "legal_status": "Company limited by guarantee", "members_100": null, "head_office_lon": null, "structure_members": "Association of Independent Schools in the Netherlands(2),\r\nF\u00f6rderverband Freier Schulen(1),\r\nAssociation of Private Schools of Bohemia Moravia and Silesia(1),\r\nBulgarian Association of Private Schools(1),\r\nDanish Council for International Cooperation for Independent Schools(2),\r\nAssiociation of Private Schools in Finland(1),\r\nFoudation pour l'ecole(1),\r\nAssociation of Hungarian Independent Schools(1),\r\nFederation of Independent Schools(1),\r\nNational Forum of Non-public Education(1),\r\nPortuguese Association of Independent Schools(2),\r\nEducati\u00f3n Y Gesti\u00f3n/ Escuelas Catolicas(1),\r\nNational Union for the Development of Private Pre-University Education(1),\r\nFOMENTO Education Centers(1),\r\nAssociation of Catholic Schoolboards(1),\r\nVerus(1),\r\nTurkish Private Schools' Association(1),\r\nUkrainian Association of Private Educational Istitutes(1),\r\nStichting Rijdende School(1),\r\nHellenic Private Schools Association(1),\r\nElternlobby(1)", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-26T01:30:01.606285", "entity": "50c6580582f94a34af348a115a00ae2b", "number_of_natural_persons": null, "legal": "a7ffe3422509435fbb15f365747978f8", "native_name": null, "head_office_country": "Ireland", "id": "ff698260d45047178a5e8775547815bc", "activity_industry_forums": "None", "contact_country": 105, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Dublin", "info_members": "", "head": "2382bd341af34ef786218727e8e6c46b", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Old Central Terminal Building, 1st Floor Dublin Airport Dublin Airport", "activity_inter_groups": "None", "acronym": "daa", "activity_eu_legislative": "Air Passenger Rights, Slots, Aviation Security, General Aviation Policy; Environmental Issues, Energy Union, Infrastructure Development", "registration_date": "2012-04-27T11:56:55.661000", "activity_relevant_comm": "None", "head_office_post_code": "N/A", "goals": "To influence the formulation or implementation of policy and decision making processes of the EU Institutions", "members": 25, "last_update_date": "2016-03-24T12:49:27.922000", "members_fte": 6.25, "head_office_phone": "353 1 8141111", "members_25": 25, "web_site_url": "http://www.daa.ie/gns/home.aspx", "sub_category": 21, "activity_other": "Engagement on Airport Package", "name": "daa plc", "created_at": "2015-04-24T02:07:49.792070", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff698260d45047178a5e8775547815bc", "identification_code": "64031768679-71", "legal_status": "Operating", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "Participation in BEPA until 2009", "activity_high_level_groups": "None", "head_office_lat": 50.01643435, "updated_at": "2016-03-09T01:52:57.476417", "entity": "40d6d5612dce4849a8422da8868f0570", "number_of_natural_persons": 9, "legal": "0ce76701cd904ea082793e5af8572015", "native_name": null, "head_office_country": "Germany", "id": "ff5e850d10a34a8d9e0b6772f68050b2", "activity_industry_forums": "None", "contact_country": 82, "head_office_postbox": "no", "networking": "SGI Europe Buddhist Association e.V. is a member of Soka Gakkai International, domiciled in Tokyo, Japan", "members_75": null, "main_category": 5, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Organisations representing churches and religious communities", "other_code_of_conduct": null, "head_office_town": "M\u00f6rfelden-Walldorf", "info_members": "Matthias Gr\u00f6ninger (chairperson)\r\nHideaki Takahashi (vice (deputy) chairperson)\r\nRobert Samuels (treasurer)\r\nSuzanne Pritchard (member of the board of directors)\r\nJo\u04eblle Troeder (member of the board of directors)\r\nKazuo Fujii (member of the board of directors)", "head": "9a6e6bafa8a2494fa169854ef3c6757f", "status": "active", "main_category_title": "V - Organisations representing churches and religious communities", "head_office_street": "Nordendstrasse, 38 ", "activity_inter_groups": "None", "acronym": "SGI EBA", "activity_eu_legislative": "We are active in the fields of peace-building through culture and education based on the humanistic principles of Nichiren Buddhism as practised within the SGI movement", "registration_date": "2014-06-18T14:44:23.915000", "activity_relevant_comm": "We remain open to involvement in activities and projects", "head_office_post_code": "64546", "goals": "We are the European branch of the Soka Gakkai International (SGI) a lay Buddhist movement linking together approximately 140,000 members across Europe. (see www.sgi.org for more information).", "members": 2, "last_update_date": "2016-03-08T17:23:38.377000", "members_fte": 0.5, "head_office_phone": "49 610540910", "members_25": 2, "web_site_url": null, "sub_category": 51, "activity_other": "Our various constituent national organisations are active in interfaith activities and projects aimed at developing tolerance, understanding and cohesion", "name": "SGI Europe Buddhist Association", "created_at": "2015-04-24T02:31:28.178188", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff5e850d10a34a8d9e0b6772f68050b2", "identification_code": "828340313721-55", "legal_status": "registered association at district court Darmstadt registration number: VR 83170", "members_100": null, "head_office_lon": 8.58259536432507, "structure_members": "http://www.sgi.org/about-us/sgi-facts/sgi-organizations-registered-constituent.html", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-06-04T01:34:25.606548", "entity": "5de9a6d9a53747f6975b9a445620cba3", "number_of_natural_persons": null, "legal": "496705ef71014783a6550f088671bb28", "native_name": null, "head_office_country": "United Kingdom", "id": "ff5de8e3812e48caa9147bed2f17c2d3", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": "Innovate Finance, innovatefinance.com\r\n\r\nFuture 50, futurefifty.com", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "London", "info_members": "", "head": "04ac790fa23b4605b043b5fe65caf051", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "186 - 188 City Road London London", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "PSD, AMLD, EMD.", "registration_date": "2015-06-30T12:34:39.762000", "activity_relevant_comm": "None", "head_office_post_code": "EC1V 2NT", "goals": "We\u2019re making the world a bit better by helping to make the financial system fair.\r\n\r\nWhen you transfer money internationally, banks and brokers often hide the real cost so you end up paying more in fees than you thought you were going to.\r\nSometimes this is because of the mark-up they put on the exchange rate or because there are additional fees that they just don\u2019t tell you about upfront.\r\n\r\nAt TransferWise, we\u2019re always completely transparent about the total charge and we make that as low as we can. TransferWise is the cheapest and fairest way of transferring money internationally. We\u2019re making sure that it\u2019s our customers that benefit and not the banking system.", "members": 2, "last_update_date": "2016-06-03T14:25:12.105000", "members_fte": 1.25, "head_office_phone": "44 207 250 3119", "members_25": 1, "web_site_url": "http://transferwise.com", "sub_category": 21, "activity_other": null, "name": "TransferWise Ltd", "created_at": "2015-07-07T00:57:02.084724", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff5de8e3812e48caa9147bed2f17c2d3", "identification_code": "843309518020-96", "legal_status": "Corporation", "members_100": 1, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 41.3989444, "updated_at": "2015-07-07T00:54:39.651407", "entity": "b710ed84a0714ee6bc51f5802ba6f3d8", "number_of_natural_persons": null, "legal": "c008150a897b47e4923badc9114a49f0", "native_name": null, "head_office_country": "Spain", "id": "ff4ffaee340a4512af726094b4ef145d", "activity_industry_forums": "None", "contact_country": 209, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Professional consultancies", "other_code_of_conduct": null, "head_office_town": "BARCELONA", "info_members": "", "head": "c008150a897b47e4923badc9114a49f0", "status": "inactive", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "LLACUNA 22 ", "activity_inter_groups": "None", "acronym": "ENERTIKA", "activity_eu_legislative": "eficiencia energ\u00e9tica", "registration_date": "2015-06-12T11:49:46.342000", "activity_relevant_comm": "None", "head_office_post_code": "08005", "goals": "Presentar nuestra organizaci\u00f3n.", "members": 2, "last_update_date": "2015-06-12T12:04:57.328000", "members_fte": 0.5, "head_office_phone": "34 030000718", "members_25": 2, "web_site_url": "http://WWW.ENERTIKA.COM", "sub_category": 11, "activity_other": null, "name": "INGENIERIA Y SERVICIOS DE EFICIENCIA ENERGETICA S.L.", "created_at": "2015-06-13T00:49:44.804466", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff4ffaee340a4512af726094b4ef145d", "identification_code": "580103617803-87", "legal_status": "SOCIEDAD LIMITADA", "members_100": null, "head_office_lon": 2.2017422, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2015-09-30T00:50:25.823162", "entity": "eafd9fd5011c4e9194f1c60a8ae53c5c", "number_of_natural_persons": null, "legal": "3cd636d80d5a405e8464dc3f13939169", "native_name": null, "head_office_country": "United Kingdom", "id": "ff3f0e3bc4824efaad758a4b11912dd7", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": null, "members_75": 1, "main_category": 3, "members_50": null, "activity_expert_groups": "IAS was until summer 2015 member of the EU Alcohol and Health Forum", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "London", "info_members": "", "head": "bab6f1f9af8746ce98bacebaabaef791", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Alliance House, 12 Caxton Street, London ", "activity_inter_groups": "None", "acronym": "IAS", "activity_eu_legislative": "IAS is actively involved at the European level regarding alcohol policies, such as the EU Alcohol Strategy, information to consumers, taxation, marketing and AVMSD, road safety.", "registration_date": "2015-09-29T13:43:09.123000", "activity_relevant_comm": "IAS is member of the European Alcohol Policy Alliance (Eurocare) and holds one board seat in Eurocare. IAS is involved in European projects and conferences on alcohol policies.", "head_office_post_code": "SW1H 0QS", "goals": "Our main work is based around helping to bridge the gap between the scientific evidence on alcohol and the wider public. We want to make all of this evidence accessible to anyone with an interest in alcohol - politicians, reporters, health professionals, students, youth workers and others - and to advocate for effective responses that will reduce the toll of alcohol in society.", "members": 2, "last_update_date": "2015-09-29T13:43:39.428000", "members_fte": 1.0, "head_office_phone": "44 2072224001", "members_25": 1, "web_site_url": "http://www.ias.org.uk", "sub_category": 31, "activity_other": null, "name": "Institute of Alcohol Studies (UK)", "created_at": "2015-09-30T00:50:25.830572", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3f0e3bc4824efaad758a4b11912dd7", "identification_code": "150480218577-06", "legal_status": "charity", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-06-23T02:00:02.214006", "entity": "14ac306c727745d4ad0c65b940d53322", "number_of_natural_persons": 8, "legal": "aa3f7ce935604bdab7b28d94d1553129", "native_name": null, "head_office_country": "Poland", "id": "ff3e2e39d8424ab198a14c1ed74b92fc", "activity_industry_forums": "None", "contact_country": 176, "head_office_postbox": null, "networking": "Sie\u0107 Szk\u00f3\u0142 Nauk Politycznych Rady Europy\r\nhttp://www.schoolsofpoliticalstudies.eu/list-of-schools.aspx", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Warszawa", "info_members": "", "head": "b4065d1f8823493092c8a2f7a970cdde", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Oleandr\u00f3w 6 ", "activity_inter_groups": "None", "acronym": "EAD", "activity_eu_legislative": "EU Global Strategy on Foreign and Security Policy", "registration_date": "2016-06-20T10:41:54.877000", "activity_relevant_comm": "Wsp\u00f3lna Polityka Zagraniczna i Bezpiecze\u0144stwa, aktywno\u015b\u0107 Europejskiej S\u0142u\u017cby Dzia\u0142a\u0144 Zewn\u0119trznych, EU Public Diplomacy, Europejska Polityka S\u0105siedztwa, Partnerstwo Wschodnie", "head_office_post_code": "00-629", "goals": "Celem Fundacji jest:\r\na) Kszta\u0142cenie m\u0142odych os\u00f3b zainteresowanych prac\u0105 w administracji krajowej i\r\nzagranicznej ze szczeg\u00f3lnym uwzgl\u0119dnieniem dyplomacji;\r\nb) Promowanie pozytywnego wizerunku Polski w kraju i za granic\u0105;\r\nc) Promowanie wiedzy z zakresu stosunk\u00f3w mi\u0119dzynarodowych;\r\nd) Dzia\u0142alno\u015b\u0107 na rzecz wsp\u00f3\u0142pracy mi\u0119dzynarodowej; \r\n\r\n\r\nFundacja realizuje swoje cele poprzez:\r\na) prowadzenie systematycznych zaj\u0119\u0107 edukacyjnych w charakterze studi\u00f3w;\r\nb) wspieranie i organizowanie kurs\u00f3w, szkole\u0144, seminari\u00f3w, warsztat\u00f3w tematycznych;\r\nc) organizowanie wyk\u0142ad\u00f3w, seminari\u00f3w i konferencji s\u0142u\u017c\u0105cych przekazywaniu wiedzy, gromadzeniu danych i informacji z zakresu dzia\u0142alno\u015bci Fundacji;\r\nd) inicjowanie i wspieranie program\u00f3w szkolenia specjalist\u00f3w r\u00f3\u017cnych dziedzin dla powstaj\u0105cych i rozwijaj\u0105cych si\u0119 instytucji rynku, demokracji i samorz\u0105du lokalnego;\r\ne) inicjowanie i wspieranie program\u00f3w badawczych maj\u0105cych dostarczy\u0107 wiedzy na temat zjawisk spo\u0142ecznych, ekonomicznych i politycznych, w zakresie o\u015bwiaty, kultury, ochrony \u015brodowiska oraz ochrony zdrowia i pomocy spo\u0142ecznej;\r\nf) inicjowanie i wspieranie program\u00f3w i przedsi\u0119wzi\u0119\u0107 podejmowanych przez plac\u00f3wki prowadz\u0105ce dzia\u0142alno\u015b\u0107 naukow\u0105, naukowo-techniczn\u0105, o\u015bwiatow\u0105, kulturaln\u0105\r\n(tak\u017ce kultury fizycznej i sportu), ochrony \u015brodowiska, dobroczynno\u015bci, ochrony zdrowia i pomocy spo\u0142ecznej oraz rehabilitacji zawodowej i spo\u0142ecznej inwalid\u00f3w;\r\ng) inicjowanie i wspieranie kontakt\u00f3w mi\u0119dzynarodowych, s\u0142u\u017c\u0105cych nawi\u0105zywaniu wsp\u00f3\u0142pracy na rzecz rozwoju demokracji, rynku, nauki, kultury, sztuki i o\u015bwiaty oraz\r\nwymiany informacji;\r\nh) Inicjowanie i wspieranie program\u00f3w informacyjnych, s\u0142u\u017c\u0105cych krzewieniu wiedzy na temat mechanizm\u00f3w rynkowych, instytucji demokracji, praw obywatelskich, a tak\u017ce propagowaniu postawy obywatelskiej oraz ekonomicznej samodzielno\u015bci i inicjatywy;\r\ni) wsp\u00f3\u0142prac\u0119 z w\u0142adzami samorz\u0105dowymi, rz\u0105dowymi i organizacjami pozarz\u0105dowymi w zakresie wymienionym w celach dzia\u0142ania Fundacji;\r\nj) organizowanie i koordynowanie pilota\u017cowych program\u00f3w badawczych oraz pracy grup ekspert\u00f3w;\r\nk) wspomaganie spo\u0142ecznych inicjatyw zbie\u017cnych z celami Fundacji;\r\nl) dzia\u0142ania na rzecz interes\u00f3w grup marginalizowanych spo\u0142ecznie; \r\nm) organizowanie i finansowanie bada\u0144 dotycz\u0105cych tworzenia i stosowania prawa;\r\nn) wsp\u00f3\u0142prac\u0119 z osobami, instytucjami krajowymi oraz zagranicznymi prowadz\u0105cymi dzia\u0142alno\u015b\u0107 w zakresie obj\u0119tym dzia\u0142alno\u015bci\u0105 Fundacji; \r\n\r\nOpr\u00f3cz realizacji inicjowanych przez siebie przedsi\u0119wzi\u0119\u0107, Fundacja wsp\u00f3\u0142dzia\u0142a z innymi instytucjami, organizacjami i osobami dla osi\u0105gania wsp\u00f3lnych cel\u00f3w\r\nstatutowych. Wsp\u00f3\u0142dzia\u0142anie to mo\u017ce mie\u0107 charakter wsparcia organizacyjnego, cz\u0119\u015bciowego lub ca\u0142kowitego finansowania przedsi\u0119wzi\u0119cia albo pomocy w uzyskaniu\r\nniezb\u0119dnych funduszy z innych \u017ar\u00f3de\u0142.", "members": 1, "last_update_date": "2016-06-22T10:16:21.966000", "members_fte": 0.25, "head_office_phone": "48 22 205 06 18", "members_25": 1, "web_site_url": "http://diplomats.pl/", "sub_category": 31, "activity_other": null, "name": "Europejska Akademia Dyplomacji", "created_at": "2016-06-21T02:01:15.432879", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3e2e39d8424ab198a14c1ed74b92fc", "identification_code": "397716222322-37", "legal_status": "Fundacja", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-09T01:47:07.392731", "entity": "e1f1e5abffaf4f109f38d141ab6191d9", "number_of_natural_persons": 33, "legal": "75619ec6640248049fe0c5d325c6e2d0", "native_name": null, "head_office_country": "United Kingdom", "id": "ff3d3f236e4747af9fc50ff58ddb4377", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": "1376", "networking": "Religious Liberty Partnership", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Luton", "info_members": "Vicki Salkin, Advocacy and Development Manager", "head": "234619020a0847b9be2d14b8b0b4a707", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "PO Box 1376 ", "activity_inter_groups": "Contact with the Intergroup on Freedom of Religion and Belief and Religious Tolerance, and attendance at hearings and other activities hosted by this Intergroup.", "acronym": "MEC", "activity_eu_legislative": "Activities of the EEAS, and the Foreign Affairs and Human Rights Committees, with a special focus on freedom of religion and belief.", "registration_date": "2014-05-20T13:25:59.855000", "activity_relevant_comm": "Policy implementation of EU Guidelines on the promotion and protection of freedom of religion or belief.", "head_office_post_code": "LU1 9PP", "goals": "Middle East Concern is a coalition of Christian organisations and individuals that promotes religious freedom in the Middle East and North Africa region, with a special focus on the Christian communities.", "members": 1, "last_update_date": "2016-03-08T10:33:23.289000", "members_fte": 0.25, "head_office_phone": "44 7408 884 202", "members_25": 1, "web_site_url": "http://www.meconcern.org", "sub_category": 31, "activity_other": "Engagement with MEPs and the European External Action Service to assist victims in individual cases of Freedom of Religion or Belief violations, and to address underlying causes of these violations in the Middle East and North Africa region.\r\n\r\nParticipation in European Parliament hearings, consultations and other meetings in Brussels relevant to our mandate.", "name": "Middle East Concern", "created_at": "2015-04-24T02:28:02.887563", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3d3f236e4747af9fc50ff58ddb4377", "identification_code": "814728213659-93", "legal_status": "Not for profit / NGO", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 53.1389846, "be_office_lat": 50.84595215, "updated_at": "2016-08-31T01:28:06.743898", "entity": "7486afe72dcd45dc9ed4331ac4b87b84", "number_of_natural_persons": null, "legal": "7e9d854f81624abfb77aa212a7a7a9f3", "native_name": null, "head_office_country": "Germany", "id": "ff3855a7d5c54d27947ce7773f6b3357", "activity_industry_forums": "None", "contact_country": 82, "head_office_postbox": null, "networking": "EWE ist aufgrund seiner Struktur Mitglied in zahlreichen Verb\u00e4nden und Foren, wie u.a. dem Bundesverband der Energie- und Wasserwirtschaft (bdew), dem Verband kommunaler Unternehmen (VKU), dem Bundesverband Breitbandkommunikation (BREKO), dem European Energy Forum (EEF) oder der European Federation of Energy Traders (EFET). \u00dcber die Mitgliedschaften im VKU und bdew, ist EWE im Rahmen des Europ\u00e4ischen Dachverbandes der lokalen und regionalen Energieunternehmen (CEDEC) sowie EURELECTRIC aktiv. Die Mitgliedschaften unterst\u00fctzen die Arbeit der EWE auf Ebene der Europ\u00e4ischen Union.", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "Task Force Smart Grid (EG 3)", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Oldenburg", "info_members": "Sebastian Schulte-Derne, Beauftragter Br\u00fcssel\r\nDr. Eberhard Meller (Senior Counselor, part-time)", "head": "61d6249ecf2e4d1cadcc5a37599949e6", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Tirpitzstra\u00dfe, 39 ", "be_office_post_code": "1040", "activity_inter_groups": "None", "acronym": "EWE AG", "activity_eu_legislative": "Dossiers v.a. der EU-Energiepolitik, u.a. der Rahmen f\u00fcr die Klima- und Energiepolitik 2030, der Vorschlag zur Einrichtung und Anwendung einer Marktstabilit\u00e4tsreserve f\u00fcr das EU-System f\u00fcr den Handel mit Treibhausgasemissionszertifikaten; die Richtlinie \u00fcber M\u00e4rkte f\u00fcr Finanzinstrumente; die Verordnung \u00fcber die Integrit\u00e4t und Transparenz des Energiegro\u00dfhandelsmarktes (REMIT) sowie die Richtlinie \u00fcber den Aufbau der Infrastruktur f\u00fcr alternative Kraftstoffe.", "registration_date": "2012-02-06T15:22:29.163000", "activity_relevant_comm": "None", "head_office_post_code": "26122", "goals": "Als innovativer Dienstleister mit regionaler Ausrichtung ist EWE in den Gesch\u00e4ftsbereichen Energie, Telekommunikation und Informationstechnologie aktiv. \r\n\r\nDie Vereinigung dieser drei Felder unter einem Dach erm\u00f6glicht es dem Konzern intelligente Energiesysteme zu entwickeln und zu betreiben. Durch eine Reihe von innovativen Produkten f\u00fcr Privat- und Gesch\u00e4ftskunden gestaltet EWE auf diese Weise die Energieversorgung der Zukunft mit gr\u00f6\u00dftm\u00f6glicher Nachhaltigkeit, Effizienz und Zuverl\u00e4ssigkeit. \r\n\r\nMit mehr als 9.000 Mitarbeitern und \u00fcber acht Milliarden Euro Umsatz geh\u00f6rt EWE zu den gro\u00dfen Energieunternehmen in Deutschland. Der Konzern mit Hauptsitz im nieders\u00e4chsischen Oldenburg befindet sich \u00fcberwiegend in kommunaler Hand. Er beliefert im Nordwesten Deutschlands, in Brandenburg und auf R\u00fcgen sowie international in Teilen Polens und der T\u00fcrkei rund 1,5 Millionen Kunden mit Strom und Gas sowie rund 700.000 Kunden mit Telekommunikationsdienstleistungen. Hierf\u00fcr betreiben verschiedene Unternehmen der EWE-Gruppe mehr als 180.000 Kilometer Energie- und Telekommunikationsnetze.", "members": 2, "last_update_date": "2016-08-30T09:56:43.802000", "members_fte": 2.0, "head_office_phone": "49 0441 480500", "be_office_town": "Br\u00fcssel", "members_25": null, "web_site_url": "http://www.ewe.com", "sub_category": 21, "activity_other": null, "be_office_postbox": null, "name": "EWE Aktiengesellschaft", "be_office_street": "Avenue de Cortenbergh 172 ", "created_at": "2015-05-07T21:24:27.391519", "be_office_country": "Belgium", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3855a7d5c54d27947ce7773f6b3357", "identification_code": "00741337988-18", "legal_status": "Aktiengesellschaft", "members_100": 2, "be_office_phone": "32 27438110", "be_office_lon": 4.39140462709525, "head_office_lon": 8.1962705, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 52.2070386, "updated_at": "2016-07-22T01:38:25.249158", "entity": "3ba2dd6a9fa8476287958f7e5c9fe427", "number_of_natural_persons": null, "legal": "bb554fda058e4557b86b4aa85f1dee23", "native_name": null, "head_office_country": "Poland", "id": "ff2e01dcb4264779be6aad1d601392b7", "activity_industry_forums": "None", "contact_country": 176, "head_office_postbox": null, "networking": "Stowarzyszenie Kreatywna Polska www.kreatywnapolska.pl", "members_75": null, "main_category": 2, "members_50": 1, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "Warszawa", "info_members": "", "head": "bb554fda058e4557b86b4aa85f1dee23", "status": "inactive", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "St\u0119pi\u0144ska 22/30 ", "activity_inter_groups": "None", "acronym": "Sygna\u0142", "activity_eu_legislative": "1. Digital Single Market Strategy\r\n2. Przegl\u0105d Dyrektywy Audiowizualnej\r\n3. Reforma Prawa Autorskiego", "registration_date": "2015-07-20T14:21:47.515000", "activity_relevant_comm": "None", "head_office_post_code": "00-739", "goals": "Stowarzyszenie Sygna\u0142 dzia\u0142a na rzecz poszanowania w\u0142asno\u015bci intelektualnej, praw nadawc\u00f3w, dystrybutor\u00f3w, licencjodawc\u00f3w oraz odbiorc\u00f3w program\u00f3w telewizyjnych i innych tre\u015bci multimedialnych. Jego pocz\u0105tki si\u0119gaj\u0105 2001 roku. Obecnie w sk\u0142ad Stowarzyszenia wchodz\u0105 22 firmy dzia\u0142aj\u0105ce w bran\u017cy medi\u00f3w i telekomunikacji.\r\n\r\nSygna\u0142 skupia swoje dzia\u0142ania wok\u00f3\u0142 propagowania konieczno\u015bci efektywnej ochrony w\u0142asno\u015bci intelektualnej. Realizuje swoje cele poprzez organizacj\u0119 szkole\u0144 i warsztat\u00f3w (w tym dla firm cz\u0142onkowskich oraz organ\u00f3w \u015bcigania), prowadzenie kampanii edukacyjnych, przygotowywanie raport\u00f3w, bada\u0144 i stanowisk na tematy zwi\u0105zane z ochron\u0105 w\u0142asno\u015bci intelektualnej.", "members": 3, "last_update_date": "2015-07-20T14:23:51.987000", "members_fte": 1.0, "head_office_phone": "48 22 848 51 29", "members_25": 2, "web_site_url": "http://sygnal.org.pl", "sub_category": 25, "activity_other": null, "name": "Stowarzyszenie Sygna\u0142", "created_at": "2015-07-21T01:03:37.663899", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff2e01dcb4264779be6aad1d601392b7", "identification_code": "208598218249-90", "legal_status": "Stowarzyszenie", "members_100": null, "head_office_lon": 21.0375624, "structure_members": "A+E Networks\r\nBBC Worldwide Polska\r\nCyfrowy Polsat\r\nDiscovery Polska\r\nFOX International Channels Poland\r\nHBO Polska\r\nIrdeto\r\nITI Neovision\r\nKino Polska TV\r\nMTG World Ltd\r\nMultimedia Polska\r\nNAGRA\r\nGrupa Onet\r\nSony Pictures Television\r\nTelewizja Polsat\r\nTurner Broadcasting System Poland\r\nTVN\r\nUniversal Networks International\r\nViacom International Media Networks Northern Europe\r\nThe Walt Disney Company (Polska)\r\nZPR Media", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-06-01T01:18:27.242764", "entity": "83e2a7225e074cda8317a50c35512eb0", "number_of_natural_persons": null, "legal": "7461491a69334e6f9b4c31663a0a1512", "native_name": null, "head_office_country": "Belgium", "id": "ff2dcae924f245828146c2bb86178fde", "activity_industry_forums": "None", "contact_country": 21, "head_office_postbox": null, "networking": "NEANT", "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Self-employed consultants", "other_code_of_conduct": "Code de conduite de la Sophrologie", "head_office_town": "BEUZET", "info_members": "NEANT", "head": "7461491a69334e6f9b4c31663a0a1512", "status": "inactive", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "12 A rue des Taillettes ", "activity_inter_groups": "None", "acronym": "JYL", "activity_eu_legislative": "NEANT", "registration_date": "2014-04-23T14:00:43.123000", "activity_relevant_comm": "NEANT", "head_office_post_code": "5030", "goals": "- Pr\u00e9vention des risques fiscaux transnationaux infra et extra europ\u00e9ens\r\n- Exercice des principes de subsidiarit\u00e9 dans les rapports transnationaux sociaux infra et extra europ\u00e9ens", "members": 1, "last_update_date": "2015-04-30T17:25:18.573000", "members_fte": 1.0, "head_office_phone": "32 478693508", "members_25": null, "web_site_url": null, "sub_category": 13, "activity_other": "NEANT", "name": "Jacques Y. LEIBOVITCH", "created_at": "2015-05-07T21:41:48.375353", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff2dcae924f245828146c2bb86178fde", "identification_code": "520259613506-88", "legal_status": "ind\u00e9pendant", "members_100": 1, "head_office_lon": null, "structure_members": "NEANT", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-01-23T02:47:18.371076", "entity": "dcb5ab6757054a2ba6dab325168c035f", "number_of_natural_persons": null, "legal": "e1faea297e1049c4a965b66fec482503", "native_name": null, "head_office_country": "United Kingdom", "id": "ff2c0482fa3f45f2a7f6b111849f11a9", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Self-employed consultants", "other_code_of_conduct": null, "head_office_town": "London", "info_members": "", "head": "e1faea297e1049c4a965b66fec482503", "status": "inactive", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "Suite 177 372 Old street 372 Old street", "activity_inter_groups": "The years I have been lobbying I have mostly followed the ITREE committee", "acronym": null, "activity_eu_legislative": "Contribute with input to different committees as ITRE, INTA and the Commission.", "registration_date": "2015-12-02T12:13:12.207000", "activity_relevant_comm": "Somerco have handed out several draft proposals to the MEPs in the European Parliament and also the Commission. See the list below:\r\nDraft proposals Enhance the competitiveness of EU member states \r\nPart 1 \u2013 Designated tax to science Enhance the competitiveness of EU member states \r\nPart 2 \u2013 Strategy to support the software industry Enhance the competitiveness of EU member states \r\nPart 3 \u2013 Actions to support women in ICT Enhance the competitiveness of EU member states \r\nPart 4 \u2013 Going abroad\u2013Competitive assets Enhance the competitiveness of EU member states \r\nPart 5 \u2013 Business incubators, financial recycling and incentives into reward Enhance the competitiveness of EU member states \r\nPart 6 \u2013 Standardization as a tool to increase competitiveness Enhance the competitiveness of EU member states \r\nPart 7 \u2013 Different types of innovations Enhance the competitiveness of EU member states \r\nPart 8 \u2013 Open source from science to society Enhance the competitiveness of EU member states \r\nPart 9 \u2013 Crowd sourcing and crowd funding Enhance the competitiveness of EU member states \r\nPart 10 \u2013 Green VAT for business Enhance the competitiveness of EU member states \r\nPart 11 \u2013 Keep talent in Europe Enhance the competitiveness of EU member states \r\nPart 12 \u2013 Research leftovers Enhance the competitiveness of EU member states \r\nPart 13 \u2013 Science Parks - Specializations Enhance the competitiveness of EU member states \r\nPart 14 \u2013 Patent trolls Enhance the competitiveness of EU member states \r\nPart 15 \u2013 Science e - Parks Enhance the competitiveness of EU member states \r\nPart 16 \u2013 Expansion options Enhance the competitiveness of EU member states \r\nPart 17 \u2013 The locally developed infrastructure Enhance the competitiveness of EU member states \r\nPart 18 \u2013 Treaty (Knowledge transfer) Enhance the competitiveness of EU member states \r\nPart 19 \u2013 Different types of infrastructure Enhance the competitiveness of EU member states \r\nPart 20 \u2013 Build infrastructure Enhance the competitiveness of EU member states \r\nPart 21 \u2013 Energy infrastructure (elsewhere) (In progress) \r\nEnhance the competitiveness of EU member states \r\nPart 22 \u2013 Quick market entry (Medical) Enhance the competitiveness of EU member states \r\nPart 23 \u2013 Innovation, Commercialization, Growth Enhance the competitiveness of EU member states \r\nPart 24 \u2013 External energy dependencies Enhance the competitiveness of EU member states \r\nPart 25 \u2013 Old innovations Enhance the competitiveness of EU member states \r\nPart 26 \u2013 The non-IP Parks Enhance the competitiveness of EU member states \r\nPart 27 \u2013 Digital inequality into prosperous society Enhance the competitiveness of EU member states \r\nPart 28 \u2013 Digital Magna Carta \u2013 exemptions in privacy Enhance the competitiveness of EU member states \r\nPart 29 \u2013 The networked subsidiarity (In progress) Enhance the competitiveness of EU member states \r\nPart 30 \u2013 Artic route (counterbalance) Enhance the competitiveness of EU member states \r\nOverview \u2013 Old and new key areas in order to increase the competitiveness of the industry (In progress) \r\nInput on threats against information society.", "head_office_post_code": "EC1V 9LT", "goals": "Somerco aims to help companies, governmental organisations and persons to succeed with increasing trade. It will create job growth. We do this online and offline.", "members": 1, "last_update_date": "2015-12-02T13:05:30.145000", "members_fte": 0.25, "head_office_phone": "44 7733824711", "members_25": 1, "web_site_url": null, "sub_category": 13, "activity_other": "I do not know if theer was a mistake doen when it was time for a renewal. Somerco has been registered in the Transparency register a few years before.", "name": "Somerco", "created_at": "2015-12-03T02:37:11.313688", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff2c0482fa3f45f2a7f6b111849f11a9", "identification_code": "035508519773-34", "legal_status": "Limitied company", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "Analysis, monitoring, communicating with DGs officers or theme related sub-sections (e.g. Executive Agencies) or external national services which are commisioned through the European Commission, related to the above mentioned policy fields in relation to the aforementioned ICCM program initiative.", "head_office_lat": null, "updated_at": "2016-08-02T02:02:57.823297", "entity": "7a85467a724b420a9943dedced251363", "number_of_natural_persons": null, "legal": "bea73ab6ec8c4ae3863da0a781add3ed", "native_name": null, "head_office_country": "Germany", "id": "ff1ddb8bfd7149b6888de10daaac1839", "activity_industry_forums": "None", "contact_country": 82, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Self-employed consultants", "other_code_of_conduct": null, "head_office_town": "Berlin", "info_members": "The operational workload including research, communication, administration and further tasks generated through engagement for European Union themes and affairs, should be basically considered as a contribution of the private sector and as such must be basically compensated. In particular, if the workload is rendered by smallest market participants.", "head": "bea73ab6ec8c4ae3863da0a781add3ed", "status": "active", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "Borsigstr. 9 ", "activity_inter_groups": "None", "acronym": "gmjw", "activity_eu_legislative": "Culture and Education; Entrepreneurship; External Relations; Neighbouring Policies; Sustainable Development; Coherency; Internal Markets; Research;", "registration_date": "2016-06-26T20:35:55.739000", "activity_relevant_comm": "Program initiative for Intercivilizational / Intercultural Dialogue, Development and Cooperation (ICCM)\r\n\r\n(in development)", "head_office_post_code": null, "goals": "gmjw consulting is dedicated to the diversity of cultures and creativity as the central root and expression of human abilities, social interrelations, identity, intercultural dialogue and exchange, and as a key driving factor for development, progress, wealth, community building, civil societies and stability.\r\n\r\ngmjw consulting develops, contributes and carries out operational and strategic value for content, individuals, projects, organisations and frameworks, in particular - but not limited - for smaller organisations, small business and single professionals.\r\n\r\ngmjw consulting supports the encouragement and promotion of cultural entrepreneurship through strategic and operational contributions such as,\r\n\r\n- assistance and support by accompanied consultancy and mentorship,\r\n- project-oriented or temporarily aligned services and mandates,\r\n- contributions and research for the development and improvement of sector and segment specific policy and advocacy frameworks, and\r\n- commitment for cooperation, networking and community building.", "members": 1, "last_update_date": "2016-08-01T10:16:17.440000", "members_fte": 1.0, "head_office_phone": "49 3020008400", "members_25": null, "web_site_url": "http://www.gmjw.net", "sub_category": 13, "activity_other": "I am not sure which other group may be right to be selected. As so far, I have dealt only with groups as described above.", "name": "gmjw consulting - Martin JW Hannemann", "created_at": "2016-06-28T02:12:32.449916", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff1ddb8bfd7149b6888de10daaac1839", "identification_code": "176405522467-72", "legal_status": "Sole entrepreneur", "members_100": 1, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-06-17T02:04:41.455253", "entity": "fa393bf592b94f44ac194ad7275d1227", "number_of_natural_persons": 15, "legal": "bf45cc3122db432e98f7dbfbdbaec6a4", "native_name": null, "head_office_country": "Hungary", "id": "ff1754756bf64805831e8bb4c762109a", "activity_industry_forums": "None", "contact_country": 99, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Budapest", "info_members": "", "head": "78d06c33eef140bb996ab3d36ac294cd", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Damjanich utca 51 ", "activity_inter_groups": "None", "acronym": "K-Monitor", "activity_eu_legislative": "Public procurement, access to information, copyright, anti-corruption, whistleblowing", "registration_date": "2016-06-15T11:00:43.648000", "activity_relevant_comm": "k-monitor.hu\r\nredflags.eu\r\nk.blog.hu", "head_office_post_code": "1071", "goals": "K-Monitor is an anti-corruption grass root NGO founded in 2007. K-Monitor strives against corruption and promotes the transparency of public spending in Hungary. K-Monitor operates open data websites, conducts research and advocates for legal reform. With the contribution of our researches, analyses and recommendations, we aim to challenge and overcome the social indifference to corruption, to raise awareness and disseminate knowledge. We truly believe that information technology can contribute to a more open, more transparent and more democratic way of governing. Therefore K-Monitor develops databases and online tools by which public expenses become trackable, and decision makers can be hold accountable.\r\nPrinciples of our operation are openness, independence and a critical approach.", "members": 1, "last_update_date": "2016-06-15T11:01:31.597000", "members_fte": 0.25, "head_office_phone": "36 17895005", "members_25": 1, "web_site_url": "http://k-monitor.hu", "sub_category": 31, "activity_other": null, "name": "K-Monitor K\u00f6zhaszn\u00fa Egyes\u00fclet", "created_at": "2016-06-17T02:04:41.460045", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff1754756bf64805831e8bb4c762109a", "identification_code": "745636122335-90", "legal_status": "public benefit assiciation", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2015-10-15T00:50:17.979238", "entity": "068450584cd44111b84e342ff687d122", "number_of_natural_persons": null, "legal": "0e3d7caca9d34f01891a740bde3f91b0", "native_name": null, "head_office_country": "United States", "id": "ff1152a3aa88470388abb9d823c78a3d", "activity_industry_forums": "None", "contact_country": 234, "head_office_postbox": null, "networking": "U.S. Chamber of Commerce", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": "DC Bar Association, Missouri Bar Association", "head_office_town": "Washinghton DC", "info_members": "", "head": "1c3ebb576bba4e1abba16bcdf6e7363b", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "1150 Connecticut Avenue NW 12th Floor 12th Floor", "activity_inter_groups": "None", "acronym": "NAMI", "activity_eu_legislative": "Food safety, trade, food labeling", "registration_date": "2015-10-14T15:06:35.057000", "activity_relevant_comm": "Nothing in the EU to date.", "head_office_post_code": "22101", "goals": "NAMI represents the North American meat industry. Our goal is to be the voice of that industry on public policy issues.", "members": 1, "last_update_date": "2015-10-14T15:07:37.490000", "members_fte": 0.25, "head_office_phone": "1 2025874200", "members_25": 1, "web_site_url": "http://meatinstitute.org", "sub_category": 25, "activity_other": null, "name": "North American Meat Institute", "created_at": "2015-10-15T00:50:17.984658", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff1152a3aa88470388abb9d823c78a3d", "identification_code": "863092419193-72", "legal_status": "501(c)(6) under U.S. law trade association", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-09T01:49:38.223999", "entity": "7614fa2ab8db4b7db6a7e5f9fa306793", "number_of_natural_persons": null, "legal": "d942401f93b84f98848b89a649d2e9b5", "native_name": null, "head_office_country": "Spain", "id": "ff0fb4adff974d2aa5b69dae56b23639", "activity_industry_forums": "None", "contact_country": 209, "head_office_postbox": null, "networking": "Deloitte Espa\u00f1a es miembro del Instituto de Censores Jurados de Cuentas de Espa\u00f1a.", "members_75": null, "main_category": 1, "members_50": 2, "activity_expert_groups": "None", "sub_category_title": "Professional consultancies", "other_code_of_conduct": "Estamos sujetos a un C\u00f3digo de Conducta interno de nuestra empresa.", "head_office_town": "Madrid", "info_members": "", "head": "6f47b0aa751a49a59be60e8d06db0144", "status": "active", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "Pza. Pablo Ruiz Picasso, 1, ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "Contabilidad y Auditor\u00eda\r\nCorporate reporting y gobierno Corporativo\r\nCapital Markets Union\r\nData security, cyber security y protection of business privacy\r\nTax \r\nTrade", "registration_date": "2015-03-06T10:58:07.343000", "activity_relevant_comm": "Deloitte S.L. realiza actos a nivel nacional de las implicaciones de las pol\u00edticas europeas para las empresas espa\u00f1olas; estos actos son, fundamentalmente relativos a regulaci\u00f3n financiera.", "head_office_post_code": null, "goals": "Realizaci\u00f3n de auditor\u00edas de cuentas econ\u00f3micas, financieras, inform\u00e1ticas, de transacciones y saldos en internet, de gesti\u00f3n y operativas para cualquier persona f\u00edsica o jur\u00eddica.\r\nRealizaci\u00f3n de auditor\u00edas y asesor\u00edas medioambientales y consultor\u00eda de gesti\u00f3n de patrimonio y proyectos inmobiliarios, as\u00ed como auditor\u00edas y evaluaciones externas de sistemas de prevenci\u00f3n de riesgos laborales.\r\nRealizaci\u00f3n de consultor\u00edas, asesoramientos, estudios sectoriales o empresariales sobre temas econ\u00f3micos, financieros, contables, sectoriales y de gesti\u00f3n de empresas y, en general, sobre todos aquellos relacionados con la informaci\u00f3n, organizaci\u00f3n y planificaci\u00f3n empresarial y de instituciones, incluidos lo servicios de consultor\u00eda y asesoramiento relativos al dise\u00f1o y mejora de los procesos de gesti\u00f3n, an\u00e1lisis y estructura de costes, valoraci\u00f3n de puestos de trabajo, gesti\u00f3n de recursos humanos, planificaci\u00f3n estrat\u00e9gica, gesti\u00f3n de calidad, gesti\u00f3n medioambiental, mejora del conocimiento organizativo, dise\u00f1o e implementaci\u00f3n de sistemas de informaci\u00f3n, gesti\u00f3n y control de tesorer\u00eda y derivados financieros, exteriorizaci\u00f3n de los departamentos de auditor\u00eda interna y mejora de su funcionamiento, an\u00e1lisis sobre la viabilidad de las empresas, gesti\u00f3n del riesgo inform\u00e1tico y an\u00e1lisis de seguridad en el tratamiento informatizado de datos. o en el tratamiento de informaci\u00f3n en internet y en su transmisi\u00f3n y comunicaci\u00f3n, dise\u00f1o de sistemas de control interno y para el control de riesgos de todo tipo y an\u00e1lisis financieros.\r\nRealizaci\u00f3n de actividades de formaci\u00f3n empresarial y profesional.\r\nPrestaci\u00f3n de servicios en el \u00e1mbito de las Tecnolog\u00edas de la informaci\u00f3n y las Comunicaciones.", "members": 2, "last_update_date": "2016-03-08T10:30:27.376000", "members_fte": 1.0, "head_office_phone": "34 915145000", "members_25": null, "web_site_url": "http://www.deloitte.es", "sub_category": 11, "activity_other": null, "name": "Deloitte, S.L.", "created_at": "2015-04-24T02:29:54.491452", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff0fb4adff974d2aa5b69dae56b23639", "identification_code": "727712916372-77", "legal_status": "Sociedad Limitada", "members_100": null, "head_office_lon": null, "structure_members": "Deloitte se refiere a Deloitte Touche Tohmatsu Limited, (private company limited by guarantee, de acuerdo con la legislaci\u00f3n del Reino Unido) y a su red de firmas miembro, cada una de las cuales es una entidad independiente. En www.deloitte.com/about se ofrece una descripci\u00f3n detallada de la estructura legal de Deloitte Touche Tohmatsu Limited y sus firmas miembro.", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "Our experts participate on as needed bases in the activities on various consultative boards within FoodDrinkEurope. \r\nThe positions are then communicated to the relevant part of the EU Commission.", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-02-23T02:22:42.262586", "entity": "81752ab16ef6415b8f9861232e0910a6", "number_of_natural_persons": null, "legal": "28df51c6a18a46c69de34b8e5a59f999", "native_name": null, "head_office_country": "Croatia", "id": "ff0cfa2add0f430d8b3d980ee89d9571", "activity_industry_forums": "None", "contact_country": 54, "head_office_postbox": null, "networking": "FoodDrinksEurope (http://www.fooddrinkeurope.eu/)\r\nCroatian Employers' Association (http://www.hup.hr)\r\nEurocommerce (http://www.eurocommerce.eu/)", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Zagreb", "info_members": "", "head": "bd190039cd2f4b1cbd62892aa15bf7d1", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Trg Dra\u017eena Petrovi\u0107a 3 ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "High Level Forum for a Better Functioning Food Supply Chain\r\n\r\nEU Platform on Added Sugar\r\n\r\nRoadmap for Action of the Food Product Improvement", "registration_date": "2016-02-22T17:25:57.643000", "activity_relevant_comm": "None", "head_office_post_code": "10000", "goals": "The Agrokor Group is the largest privately owned company in Croatia and one of the leading regional companies with almost 60,000 employees and reported consolidated total revenues reaching HRK 49 billion. \r\n\r\nThe Agrokor Group's core businesses are the production and distribution of food and beverages and retail. Corporate members include Jamnica d.d., Croatia's largest producer of mineral water, Ledo d.d., Croatia\u2019s leading ice cream company, Zvijezda d.d., the biggest domestic producer of oil, margarine and mayonnaise, the largest Croatian meat industry PIK Vrbovec d.d., Croatia\u2019s leading agricultural and industrial company Belje, and leading largest retail chains Konzum d.d. and Poslovni sistemi Mercator d.d.\r\n\r\nThe leading positions of Agrokor's companies are reflected in their dominant market shares. Ledo dominates Croatia\u2019s ice cream market. Zvijezda enjoys the biggest share of the margarine and edible oils market, while Jamnica fronts Croatia\u2019s bottled water market. Konzum is Croatia\u2019s biggest retail chain and PIK Vrbovec is the leading meat company in the region. Since it was established 30 years ago, due to a clear business vision, a consistently applied company-wide strategy and well-planned investment projects, Agrokor has grown from a small family-owned company for the production and sale of flowers into the leading food industry and retail group in the region today. \r\n\r\nHaving achieved and strengthened its indisputable leadership in the domestic marketplace by staying ahead of changing market demands, Agrokor is now focused on making a step further in an attempt to realize its long-term strategic goal \u2013 becoming a major player throughout the region.", "members": 1, "last_update_date": "2016-02-22T17:26:43.984000", "members_fte": 0.25, "head_office_phone": "385 1 489 4111", "members_25": 1, "web_site_url": "http://www.agrokor.hr", "sub_category": 21, "activity_other": null, "name": "Agrokor d.d.", "created_at": "2016-02-23T02:22:42.269992", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff0cfa2add0f430d8b3d980ee89d9571", "identification_code": "656353020755-88", "legal_status": "Private Company", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "be_office_lat": null, "updated_at": "2016-07-09T02:07:53.609887", "entity": "f83b1695de83443980ec94b4dba61a34", "number_of_natural_persons": null, "legal": "88525dc2b8c54a48bd2ea6918cedf357", "native_name": null, "head_office_country": "Italy", "id": "ff091717a1254ae3876bed6b1042569b", "activity_industry_forums": "None", "contact_country": 108, "head_office_postbox": "1", "networking": null, "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Law firms", "other_code_of_conduct": null, "head_office_town": "Milano", "info_members": "", "head": "88525dc2b8c54a48bd2ea6918cedf357", "status": "active", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "Via Barozzi ", "be_office_post_code": "1000", "activity_inter_groups": "None", "acronym": "BE", "activity_eu_legislative": "Iniziative nel campo del diritto doganale e del diritto fiscale dell'Unione europea", "registration_date": "2016-06-03T18:28:30.515000", "activity_relevant_comm": "None", "head_office_post_code": "20122", "goals": "Studio legale", "members": 2, "last_update_date": "2016-07-08T10:47:26.957000", "members_fte": 0.5, "head_office_phone": "39 02771131", "be_office_town": "Bruxelles", "members_25": 2, "web_site_url": "http://www.belex.com", "sub_category": 12, "activity_other": null, "be_office_postbox": "40", "name": "Bonelli Erede Pappalardo", "be_office_street": "Square de Meeus ", "created_at": "2016-06-04T02:01:11.176016", "be_office_country": "Belgium", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff091717a1254ae3876bed6b1042569b", "identification_code": "205283422093-55", "legal_status": "Associazione", "members_100": null, "be_office_phone": "32 25520070", "be_office_lon": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 50.8693821, "updated_at": "2016-04-07T00:34:47.370083", "entity": "fb4895a76cd84605be4c79a469edd40d", "number_of_natural_persons": 0, "legal": "24e8db86b4ac4bdaa00596d0dfab2f6b", "native_name": null, "head_office_country": "Belgium", "id": "ff04fc2f7330408a9b773b91b8272c86", "activity_industry_forums": "None", "contact_country": 21, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Brussels", "info_members": "", "head": "5b5587fb2bd24c618e7063c1ad838edd", "status": "inactive", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Avenue des Olympiades 2 ", "activity_inter_groups": "None", "acronym": "EFQM", "activity_eu_legislative": "Horizon 2020- \"Peer Learning for Innovation Agencies\"\r\nEFQM Framework for Innovation Agencies\r\nEuropean Commission\r\nEASME/DG ENTR", "registration_date": "2015-03-10T10:24:10.228000", "activity_relevant_comm": "None", "head_office_post_code": "1140", "goals": "EFQM is a not-for-profit membership foundation based in Brussels, Belgium. With around 450 members covering more than 55 countries and 50 sectors, we provide a unique platform for organisations to learn from each other and improve performance. EFQM is the custodian of the EFQM Excellence Model, a business model which is helping over 30,000 organisations around the globe to strive for Sustainable Excellence.", "members": 1, "last_update_date": "2015-11-27T11:33:41.380000", "members_fte": 0.25, "head_office_phone": "32 27753511", "members_25": 1, "web_site_url": "http://www.efqm.org/", "sub_category": 31, "activity_other": null, "name": "EFQM European Foundation for Quality Management", "created_at": "2015-04-24T02:17:54.703255", "uri": "http://api.lobbyfacts.eu/api/1/representative/ff04fc2f7330408a9b773b91b8272c86", "identification_code": "409256516428-39", "legal_status": "PRIVATE FOUNDATION", "members_100": null, "head_office_lon": 4.4046716, "structure_members": "http://www.efqm.org/about-us/our-community/our-members", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-26T01:43:17.917951", "entity": "a8e3ccebeae64920945fdec5c3e833ff", "number_of_natural_persons": null, "legal": "72d60a38b9954adb9f237dbf2abc079d", "native_name": null, "head_office_country": "United States", "id": "fefa665da246486fa7b4d6f8fd7a3c5a", "activity_industry_forums": "None", "contact_country": 234, "head_office_postbox": null, "networking": "Intertanko, BIMCO", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Vienna", "info_members": "", "head": "2dcd8a7c3d234b9993a25c45420f6470", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "8619 Westwood Center Drive Suite 402 Suite 402", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "YCF Maritime promotes the EU shipping sector by offering EU flag solutions to shipowners which combine responsive and efficient customer service with in-depth technical expertise to ensure their vessels comply with EU and international regulatory requirements. \r\n\r\nYCF Maritime is a keen supporter of EU efforts to achieve a level global playing field for the European shipping industry. YCF Maritime is committed to the principle of a level-playing field within the EU, particularly regarding seafarer social security.\r\n\r\nKey organisations served by our group include EuroFlag Services, SeaNet Maritime Services, Liberian International Ship & Corporate Registry, EMA Manning Agency and EMTI.", "registration_date": "2015-04-17T10:16:37.333000", "activity_relevant_comm": "Concrete EU policy developments followed by YCF Maritime include the EU Review of Maritime Transport Strategy, Maritime Social Package, Recognized Organisations and Ship Emissions.", "head_office_post_code": "22182", "goals": "YCF Maritime is an international service provider with experience in a broad range of ocean shipping matters including vessel ownership, management and operations as well as seafarer training, the development of financial structures and regulatory administration and enforcement. Through its regional offices worldwide, YCF Maritime provides shipowners with comprehensive flag administration options on a global scale.", "members": 1, "last_update_date": "2016-03-24T16:27:57.827000", "members_fte": 0.25, "head_office_phone": "1703 2512406", "members_25": 1, "web_site_url": "http://www.ycfgroupllc.com/ycfmaritime.html", "sub_category": 21, "activity_other": null, "name": "YCF Maritime LLC", "created_at": "2015-04-24T02:21:04.322364", "uri": "http://api.lobbyfacts.eu/api/1/representative/fefa665da246486fa7b4d6f8fd7a3c5a", "identification_code": "128313216890-32", "legal_status": "Limited Liability Company", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-08T02:30:33.883110", "entity": "9a583b6ad41c49bcbb93db186b4408d3", "number_of_natural_persons": null, "legal": "2b89e910695c400a93951065b2a46a2a", "native_name": null, "head_office_country": "United Kingdom", "id": "feefe27755c74f6ca7df54e5d2b8b733", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "London", "info_members": "", "head": "361ba97fdc614463bc751fb184bc7238", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "160 Queen Victoria Street ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "Key financial markets EU initiatives impacting our clients and funds: \r\nEMIR (European Market Infrastructure Regulation), MiFIR (Markets in Financial Instruments Regulation), CRDIV (Capital Requirements Directive IV), \r\nCMU (Capital Markets Union), \r\nSFTR (The Securities Financing Transactions Regulation), \r\nMMFs (Money Market Fund Regulations), \r\nAIFMD (Alternative Investment Fund Managers Directive), \r\nUCITS (Undertakings for Collective Investments in Transferable Securities), and\r\nFTT (Financial Transaction Tax)", "registration_date": "2016-03-07T18:47:15.067000", "activity_relevant_comm": "None", "head_office_post_code": "EC4V 4LA", "goals": "Insight Investment is a leading global asset manager for institutional investors, particularly pension funds. Our investment management approach is focused on delivering solutions for our clients to provide greater certainty of financial outcome, and a large proportion of our assets is managed on behalf of pension funds in the form of liability risk management mandates, which positions us as one of the largest managers of European pension funds. We closely follow key financial market regulatory initiatives that would have an impact on our clients, and wish to positively engage in this process by providing a voice for European pension funds and other institutional clients.", "members": 1, "last_update_date": "2016-03-07T18:47:46.318000", "members_fte": 0.25, "head_office_phone": "44 207 163 0000", "members_25": 1, "web_site_url": "http://www.insightinvestment.com", "sub_category": 21, "activity_other": null, "name": "Insight Investment Management", "created_at": "2016-03-08T02:30:33.890643", "uri": "http://api.lobbyfacts.eu/api/1/representative/feefe27755c74f6ca7df54e5d2b8b733", "identification_code": "283171720947-78", "legal_status": "corporation", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 50.68241005, "updated_at": "2016-03-26T01:46:55.801398", "entity": "af42fc73d40e4bc4bef06e7482ee015d", "number_of_natural_persons": null, "legal": "a08398a128c243ac84d2f2bb92299987", "native_name": null, "head_office_country": "Germany", "id": "feed2f70644144b48b258eafe5efae0c", "activity_industry_forums": "None", "contact_country": 82, "head_office_postbox": null, "networking": "The BfT is a corporate member of the German Association of the Chemical Industry (VCI) and of IFAH (International Federation for Animal Health), the global association of the animal health industry and the European Federation of Animal Health Industry (IFAH Europe).", "members_75": null, "main_category": 2, "members_50": 2, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": "Verbandsinterner Kodex", "head_office_town": "Bonn", "info_members": "National association which follows and contributes to relevant european development through involvement in the work of the european sector association.", "head": "a08398a128c243ac84d2f2bb92299987", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Schwertbergerstr., 14 ", "activity_inter_groups": "None", "acronym": "BfT", "activity_eu_legislative": "Review Veterinary Medicines Regulation\r\nReview Medicated Feed Directive\r\nAnimal Health Regulation\r\n[ VERORDNUNG zur \u00c4nderung der Verordnung (EG) Nr. 726/2004 (Bundesrats-Drucksache 418/14) und den weiteren zugeh\u00f6rigen Vorschl\u00e4gen VERORDNUNG des Europ\u00e4ischen Parlamentes und des Rates \u00fcber die Herstellung, das Inverkehrbringen und die Verwendung von Arzneifuttermitteln sowie zur Aufhebung der Richtlinie 90/167/EWG des Rates (Bundesrats-Drucksache 417/14) und Vorschlag f\u00fcr eine VERORDNUNG des Europ\u00e4ischen Parlaments und des Rates \u00fcber Tierarzneimittel (Bundesrats-Drucksache 420/14) ].", "registration_date": "2014-08-14T18:07:37.568000", "activity_relevant_comm": "Quarterly newsletter Tiergesundheit im Blickpunkt", "head_office_post_code": "53177", "goals": "BfT represents the leading manufacturers of veterinary medicines in Germany.The BfT is a corporate member of the German Association of the Chemical Industry (VCI) and of IFAH (International Federation for Animal Health), the global association of the animal health industry and the European Federation of Animal Health Industry (IFAH Europe). Activities include representing members' interests with legislators, government agencies and professional organizations, supporting high standards of animal health and in the entire food production, sharing information with member companies about relevant latest developments, and informing the public about animal health issues and products.", "members": 3, "last_update_date": "2016-03-23T15:04:20.288000", "members_fte": 1.25, "head_office_phone": "49228 318296", "members_25": 1, "web_site_url": "http://www.bft-online.de", "sub_category": 25, "activity_other": null, "name": "Bundesverband fuer Tiergesundheit", "created_at": "2015-04-24T02:23:50.056410", "uri": "http://api.lobbyfacts.eu/api/1/representative/feed2f70644144b48b258eafe5efae0c", "identification_code": "369699114231-49", "legal_status": "e.V. (Eingetragener Verein)", "members_100": null, "head_office_lon": 7.15161428929912, "structure_members": "http://www.bft-online.de/mitglieder/", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-17T02:10:27.679053", "entity": "f67d92acd4d54ce192d076051a8ceed4", "number_of_natural_persons": null, "legal": "57e1b8f4c48d4974afcbf9d5727c3732", "native_name": null, "head_office_country": "Denmark", "id": "feec5f95637641aa83f9fa5076cd259d", "activity_industry_forums": "None", "contact_country": 59, "head_office_postbox": null, "networking": "Member of the EURELECTRIC (delegated through the Danish Energy Association)", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "Frederiksberg", "info_members": "", "head": "57e1b8f4c48d4974afcbf9d5727c3732", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Vodroffsvej 59, Frederiksberg C ", "activity_inter_groups": "None", "acronym": "DEA", "activity_eu_legislative": "The Alternative Fuels Infrastructure Directive\r\nCO2 Emisssions from Passenger Cars\r\nClean Power for Transport Initiative\r\nWLTP\r\nJuncker Investment Plan", "registration_date": "2014-11-04T08:35:59.078000", "activity_relevant_comm": "None", "head_office_post_code": "DK-1900", "goals": "The Danish Electric Vehicle Alliance works to promote a better political environment for mass roll out of Electric Vehicles, namely battery powered cars and plug in hybrid electric cars, both in Denmark and the EU.\r\n\r\nWe work through providing political incentives for first movers, promoting infrastructure for EV's and educating the public of the possibilities provided by the new electric technology.\r\n\r\nWe are (as of March 2016) four people in an legally autonomous organisation, physically situated within the Danish Energy Association. We represent 47 member companies, Danish and foreign, along every link of the EV value chain.", "members": 1, "last_update_date": "2016-03-10T11:11:03.952000", "members_fte": 0.25, "head_office_phone": "0045 35300491", "members_25": 1, "web_site_url": "http://www.danskelbilalliance.dk", "sub_category": 25, "activity_other": null, "name": "Danish Electric Vehicle Alliance", "created_at": "2015-04-24T02:30:39.870639", "uri": "http://api.lobbyfacts.eu/api/1/representative/feec5f95637641aa83f9fa5076cd259d", "identification_code": "583653114856-56", "legal_status": "Dansk Elbil Alliance", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2015-07-29T23:29:35.253216", "entity": "403f6e713ed24f529b2e77e909a8e56f", "number_of_natural_persons": 13, "legal": "15ce760f485642eaa70fe3e1e639c017", "native_name": null, "head_office_country": "Italy", "id": "fee73f7916f94c36b2f90c4e1b294a51", "activity_industry_forums": "None", "contact_country": 108, "head_office_postbox": null, "networking": "UNFCCC\r\nGEF\r\nECOSOC of United Nations\r\nUNODC", "members_75": null, "main_category": 3, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "casoria", "info_members": "", "head": "15ce760f485642eaa70fe3e1e639c017", "status": "inactive", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Via E. Fermi, 18 ", "activity_inter_groups": "None", "acronym": "APK", "activity_eu_legislative": "Attivita nel settore dell'ambiente a livello comunitario", "registration_date": "2012-09-29T23:51:11.196000", "activity_relevant_comm": "None", "head_office_post_code": "80026", "goals": "Protection of the environment", "members": 2, "last_update_date": "2015-02-05T18:27:53.562000", "members_fte": 2.0, "head_office_phone": "377 9430541", "members_25": null, "web_site_url": null, "sub_category": 31, "activity_other": "Attivita'di divugazione delle politiche comunitarie nel campo dell'ambiente", "name": "Amigos do Protocolo de Kyoto", "created_at": "2015-04-24T02:08:08.971885", "uri": "http://api.lobbyfacts.eu/api/1/representative/fee73f7916f94c36b2f90c4e1b294a51", "identification_code": "82132839724-37", "legal_status": "ONLUS", "members_100": 2, "head_office_lon": null, "structure_members": "APK Italy(4),\r\nAPK Poland(3),\r\nAPK Hungary(2),\r\nAPK Brazil(4)", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-05-25T01:22:39.194553", "entity": "2188e813114a4dd6ad7e3e6e101a2b76", "number_of_natural_persons": null, "legal": "2d44c0cba0794197ac8315978742b9b5", "native_name": null, "head_office_country": "Netherlands", "id": "fedf6bda46184c118b81b1950746a169", "activity_industry_forums": "None", "contact_country": 155, "head_office_postbox": null, "networking": null, "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Bruinehaar", "info_members": "Taak bovenop reguliere werkzaamheden.", "head": "2d44c0cba0794197ac8315978742b9b5", "status": "inactive", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Driehoeksweg 9 ", "activity_inter_groups": "None", "acronym": "Pl. EDV", "activity_eu_legislative": "N2000 dossier en Vogel- en habitatrichtlijn.", "registration_date": "2015-05-20T21:53:23.653000", "activity_relevant_comm": "Zienswijzen insturen, inspraakprocedure`s benutten,\r\npolitici en pers informeren, contacten onderhouden en informatie uitwisselen met relevante organisatie`s.", "head_office_post_code": "7675 TA", "goals": "Het Platform Engbertsdijksvenen (EDV) behartigd de belangen van haar leden die grenzen aan het N2000 gebied het Engbertsdijksvenen.", "members": 4, "last_update_date": "2015-05-20T22:07:08.277000", "members_fte": 1.0, "head_office_phone": "31 620366362", "members_25": 4, "web_site_url": null, "sub_category": 21, "activity_other": null, "name": "Platform Engbertsdijksvenen", "created_at": "2015-05-24T21:45:42.617388", "uri": "http://api.lobbyfacts.eu/api/1/representative/fedf6bda46184c118b81b1950746a169", "identification_code": "020890017437-27", "legal_status": "geen", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-08-18T02:05:44.790468", "entity": "9e06d7fb83cb44588093ab4606de4b74", "number_of_natural_persons": null, "legal": "02b132016c10414581d14ba40423cb57", "native_name": null, "head_office_country": "Poland", "id": "fed7ebf4abe64ddaa22834b1e4776fd7", "activity_industry_forums": "None", "contact_country": 176, "head_office_postbox": null, "networking": "European Rail Freight Association http://www.erfarail.eu/home.asp", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "IGTL jest cz\u0142onkiem European Rail Freight Association, kt\u00f3re jest podmiotem wsp\u00f3\u0142pracuj\u0105cym z KE", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "Warszawa", "info_members": "", "head": "02b132016c10414581d14ba40423cb57", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Aleje Jerozolimskie 125/127 ", "activity_inter_groups": "None", "acronym": "IGTL", "activity_eu_legislative": "polityka transportowa, polityka sp\u00f3jno\u015bci, czwarty pakiet kolejowy, TSI, interoperacyjno\u015b\u0107, jednolity europejski obszar kolejowy, sie\u0107 TEN-T, rozporz\u0105dzenie 913/2010 RFC, CEF, RID, CIM,", "registration_date": "2016-08-17T13:23:06.070000", "activity_relevant_comm": "IGTL wsp\u00f3\u0142pracuje z administracj\u0105 publiczn\u0105 (ministerstwa, Urz\u0105d Transportu Kolejowego, Transportowy Doz\u00f3r Techniczny), reprezentuj\u0105c stanowisko bran\u017cy w szeregu dyskusji na temat regulacji dotycz\u0105cych transportu kolejowego - jest podmiotem bior\u0105cym udzia\u0142 w konsultacjach publicznych w procesie legislacyjnym (ustawy, rozporz\u0105dzenia) oraz dokument\u00f3w i program\u00f3w rz\u0105dowych. IGTL wsp\u00f3\u0142pracuje z narodowym zarz\u0105dc\u0105 infrastruktury, m.in. poprzez udzia\u0142 w Forum Inwestycyjnym (Prezes Izby jest cz\u0142onkiem Prezydium Forum). Izba prowadzi dzia\u0142alno\u015b\u0107 szkoleniow\u0105 dla cz\u0142onk\u00f3w (seminaria, konferencje), obejmuje patronatem najwa\u017cniejsze wydarzenia kolejowe w Polsce i udziela merytorycznego wsparcia poprzez publikacj\u0119 stanowisk i udzia\u0142 przedstawicieli Izby jako prelegent\u00f3w, panelist\u00f3w, itd. Izba prowadzi r\u00f3wnie\u017c dzia\u0142alno\u015bci wydawnicz\u0105 oraz wsp\u00f3\u0142pracuje z bran\u017cowymi wydawcami i pras\u0105, dostarczaj\u0105c stanowisk merytorycznych do publikacji. Izba wsp\u00f3\u0142pracuje z innymi organizacjami bran\u017cowymi w zakresie opisanym powy\u017cej.", "head_office_post_code": "02-017", "goals": "Izba Gospodarcza Transportu L\u0105dowego (Land Transport Chamber of Commerce) jest organizacj\u0105 samorz\u0105du gospodarczego dzia\u0142aj\u0105c\u0105 od 1995r. na mocy Ustawy z 30 maja 1989r. o izbach gospodarczych. Izba pe\u0142ni rol\u0119 reprezentanta firm zwi\u0105zanych z transportem kolejowym wobec administracji pa\u0144stwowej oraz r\u00f3\u017cnego rodzaju organizacji krajowych i zagranicznych maj\u0105cych wp\u0142yw na dzia\u0142alno\u015b\u0107 tych przedsi\u0119biorstw. \r\nIzba skupia kilkadziesi\u0105t przedsi\u0119biorstw z ca\u0142ego kraju zwi\u0105zanych z bran\u017c\u0105 kolejow\u0105. Celem Izby jest przede wszystkim ochrona interes\u00f3w firm oraz wyst\u0119powanie do organ\u00f3w administracji pa\u0144stwowej i samorz\u0105dowej z wnioskami i opiniami w zakresie regulacji dotycz\u0105cych szeroko rozumianego transportu kolejowego.\r\nIGTL u\u0142atwia swoim cz\u0142onkom dost\u0119p do wiedzy o aktualnych procesach gospodarczych, szczeg\u00f3lnie tych dotycz\u0105cych transportu i infrastruktury kolejowej. Wsp\u00f3\u0142praca z Izb\u0105 daje cz\u0142onkom mo\u017cliwo\u015b\u0107 bezpo\u015bredniego wp\u0142ywu na kszta\u0142towanie warunk\u00f3w dzia\u0142alno\u015bci i rozwoju transportu kolejowego, a tak\u017ce integruje bran\u017c\u0119 kolejow\u0105.\r\nW IGTL funkcjonuj\u0105 trzy sekcje bran\u017cowe: Przewo\u017anik\u00f3w Kolejowych, Wagon\u00f3w i Spedycji, Budownictwa Kolejowego \r\nCz\u0142onkiem Izby mo\u017ce zosta\u0107 podmiot gospodarczy prowadz\u0105cy dzia\u0142alno\u015b\u0107 gospodarcz\u0105 zgodnie z zasadami etyki zawodowej, z wy\u0142\u0105czeniem os\u00f3b fizycznych prowadz\u0105cych tak\u0105 dzia\u0142alno\u015b\u0107 jako zaj\u0119cie uboczne.", "members": 8, "last_update_date": "2016-08-17T13:23:42.060000", "members_fte": 2.75, "head_office_phone": "48 6540942", "members_25": 7, "web_site_url": "http://www.igtl.pl", "sub_category": 25, "activity_other": null, "name": "Izba Gospodarcza Transportu L\u0105dowego", "created_at": "2016-08-18T02:05:44.797758", "uri": "http://api.lobbyfacts.eu/api/1/representative/fed7ebf4abe64ddaa22834b1e4776fd7", "identification_code": "501998723038-69", "legal_status": "izba gospodarcza", "members_100": 1, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2015-12-01T02:42:19.420436", "entity": "7abf0809a837474485cfcc035b933d5b", "number_of_natural_persons": null, "legal": "5eb772ccd2e04cde9ae9ba82a2b4f16f", "native_name": null, "head_office_country": "Italy", "id": "fed17c17924045649b1e30abb8afd3f3", "activity_industry_forums": "None", "contact_country": 108, "head_office_postbox": null, "networking": "U.C.E.E. Unione Camere Esperti Europei\r\nwww.ucee.be\r\n\r\nNAFOP National Association Fee Only Planner\r\nwww.nafop.org\r\n\r\nLAPET - Associazione Nazionale Tributaristi\r\nwww.iltributaristalapet.it", "members_75": 1, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Self-employed consultants", "other_code_of_conduct": null, "head_office_town": "Laurenzana", "info_members": "Dott. Giuseppe Lettini", "head": "5eb772ccd2e04cde9ae9ba82a2b4f16f", "status": "active", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "III\u00b0 Vico Vittorio Emanuele 4 ", "activity_inter_groups": "None", "acronym": "Studio Lettini", "activity_eu_legislative": "FINANZIAMENTI EUROPEI\r\nFINANZIAMENTI NAZIONALI\r\nFINANZIAMENTI REGIONALI\r\nINTERNAZIONALIZZAZIONE\r\nSTART UP IMPRESE\r\n\r\nLe attivit\u00e0 che lo studio segue riguardano principalmente il supporto ai clienti nella presentazione di domande di finanziamento per i programmi Horizon 2020, Cosme, Creative Europe.\r\nLa normativa finanziamenti agevolati a favore di piccole medie e grandi imprese coinvolge tutti i settori, da quello industriale a quello turistico, commercio, servizi, agricoltura.\r\n\r\nL\u2019obiettivo \u00e8 lo sviluppo dell\u2019imprenditorialit\u00e0 come avvio d\u2019impresa e/o sviluppo d\u2019impresa", "registration_date": "2015-11-25T13:36:23.400000", "activity_relevant_comm": "Europrogetti e comunicazioni inerenti i bandi", "head_office_post_code": "85014", "goals": "Lo Studio Lettini, offre un servizio di consulenza altamente specializzato nel mondo della finanza pubblica e del controllo di gestione individuando le migliori soluzioni per le innumerevoli necessit\u00e0 finanziarie di ogni tipo di imprese, ente, ecc. Lo studio di consulenza permette e offre soluzioni ed assistenza all\u2019imprenditore o di chi ha un\u2019idea imprenditoriale, attraverso una attenta analisi delle esigenze aziendali, l\u2019individuazione del tipo di finanziamento ottimale, la definizione delle opportune soluzioni organizzative, la creazione del sistema di controllo interno, la compilazione del relativo dossier per una istruttoria in linea con i requisiti legislativi richiesti, \u00e8 sufficiente programmare un qualsiasi intervento aziendale perch\u00e8 l\u2019intervento di Studio Lettini possa far emergere sostanziali utilit\u00e0 per l\u2019impresa.", "members": 1, "last_update_date": "2015-11-30T17:01:26.337000", "members_fte": 0.75, "head_office_phone": "39 3899873276", "members_25": null, "web_site_url": "http://www.studiolettini.it", "sub_category": 13, "activity_other": "Consulenza in europrogettazione finalizzata al successo nella partecipazione ai bandi europei nella nuova programmazione 2014-2020.", "name": "Lettini Giuseppe", "created_at": "2015-12-01T02:42:19.427576", "uri": "http://api.lobbyfacts.eu/api/1/representative/fed17c17924045649b1e30abb8afd3f3", "identification_code": "731027919621-04", "legal_status": "Consulente autonomo", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-07-29T01:38:12.539457", "entity": "a402743e5808426db003a7f1948dbe99", "number_of_natural_persons": null, "legal": "1301c3d6c89347b1ab9fc84c383e847e", "native_name": null, "head_office_country": "Netherlands", "id": "fecde2aeabb843f4a8a55a4b3b92de50", "activity_industry_forums": "None", "contact_country": 155, "head_office_postbox": null, "networking": "cumula", "members_75": null, "main_category": 2, "members_50": 1, "activity_expert_groups": "None", "sub_category_title": "Companies & groups", "other_code_of_conduct": null, "head_office_town": "Appingedam", "info_members": "", "head": "1301c3d6c89347b1ab9fc84c383e847e", "status": "inactive", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "1ste Industrieweg 16 ", "activity_inter_groups": "None", "acronym": "HW", "activity_eu_legislative": "Klimaat onderwerken, paludicultuur, natuurbeheer", "registration_date": "2015-07-27T17:07:14.809000", "activity_relevant_comm": "None", "head_office_post_code": "9902 AM", "goals": "Wij zijn een bedrijf met als core business the oogst van biomassa en een machinefabriek en we gaan richting een bedrijf in de biobased economie. In die zin bestaan we uit een bedrijf dat een loonbedrijf heeft in de natte gebieden, een machine fabriek en een consultancy.", "members": 3, "last_update_date": "2015-07-27T17:35:38.170000", "members_fte": 1.75, "head_office_phone": "316 36109878", "members_25": 1, "web_site_url": "http://hanzewetlands.com", "sub_category": 21, "activity_other": null, "name": "Hanze Wetlands", "created_at": "2015-07-28T01:16:50.660106", "uri": "http://api.lobbyfacts.eu/api/1/representative/fecde2aeabb843f4a8a55a4b3b92de50", "identification_code": "200438718349-72", "legal_status": "BV", "members_100": 1, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": 50.8248068, "updated_at": "2016-03-26T01:19:06.631263", "entity": "e0bb8dab8e9e4bec9a05f9c6a9244b53", "number_of_natural_persons": 0, "legal": "3eba6f061ca649d0a4046654ee392dfe", "native_name": null, "head_office_country": "Belgium", "id": "fec76a9f6e224986b3edb9b89e8afad3", "activity_industry_forums": "None", "contact_country": 21, "head_office_postbox": null, "networking": "WFTO-Europe is one of the five regional branches of the World Fair Trade Organization global network, the other four being: WFTO-Africa/COFTA (the Cooperation for Fair Trade in Africa), WFTO-Asia (World Fair Trade Organization - Asia), WFTO-LA (World Fair Trade Organization \u2013 Latin America) and WFTO Pacific Rim. Together, the five WFTO regional networks come together as regional chapters to represent over 450 members within 75 countries worldwide, that are committed 100% to Fair Trade and its principles.\r\n\r\nFor a detailed view on the WFTO global network, its members and structure, please visit WFTO global website at: http://www.wfto.com/ \r\n\r\nAt European level, WFTO-Europe is a member organization of the Fair Trade Advocacy Office (FTAO) in Brussels. The FTAO is a joint initiative of World Fair Trade Organization \u2013 Europe (WFTO-Europe), Fairtrade International (FLO) and the European Fair Trade Association (EFTA). Through these three networks the FTAO represents an estimate of 2.5 million Fair Trade producers and workers from 70 countries, 24 labelling initiatives, over 500 specialised Fair Trade importers, 4.000 World Shops and more than 100.000 volunteers. The Fair Trade Advocacy Office speaks out for Fair Trade and trade justice with the aim to improve the livelihoods of marginalised producers and workers, especially in the South. \r\n\r\nFor a detailed view on the FTAO\u2019s activities, please visit its website at: http://www.fairtrade-advocacy.org/\r\n\r\nWFTO-Europe is a member of the European inter-network of ethical and responsible initiatives (IRIS, www.irisnetwork.eu), a network create by European networks and organisations, aimed at promoting synergies between them, in order to implement solidarity economy initiatives and to fight against poverty and social exclusion, through a sustainable development and responsible economic approach. IRIS represents different families of responsible economic initiatives: responsible finance (FEBEA, INAISE), Fair Trade (WFTO-Europe), responsible consumption (ASECO), local partnerships between farmers and consumers (URGENCI) and Social Integration Enterprises (ENSIE), with the participation and support of institutional partners (Council of Europe and the Trento Autonomous Province, Italy).\r\n\r\nWFTO-Europe is also a member of the \"Federation of European & International associations based in Belgium\" (FAIB).", "members_75": null, "main_category": 3, "members_50": 1, "activity_expert_groups": "None", "sub_category_title": "Non-governmental organisations, platforms and networks and similar", "other_code_of_conduct": null, "head_office_town": "Bruxelles", "info_members": "", "head": "3eba6f061ca649d0a4046654ee392dfe", "status": "active", "main_category_title": "III - Non-governmental organisations", "head_office_street": "Rue Washington, 40 ", "activity_inter_groups": "None", "acronym": "WFTO-Europe", "activity_eu_legislative": "WFTO-Europe has been following the EU directive on public procurement as well as the main communication and initiatives related to Fair Trade via the Fair Trade Advocacy Office (FTAO).", "registration_date": "2012-12-18T15:24:10.203000", "activity_relevant_comm": "WFTO-Europe is currently involved in one project at European level: \"Food Smart Cities for Development\".", "head_office_post_code": "1050", "goals": "WFTO-Europe, formerly known as IFAT Europe (International Federation for Alternative Trade), represents the European branch of the World Fair Trade Organization (WFTO). It is currently formed by 74 members from 15 countries, amongst them Fair Trade Organizations, Fair Trade Networks and Support Organizations.\r\n\r\nWFTO-Europe stands by WFTO global network\u2019s vision and mission.\r\n\r\nWFTO\u2019s vision: a world in which trade structures and practices have been transformed to work in favour of the poor and promote sustainable development and justice.\r\n \r\nWFTO\u2019s mission: to enable producers to improve their livelihoods and communities through Fair Trade. WFTO will advocate for Fair Trade, ensuring producer voices are heard. The interests of producers, especially small farmers and artisans, should be the main focus in all the policies, governance, structures and decision-making within the World Fair Trade Organization.\r\n\r\nIn its status of regional branch, WFTO-Europe has four strategic aims: \r\n\r\n1.\tSupport the growth and consolidation of WFTO global network.\r\n2.\tBe the reference for Fair Trade in Europe, its representative organ and its voice.\r\n3.\tProtect the noble values of Fair Trade and the 100% commitment to it.\r\n4.\tSupport Fair Trade policies and support the legality of the office.\r\n\r\nIn this respect, one of the most important initiatives of WFTO-Europe is that of facilitating a framework for producer assistance and product development, by:\r\n\r\n- Supporting the monitoring process and WFTO system;\r\n- Serving as a facilitator between members who want to work on producer assistance and product development in a structured and articulated way. Also by facilitating bilateral and multilateral work between them;\r\n- Facilitating and bridging other initiatives and actors working on these key issues (WFTO global and other regional offices, Fair Trade Organizations, other civil society organisations) and informing southern Fair Trade partners on market tendencies in a structured and articulated way. \r\n\r\n\r\nWFTO global network\u2019s aims at large, to which WFTO-Europe shall contribute from a regional level, are to improve the livelihoods of marginalized producers and workers, especially in the South. To change unfair structures of international trade, mainly by means of Fair Trade, to improve and co-ordinate the co-operation of its member organizations and to promote the interests of and provide services to its member organizations and individuals (Source: The Constitution of the World Fair Trade Organization)", "members": 2, "last_update_date": "2016-03-23T17:16:01.371000", "members_fte": 1.5, "head_office_phone": "32 2 640 63 86", "members_25": null, "web_site_url": "http://www.wfto-europe.org", "sub_category": 31, "activity_other": "Project with local authorities", "name": "World Fair Trade Organization - Europe", "created_at": "2015-04-24T01:57:44.867858", "uri": "http://api.lobbyfacts.eu/api/1/representative/fec76a9f6e224986b3edb9b89e8afad3", "identification_code": "725848610338-68", "legal_status": "ASBL - Association Sans But Lucratif (Non-profit association)", "members_100": 1, "head_office_lon": 4.36371042912679, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2015-10-30T01:56:56.246954", "entity": "7b46510f154947128c02d05bd79a3358", "number_of_natural_persons": null, "legal": "a42346118a234821a8de93818be55c95", "native_name": null, "head_office_country": "Switzerland", "id": "fec607c127414c259cbf2f7f86eb041c", "activity_industry_forums": "None", "contact_country": 215, "head_office_postbox": "CP246", "networking": null, "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "geneve", "info_members": "", "head": "4d7fa8f59ace457388b82ac625f9ef2d", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "maison de la paix, WBCSD chemin Eug\u00e8ne Rigot 2 chemin Eug\u00e8ne Rigot 2", "activity_inter_groups": "None", "acronym": "WBCSD", "activity_eu_legislative": "- Climate Change Strategy\r\n- CSR Strategy\r\n- Biodiversity Strategy\r\n- Sustainability Strategy\r\n- Water and Food and Forest Strategy\r\n- Sustainable City Strategy\r\n- Mobility Strategy", "registration_date": "2015-10-22T14:38:03.288000", "activity_relevant_comm": "WBCSD is directly involved with the EU Commission on above topics via direct meetings and workshops. \r\nIndirectly the organisation is represented by associated organisations such as Econsense or IETA.\r\nIndirectly the organisation is also represented by its about 200 member companies.", "head_office_post_code": "1211", "goals": "The World Business Council for Sustainable Development (WBCSD) is a CEO-led organization of forward-thinking companies that galvanizes the global business community to create a sustainable future for business, society and the environment. Through its members, the Council applies its respected thought leadership and effective advocacy to generate constructive solutions and take shared action to drive business action on sustainability in the coming decade and beyond. The WBCSD aims to be the leading voice of business that will support companies in scaling up true value-added business solutions and in creating the conditions where more sustainable companies will succeed and be recognized. \r\n\r\nMembers work together across sectors, geographies and value chains to explore, develop and scale up business solutions to address the world\u2019s most pressing sustainability challenges. Through our work to change the rules of the game and drive measurable impact, WBCSD is emerging as the leading and most compelling sustainable development business voice with multilateral institutions such as the United Nations, World Bank, UNFCCC, as well as with global platforms like the UN Climate Summit and COP negotiations. \r\n\r\nThe WBCSD is unique because its output is developed and road tested by its members. Its comprehensive work program enables it to cover all aspects of sustainable development in business. To deal effectively with all issues the work program is divided into six Action2020 Clusters , sector and value chain projects, systems solutions and capacity building.\r\n\r\nWe also benefit from a Global Network of 65+ independent national and regional business councils and partner organizations, involving thousands of business leaders, two-thirds in developing countries and emerging economies.", "members": 1, "last_update_date": "2015-10-29T16:41:14.433000", "members_fte": 0.25, "head_office_phone": "41 228393100", "members_25": 1, "web_site_url": "http://www.wbcsd.org/home.aspx", "sub_category": 25, "activity_other": "WBCSD as a non-profit organisation represents the business voice of it's members based on solid scientific evidence to enhance and facilitate the understanding and direction setting between companies and policy making towards a sustainable society. It is important for policy makers to fully understand the actual potential of advanced business solutions as these are crucial for the successful implementation of policies and strategies mentioned above.", "name": "World Business Council For Sustainable Development", "created_at": "2015-10-23T00:55:45.123574", "uri": "http://api.lobbyfacts.eu/api/1/representative/fec607c127414c259cbf2f7f86eb041c", "identification_code": "074000219282-17", "legal_status": "association", "members_100": null, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-03-05T02:28:51.723088", "entity": "7252c50b894d41e9bf6079782137f31f", "number_of_natural_persons": null, "legal": "7cf0eca1988e48ee9021a79332f3f7f9", "native_name": null, "head_office_country": "Belgium", "id": "fec5815bf76348d69521bc170db3d77c", "activity_industry_forums": "None", "contact_country": 21, "head_office_postbox": null, "networking": "Ei ole.", "members_75": null, "main_category": 1, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Professional consultancies", "other_code_of_conduct": null, "head_office_town": "Bruxelles", "info_members": "", "head": "7cf0eca1988e48ee9021a79332f3f7f9", "status": "active", "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", "head_office_street": "Chauss\u00e9e de Charleroi 143, box 3 ", "activity_inter_groups": "None", "acronym": null, "activity_eu_legislative": "S\u00e4hk\u00f6isen viestinn\u00e4n s\u00e4\u00e4ntely, digitaaliset sis\u00e4markkinat.", "registration_date": "2016-03-04T14:27:41.702000", "activity_relevant_comm": "J\u00e4rjest\u00e4mme tapaamisia ja harjoitamme tiedonvaihtoa EU-vaikuttajien ja s\u00e4hk\u00f6isen viestinn\u00e4n alan yrityksen kesken.", "head_office_post_code": "B-1060", "goals": "Petri Lahesmaa Consulting on EU-vaikuttajaviestint\u00e4\u00e4n erikoistunut yritys. Toimialaamme on EU-vaikuttaminen, s\u00e4hk\u00f6isen viestinn\u00e4n s\u00e4\u00e4ntelyasiat ja EU-journalismi. Petri Lahesmaalla on yli 16 vuoden kokemus EU-vaikuttamisesta sek\u00e4 Brysseliss\u00e4 ett\u00e4 Suomessa.", "members": 1, "last_update_date": "2016-03-04T14:35:08.052000", "members_fte": 0.25, "head_office_phone": "32 0476909496", "members_25": 1, "web_site_url": null, "sub_category": 11, "activity_other": null, "name": "Petri Lahesmaa Consulting", "created_at": "2016-03-05T02:28:51.726617", "uri": "http://api.lobbyfacts.eu/api/1/representative/fec5815bf76348d69521bc170db3d77c", "identification_code": "344894120925-87", "legal_status": "Une entreprise personne physique", "members_100": null, "head_office_lon": null, "structure_members": "Ei ole.", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "be_office_lat": 50.84178695, "updated_at": "2016-03-09T00:56:50.059467", "entity": "44f5ad8112524b51a08db529e8753272", "number_of_natural_persons": null, "legal": "f4a66136f5634ec68be50672e3f2dfa4", "native_name": null, "head_office_country": "Denmark", "id": "feac8ce68d3142848d501f1bf11bf46a", "activity_industry_forums": "None", "contact_country": 59, "head_office_postbox": null, "networking": "European Energy Forum http://www.europeanenergyforum.eu/\r\nEurelectric http://www.eurelectric.org/\r\n\r\nThe Danish Energy Association also participates in a number of informal networks in Brussels.", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "Frederiksberg C", "info_members": "", "head": "5bde983ce5cd4a8ea7d87b79ece7bbc0", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "Rosen\u00f8rns All\u00e9, 9 ", "be_office_post_code": "1040", "activity_inter_groups": "None", "acronym": "DEA", "activity_eu_legislative": "Energy Union \r\n2030 governance\r\nETS reform\r\nRetail Energy Market: Action Plan\r\nCapacity Mechanisms", "registration_date": "2008-09-10T13:21:30.828000", "activity_relevant_comm": "None", "head_office_post_code": "1970", "goals": "The Danish Energy Association (Dansk Energi) is a commercial and professional organisation for Danish energy companies. It is managed and financed by its member companies, mainly the electricity companies, and works to secure for them the most free and favourable conditions for competition in order to ensure development, growth and business friendly environment in Denmark.\r\n\r\nThe Danish Energy Association represents the interests of its member companies and thus conducts regular contacts with government, authorities etc. nationally and within the EU.", "members": 2, "last_update_date": "2016-03-08T09:35:15.467000", "members_fte": 2.0, "head_office_phone": "45 35300400", "be_office_town": "Bruxelles", "members_25": null, "web_site_url": "http://www.danskenergi.dk", "sub_category": 25, "activity_other": "Energy, climate, transport and environmental policy.", "be_office_postbox": null, "name": "Danish Energy Association / Dansk Energi", "be_office_street": "Rue de la Loi 227 ", "created_at": "2015-04-24T01:47:43.770790", "be_office_country": "Belgium", "uri": "http://api.lobbyfacts.eu/api/1/representative/feac8ce68d3142848d501f1bf11bf46a", "identification_code": "1733114388-50", "legal_status": "Association", "members_100": 2, "be_office_phone": "32 491 25 30 23", "be_office_lon": 4.38526824209953, "head_office_lon": null, "structure_members": "", "code_of_conduct": "European Commission's code of conduct for interest representative"}, {"activity_consult_committees": "None", "activity_high_level_groups": "None", "head_office_lat": null, "updated_at": "2016-07-01T01:37:23.590560", "entity": "3ed6121ae7b54e19bcc1ce7371a0c218", "number_of_natural_persons": null, "legal": "9780c60b13234d82b65e1b32c10bbc08", "native_name": null, "head_office_country": "United Kingdom", "id": "fea393c1edda4541847f16497b8d35a8", "activity_industry_forums": "None", "contact_country": 233, "head_office_postbox": null, "networking": "ENA is a member of EURELECTRIC, GEODE and Eurogas.", "members_75": null, "main_category": 2, "members_50": null, "activity_expert_groups": "None", "sub_category_title": "Trade and business organisations", "other_code_of_conduct": null, "head_office_town": "London", "info_members": "", "head": "f5f91b124a08449ebefe428af0978bcf", "status": "active", "main_category_title": "II - In-house lobbyists and trade/professional associations", "head_office_street": "6th Floor Dean Bradley House Dean Bradley House", "activity_inter_groups": "None", "acronym": "ENA", "activity_eu_legislative": "Single Energy Market and Future Market Design\r\nDSO/TSO Interface\r\nFlexibility services\r\nNetwork Tariffs\r\nInnovation\r\nFuture role for Gas\r\n2030 climate and energy framework\r\nRenewable Sources of Energy\r\nEnergy Efficiency\r\nLow carbon transport", "registration_date": "2015-07-22T15:58:48.209000", "activity_relevant_comm": "None", "head_office_post_code": "SW1P 2AF", "goals": "Energy Networks Association (ENA) is the voice of the networks, representing the electricity and gas transmission and distribution network operators in the UK and Ireland. Our members are diverse, from major international companies to independent network operators. \r\nENA is actively engaged with government, regulators and the EU Commission as well as producing a wide range of industry standards. The impact of regulation, the influence of European legislation, the challenge of new technologies and the importance of securing our energy future, all against the background of national low carbon targets, are just some issues ENA deals with.", "members": 1, "last_update_date": "2016-06-30T15:09:08.535000", "members_fte": 1.0, "head_office_phone": "44 02077065131", "members_25": null, "web_site_url": "http://www.energynetworks.org", "sub_category": 25, "activity_other": null, "name": "Energy Networks Association", "created_at": "2015-07-23T01:03:14.242168", "uri": "http://api.lobbyfacts.eu/api/1/representative/fea393c1edda4541847f16497b8d35a8", "identification_code": "247299118284-24", "legal_status": "Private Limited Company", "members_100": 1, "head_office_lon": null, "structure_members": "http://www.energynetworks.org/", "code_of_conduct": "European Commission's code of conduct for interest representative"}], "next": "http://api.lobbyfacts.eu/api/1/representative?limit=50&offset=50", "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 12129, + "facets": {}, + "results": [ + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-04-21T00:36:51.167919Z", + "entity": "f68eebed3ca14d66aeb9be6e5680cdcd", + "number_of_natural_persons": null, + "legal": "8e8b73cc70d241e5bb32c8907cd042ba", + "native_name": null, + "head_office_country": "Denmark", + "id": "fffebd3272294bb0a38d0347b0e0c4df", + "activity_industry_forums": "None", + "contact_country": 59, + "head_office_postbox": null, + "networking": "The European Federation of Building and Woodworkers (EFBWW) is the European Industry Federation for the construction industry, the building materials industry, the wood and furniture industry and the forestry industry. The EFBWW has 76 affiliated unions in 34 countries and represents a total of 2,000,000 members, see\r\nhttp://www.efbww.org/default.asp?Language=EN", + "members_75": null, + "main_category": 2, + "members_50": 4, + "activity_expert_groups": "None", + "sub_category_title": "Trade unions and professional associations", + "other_code_of_conduct": null, + "head_office_town": "K\u00f8benhavn V", + "info_members": "", + "head": "8e8b73cc70d241e5bb32c8907cd042ba", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Kampmannsgade 4, 70300300 ", + "activity_inter_groups": "None", + "acronym": "BAT", + "activity_eu_legislative": "Policies in the fields of the construction industry, employment and labour market, posting of workers, migrant workers, energy savings, works councils, occupational health and safety", + "registration_date": "2012-09-19T14:07:17.947000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "1790", + "goals": "BAT coordinates and represents the member organisations' (3F, Blik & R\u00f8rarbejderforbundet, El-forbundet, HK/Privat, Malerforbundet, Dansk Metal og Teknisk Landsforbund) interests on working environment, co-determination, AS, Works Councils and EWC, industrial policy, housing policy and labour market polity , international work, posted workers, foreign companies and Greenland.", + "members": 4, + "last_update_date": "2016-04-12T08:34:24.029000Z", + "members_fte": 2.0, + "head_office_phone": "45 70300300", + "members_25": null, + "web_site_url": "http://www.batkartellet.dk", + "sub_category": 26, + "activity_other": "BAT coordinates the member organisations' interest on an european level through compilation and dialogue with the decision-makers. Further, BAT is the proponent for the Danish collective agreement model.", + "name": "Bygge-, Anl\u00e6gs- og Tr\u00e6kartellet", + "created_at": "2015-04-24T02:06:02.588289Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fffebd3272294bb0a38d0347b0e0c4df", + "identification_code": "18539199654-93", + "legal_status": "Faglig organisation (association; trade union federation)", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 45.5893459, + "updated_at": "2016-02-17T01:42:44.613826Z", + "entity": "c476460f5e8243a8b16b75ae1cfafa41", + "number_of_natural_persons": 390, + "legal": "e9918b3c28ed4f1197e97c17a59e4703", + "native_name": null, + "head_office_country": "Italy", + "id": "ffdb86d0032b4bdf8682ff4cc908bf48", + "activity_industry_forums": "None", + "contact_country": 108, + "head_office_postbox": null, + "networking": "* wikimedia.org\r\n* https://meta.wikimedia.org/wiki/Wikimedia_chapters\r\n* https://meta.wikimedia.org/wiki/EU_policy\r\n* frontieredigitali.it\r\n* beniculturaliaperti.it", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Monza (MB)", + "info_members": "Only volunteer work, mostly by members Federico Leva and Lorenzo Losa.\r\n\r\nWe also contribute a small share of the costs for the Free Knowledge Advocacy Group EU representative in Brussels.", + "head": "e9918b3c28ed4f1197e97c17a59e4703", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "via Bergamo, 18 ", + "activity_inter_groups": "None", + "acronym": "WMI", + "activity_eu_legislative": "Net neutrality, InfoSoc directive; anything related to public domain, copyright, free knowledge, free/libre open source software, open data, cultural heritage, digital divide, wikis, collaboration and sharing on the internet.", + "registration_date": "2014-01-27T13:07:45.787000Z", + "activity_relevant_comm": "http://wiki.wikimedia.it/wiki/Consultazione_europea_sul_diritto_d%27autore", + "head_office_post_code": "20900", + "goals": "Wikimedia Italia persegue esclusivamente finalit\u00e0 di solidariet\u00e0 sociale nel campo della promozione della cultura. L'Associazione ha per obiettivo di contribuire attivamente a diffusione, miglioramento e avanzamento del sapere e della cultura promuovendo la produzione, raccolta e diffusione gratuita di contenuti liberi (Open Content) per incentivare le possibilit\u00e0 di accesso alla conoscenza e alla formazione. Sono definiti \"contenuti liberi\" nel senso inteso dall'associazione tutte le opere che sono state contrassegnate dai loro autori con una licenza che ne permetta l'elaborazione e/o la diffusione gratuita. In aggiunta a ci\u00f2 sar\u00e0 approfondita anche la conoscenza e la consapevolezza delle questioni sociali e filosofiche correlate.\r\n\r\nIn particolare Wikimedia Italia si d\u00e0 come obiettivo di promuovere e sostenere, direttamente o indirettamente, gli sviluppi, i trasferimenti, le traduzioni in lingua italiana dei progetti della Wikimedia Foundation, Inc.\r\n\r\nAnche se Wikimedia Italia \u00e8 soggetta alla legge italiana, i suoi obiettivi includono il sostegno ai progetti di Wikimedia Foundation, Inc. nel suo complesso e non solamente a quelli in lingua italiana. Wikimedia Italia non ha interesse a intervenire nella gestione dei siti di Wikimedia Foundation, Inc.\r\n\r\n----\r\n\r\n\"Wikimedia italiana\" has no profit purpose. It intends to operate in the field of the culture and knowledge. In order to actively contribute to the diffusion, the improvement and the progress of the knowledge and culture in the world, Wikimedia italiana aims at supporting the development of encyclopedias, quote collections, educational books and collections of other documents, information and electronic databases having the following characteristics:\r\n\r\n they are completely free\r\n they are available on-line through the internet technologies and their derivatives\r\n they have a content editable by the user\r\n they have a free content, that can be distributed freely under the conditions of licenses like the GNU Free Documentation License, issued by the Free Software Association Inc., and particularly by its European branch on the site http://www.fsfeurope.org/.\r\n\r\nParticularly, Wikimedia italiana intends to promote and support, directly and indirectly, the developments, the transfers, the translations in Italian language of the projects of the Wikimedia Foundation, Inc.\r\n\r\nEven though Wikimedia italiana is subject to the Italian laws, its purposes include the support to the projects of the Association on the whole, and not only to the ones in Italian language. The usage of the Italian language is functional to the work of the association but it does not mean a definition of the association purposes on a national basis.", + "members": 1, + "last_update_date": "2016-02-16T16:19:57.030000Z", + "members_fte": 0.25, + "head_office_phone": "39 0395962256", + "members_25": 1, + "web_site_url": "http://wikimedia.it/", + "sub_category": 31, + "activity_other": "* Joined the https://meta.wikimedia.org/wiki/EU_policy/Statement_of_Intent\r\n* Helped draft https://meta.wikimedia.org/wiki/European_Commission_copyright_consultation\r\n* Submitted http://wiki.wikimedia.it/wiki/Consultazione_europea_sul_diritto_d%27autore and partecipating in InfoSoc directive review debate.\r\n* Joined Italian activities by multiple organisations, like beniculturaliaperti.it and fotoliberebbcc.wordpress.com, aimed at free culture promotion in Italy, also with an EU-level scope.", + "name": "Associazione Wikimedia Italia", + "created_at": "2015-04-24T02:33:36.659656Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffdb86d0032b4bdf8682ff4cc908bf48", + "identification_code": "070762412733-39", + "legal_status": "Associazione di promozione sociale", + "members_100": null, + "head_office_lon": 9.289427, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-06-28T02:12:35.246192Z", + "entity": "2c67100610be42cd8f3573a08c677329", + "number_of_natural_persons": null, + "legal": "4cb1b6f7ae6944c1afc30fb37e0cb5e6", + "native_name": null, + "head_office_country": "Switzerland", + "id": "ffc66947e9214c91ad50ca1f21879084", + "activity_industry_forums": "None", + "contact_country": 215, + "head_office_postbox": null, + "networking": "Advanced Medical Technology Association (AdvaMed) - advamed.org; European Society for Radiotherapy and Oncology (ESTRO) - estro.org; European Coordination Committee of the Radiological Electromedical and Healthcare IT Industry (COCIR) - cocir.org; Global Diagnostic Imaging, Healthcare IT and Radiation Therapy Trade Association (DITTA) - globalditta.org; Union for International Cancer Control (UICC) - uicc.org", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Cham", + "info_members": "All Varian employees involved in activities described under heading 9 are based in Cham, Switzerland. Varian does maintain a small office in Belgium, but this office and all of its employees are entirely excluded from any activities described under heading 9, and is thus not applicable for the purpose of this registration.", + "head": "b6b2bc34195647919988bdc66a928041", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Varian Medical Systems International AG Hinterbergstrasse 14 Hinterbergstrasse 14", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "Varian Medical Systems primarily follows EU initiatives, policies and legislative files relating to public health and/or research and innovation (e.g., Horizon 2020).", + "registration_date": "2016-06-27T17:53:26.204000Z", + "activity_relevant_comm": "Horizon 2020; Europe 2020 Strategy", + "head_office_post_code": "6330", + "goals": "Varian's mission is to focus energy on saving lives. Varian pioneered the use of high-energy X-rays for cancer treatments and developed the first linear accelerators to deliver radiotherapy. Today, Varian is the world's leading supplier of radiotherapy treatment solutions, continually improving delivery systems and advancing the field with new technologies, such as radiosurgery and proton therapy.", + "members": 2, + "last_update_date": "2016-06-27T17:53:56.186000Z", + "members_fte": 0.5, + "head_office_phone": "41 417498844", + "members_25": 2, + "web_site_url": "http://varian.com", + "sub_category": 21, + "activity_other": "Varian Medical Systems is currently a member of the Innovative Medicines Initiative 2 (IMI2).", + "name": "Varian Medical Systems International AG", + "created_at": "2016-06-28T02:12:35.253532Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffc66947e9214c91ad50ca1f21879084", + "identification_code": "185216022477-29", + "legal_status": "public limited company", + "members_100": null, + "head_office_lon": null, + "structure_members": "N/A", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-05-18T01:55:12.188289Z", + "entity": "58e648b6c5f84e7385d918a130930e8e", + "number_of_natural_persons": null, + "legal": "3919868fa8014565a1d1c5a3a805178b", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "ffc559aded2d4379915fe024267d5399", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": "ECCO\r\nESSO\r\nESO\r\nECPC\r\nESMO\r\nEPF\r\nUEG\r\nESDO", + "members_75": 1, + "main_category": 3, + "members_50": 3, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Salisbury", + "info_members": "", + "head": "a7b6d02d614b4e98a40e35a9246facd4", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "5 Deans Yard Phillips Lane Phillips Lane", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "Wo work with our 40 partner groups in Europe to support patients, raise awareness of colorectal cancer and to advocate for the best treatment care and screening across all EU countries", + "registration_date": "2016-05-16T18:01:23.910000Z", + "activity_relevant_comm": "White Paper on colorectal cancer treatment\r\nAnnual review\r\nMeetings in the EU Parliament \r\nCollaboration with other NGO and clinical stakeholders in Europe on health issues", + "head_office_post_code": "SP1 3YP", + "goals": "EuropaColon is committed to preventing deaths from colorectal cancer and improving the quality of life and support for those affected by the disease\r\n\r\nOur 4 Key Goals\r\nTo reduce the numbers of European citizens affected by colorectal cancer\r\nTo identify colorectal cancer at an early stage\r\nTo ensure access\r\nto best treatment and care for all European patients\r\nTo support novel and innovative research into colorectal cancer", + "members": 5, + "last_update_date": "2016-05-17T10:41:19.666000Z", + "members_fte": 3.25, + "head_office_phone": "44 1772333587", + "members_25": null, + "web_site_url": "http://www.europacolon.com", + "sub_category": 31, + "activity_other": "We are not involved in these groups at present", + "name": "Europacolon", + "created_at": "2016-05-17T01:52:12.447290Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffc559aded2d4379915fe024267d5399", + "identification_code": "509496521674-06", + "legal_status": "not for profit", + "members_100": 1, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "be_office_lat": null, + "updated_at": "2016-08-12T02:07:20.156460Z", + "entity": "1b95406c5f8c486fbad9295c26f6e201", + "number_of_natural_persons": null, + "legal": "4499ffdcc0744c59914a27084dbe7d22", + "native_name": null, + "head_office_country": "Italy", + "id": "ffb255f6e8004fe88b4593048bae9c6f", + "activity_industry_forums": "Nell'ambito della realizzazione di ETIS (European Tourism Indicator System) la Dott.ssa Bresciani, consulente specializzato nel Turismo ha partecipato a tutti i Forum sulla materia organizzati dalla Commissione dagli anni 2009 ed ha concluso l'iter partecipativo con la relazione tenuta presso la Commissione lo scorso Gennaio 2016 durante la premiazione per le 100 destinazioni di turismo europeo di cui ha fatto parte con l'Unione dei Comuni TERRAE ANIO IUBENSANAE come coordinatore del progetto.", + "contact_country": 108, + "head_office_postbox": "00027", + "networking": "www.lazio.coldiretti.it\r\nwww.confcooperative.it\r\nwww.jlag.com\r\nwww.festfoundation.eu\r\nwww.pm4esd.eu\r\nwww.ccitabel.com", + "members_75": null, + "main_category": 1, + "members_50": 100, + "activity_expert_groups": "None", + "sub_category_title": "Self-employed consultants", + "other_code_of_conduct": "nessuno", + "head_office_town": "ROVIANO", + "info_members": "La costruzione di PRESS il nuovo gruppo associativo di progettisti europei fa pensare ad un aumento del gruppo di interesse intorno al proponente MB&PARTNERS", + "head": "4499ffdcc0744c59914a27084dbe7d22", + "status": "inactive", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "Viale Alessandro Manzoni 13 13", + "be_office_post_code": null, + "activity_inter_groups": "None", + "acronym": "MB&P", + "activity_eu_legislative": "Le principali iniziative sono state nell'ambito del turismo in collaborazione con la attuale DG GROWTH con cui si \u00e8 percorso il cammino dei label territoriali ETIS sui piccoli comuni del Lazio. La societ\u00e0 ha anche partecipato a riunioni del Consiglio d'Europa sui Cammini e il Presidente \u00e8 divenuto Manager di Routes presso l'Istituto Culturale di Lussemburgo per il riconoscimento dei Cammini Certificati.\r\nIniziative sono state svolte di seminari relativi alle opportunit\u00e0 della Commissione per la convergenza tra turismo e agricoltura.\r\nNell'ambito formativo si \u00e8 ottenuta la certificazione PM4SD in Bruxelles per le certificazioni di Project Management e si sono organizzati seminari in Roma per il trasferimento di competenza e informazione sulle opportunit\u00e0 europee all'interno di Fondazione Italia Sostenibile per Azioni. \r\nAttualmente MB&PARTNERS \u00e8 proponente di una petizione europea per il riconoscimento della figura professionale del progettista europeo seguendo i regolamenti comunitari 1025/2012, la Direttiva 123/2006 sui Servizi e le attivit\u00e0 di controllo e sorveglianza, EQF (European Qualification Framework), Reg. CE n.765/2008 in materia di sorveglianza del mercato.", + "registration_date": "2016-07-26T07:50:53.829000Z", + "activity_relevant_comm": "MB&PARTNERS ha svolto attivit\u00e0 di comunicazione sia a livello locale , regionale e nazionale , che a livello internazionale. In ambito locale \u00e8 attiva con animazione territoriale per la conoscenza delle linee programmatiche europee di sviluppo dei territori rurali con attivit\u00e0 eventistiche per il miglior posizionamento dei temi. Con un evento di rilevanza europea \u00e8 stata la societ\u00e0 proponente dell'evento INCOUNTRY (www.incountry.eu), patrocinato dalla rappresentanza italiana della Commissione Europea. Il Presidente Dott.ssa Marina Bresciani ha partecipato al panel di ETIS (European Tourism Indicator System) come una tra le 100 destinazioni selezionate in Europa per il turismo sostenibile (marina bresciani-youtube-ETIS PANEL CONFERENCE). Il Presidente \u00e8 presente a tutti gli INFODAY sul turismo e alle discussioni correlate per il benessere e la qualit\u00e0 della vita con forti connotazioni e correlazioni con l'agricoltura (Coldiretti). Il Presidente \u00e8 attualmente anche rappresentante della Associazione Europea PRESS che ha realizzato il primo evento lo scorso 8 luglio per la certificazione degli skills del progettista europeo e i criteri di valutazione della figura professionale per una regolamentazione europea (pagina facebook PRESS - Progettisti Europei Associati).", + "head_office_post_code": "00027", + "goals": "MB&PARTNERS nasce dall'idea di creare un network di aziende e professionisti accomunati da un unico obiettivo, in cui ciascuno possa consolidare e condividere le proprie esperienze professionali maturate nel marketing territoriale, del turismo, strizzando l'occhio all'agricoltura, all'arte, alla cultura ed all'ambiente in generale.\r\nIl network non nasce come semplice aggregazione di aziende e professionisti che si occupano delle stesse cose, ma di entit\u00e0 che hanno effettivamente lavorato insieme, cooperato in progetti europei o nazionali o regionali, creato valore aggiunto per il proprio territorio ed abbiano, effettivamente, consolidato la propria collaborazione, collaudandola e fondandola sui risultati effettivamente raggiunti.\r\nMarina Bresciani \u00e8 l'elemento di coordinamento e raccordo tra le competenze verticali e specifiche dei singoli partner, grazie alle molteplici competenze sviluppate nel coordinare progetti integrati dal 2003 ad oggi. Lo spirito aggregativo e cooperativo nasce dalla qualit\u00e0 e solidit\u00e0 delle relazioni professionali che si sono create nel tempo tra i diversi soggetti coinvolti.", + "members": 100, + "last_update_date": "2016-07-26T08:01:19.825000Z", + "members_fte": 50.0, + "head_office_phone": "39 3274089916", + "be_office_town": "Bruxelles", + "members_25": null, + "web_site_url": "http://mbandpartners.it", + "sub_category": 13, + "activity_other": null, + "be_office_postbox": null, + "name": "MB&PARTNERS di BRESCIANI MARINA", + "be_office_street": "Rue de la Loi 26 ", + "created_at": "2016-07-27T02:05:12.456085Z", + "be_office_country": "Belgium", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffb255f6e8004fe88b4593048bae9c6f", + "identification_code": "346207322801-08", + "legal_status": "DITTA INDIVIDUALE", + "members_100": null, + "be_office_phone": "32 33185868", + "be_office_lon": null, + "head_office_lon": null, + "structure_members": "www.studiomorandini.net\r\nwww.italiaspa.org\r\nwww.unionegiovenzano.rm.it\r\nwww.comune.mentana.rm.it", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "Standing Committee on Agricultural Research (SCAR) Brusel, Belgicko\r\nInternational Committee for Animal Recording, Rome Italy (Medzin\u00e1rodn\u00e1 komisia pre evidenciu zvierat)\r\nInternational Committee on Food Microbiology and Hygiene (ICFMH) of International Union of Microbiological Societes (IUMS), Monells, \u0160panielsko (pracovn\u00edci NPPC \u2013 V\u00daP s\u00fa zodpovedn\u00ed za rie\u0161enie jednotliv\u00fdch oblast\u00ed potravin\u00e1rskej mikrobiol\u00f3gie pri zabezpe\u010dovan\u00ed bezpe\u010dnos\u0165 potrav\u00edn.", + "activity_high_level_groups": "Akt\u00edvna \u010dinnos\u0165 NPPC je v pracovnej skupine Rady EU pre medzin\u00e1rodn\u00e9 environment\u00e1lne z\u00e1le\u017eitosti \u2013 dezertifik\u00e1cia k problematike Dohovoru OSN o boji proti dezertifik\u00e1cii,\r\n\r\n\tEuropean Soil Bureau Network \u2013 Eur\u00f3psky \u00farad pre p\u00f4du, EK/JRC/IES/Ispra,(Zvy\u0161ovanie povedomia o p\u00f4de \u2013 pr\u00edprava podkladov, spracov\u00e1vanie p\u00f4dnych \u00fadajov)\r\n\r\nEuropean Commission, Directorate General for Health and Consumer Protection, Brusel, Belgicko\r\nNPPC \u2013 V\u00daP spolupracuje s komisiou v oblastiach zdravia a ochrany spotrebite\u013eov a zaober\u00e1 sa ochranou a zlep\u0161ovan\u00edm zdravia obyvate\u013eov, bezpe\u010dnos\u0165ou a ne\u0161kodnos\u0165ou potrav\u00edn,", + "head_office_lat": null, + "updated_at": "2016-08-31T02:17:50.588053Z", + "entity": "15af1f49221b4eafba575eca7e3d371e", + "number_of_natural_persons": null, + "legal": "6513b50e074640aaae1de8a9622abfa2", + "native_name": null, + "head_office_country": "Slovakia", + "id": "ffae9158758a410391d34d6831f01b86", + "activity_industry_forums": "Medzivl\u00e1dny technick\u00fd panel Glob\u00e1lneho partnerstva o p\u00f4de v r\u00e1mci FAO (ITPS-GSP FAO) \u2013 NPPC - V\u00daPOP akt\u00edvna spolupr\u00e1ca\r\n\r\nFarm Accountancy Data Network Committee (\u00da\u010das\u0165 na zasadnutiach v\u00fdboru FADN 3-4x ro\u010dne. Prerokovan\u00e9 s\u00fa: predpisy a nariadenia Eur\u00f3pskej Komisie, Rady a Parlamentu, s\u00favisiace s informa\u010dnou sie\u0165ou po\u013enohospod\u00e1rskeho \u00fa\u010dtovn\u00edctva E\u00da, form\u00e1t v\u00fdkazu pre zber d\u00e1t.)\r\n\r\nInternational Commission of Agricultural and Biosystems Engineering (CIGR), Brusel, Belgicko\r\nThe Organisation for Economic Co-operation and Development, Par\u00ed\u017e, Franc\u00fazsko (OECD)", + "contact_country": 201, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 4, + "members_50": null, + "activity_expert_groups": "DG SANTE - Health and Food Safety, Unit E2 Plant Health, WG Plant Genetic Resources, Brusel, Belgicko (Expertn\u00e1 pracovn\u00e1 skupina genetick\u00fdch zdrojov rastl\u00edn pri E\u00da).\r\n\r\nKomisia E\u00da COPA/COGECA pracovn\u00e1 skupina pre ovce, kozy, te\u013eacie a hov\u00e4dzie m\u00e4so, Brusel, Belgicko (Organiz\u00e1cia EU zastre\u0161uj\u00faca potravin\u00e1rske a po\u013enohospod\u00e1rske organiz\u00e1cie a zv\u00e4zy. NPPC-V\u00da\u017dV Nitra m\u00e1 \u010dlenov v pracovnej skupine Ovce a kozy (poradensk\u00e1 skupina te\u013eacie a hov\u00e4dzie m\u00e4so).\r\n\tEuropean Food Safety Authority (EFSA), Parma, Taliansko\r\n\r\nEuropean Federation of Animal Science (EAAP)\r\nR\u00edm, Taliansko", + "sub_category_title": "Think tanks and research institutions", + "other_code_of_conduct": null, + "head_office_town": "Lu\u017eianky", + "info_members": "", + "head": "6513b50e074640aaae1de8a9622abfa2", + "status": "active", + "main_category_title": "IV - Think tanks, research and academic institutions", + "head_office_street": "Hlohoveck\u00e1 2 ", + "activity_inter_groups": "European Regional Focal Point for ANGR (Eur\u00f3psky region\u00e1lny kontaktn\u00fd bod pre genetick\u00e9 \u017eivo\u010d\u00ed\u0161ne zdroje)\r\n\tEuropean Association for Research on Plant Breeding (EUCARPIA), Z\u00fcrich, \u0160vaj\u010diarsko (Eur\u00f3pska asoci\u00e1cia pre v\u00fdskum v \u0161\u013eachten\u00ed rastl\u00edn (V\u00daRV sa podie\u013ea na pr\u00e1ci viacer\u00fdch sekci\u00ed, najm\u00e4 GZ, krmov\u00edn a obiln\u00edn a zabezpe\u010duje pokusy s tritikale, pr\u00ednosom je mo\u017enos\u0165 z\u00edskavania najnov\u0161\u00edch inform\u00e1ci\u00ed v oblasti geneticko-\u0161\u013eachtite\u013esk\u00e9ho v\u00fdskumu)\r\n\r\nDAGENE (Dunamenti \u00c1llatfajt\u00e1k G\u00e9nmeg\u00f6rz\u00f6 Nemzetk\u00f6zi Egyes\u00fclete), Budape\u0161\u0165, Ma\u010farsko\r\nMedzin\u00e1rodn\u00e1 organiz\u00e1cia pre vini\u010d a v\u00edno v Par\u00ed\u017ei, O.I.V.", + "acronym": "NPPC", + "activity_eu_legislative": "V zmysle plnenia Nariadenia Eur\u00f3pskeho parlamentu a Rady \u010d. 1107/2009 o uv\u00e1dzan\u00ed pr\u00edpravkov na ochranu rastl\u00edn na trh a Smernice Eur\u00f3pskeho Parlamentu a Rady 2009/128/ES,ktorou sa ustanovuje r\u00e1mec pre \u010dinnos\u0165 Spolo\u010denstva na dosiahnutie trvalo udr\u017eate\u013en\u00e9ho pou\u017e\u00edvania pestic\u00eddov NPPC v s\u00fa\u010dasnosti rie\u0161i \u00falohu \u201eHodnotenie riz\u00edk pr\u00edpravkov na ochranu rastl\u00edn pre ope\u013eova\u010de a spravovanie toxikologicko-informa\u010dn\u00e9ho centra pre v\u010dely a pestic\u00eddy\u201c\r\n-\tSpracov\u00e1vaj\u00fa sa odborn\u00e9 stanovisk\u00e1 pre St\u00e1ly v\u00fdbor pre bezpe\u010dnos\u0165 potrav\u00edn pri EK oh\u013eadom rizika aplik\u00e1cie pr\u00edpravkov na ochranu rastl\u00edn", + "registration_date": "2016-08-23T14:54:09.690000Z", + "activity_relevant_comm": "V zmysle rozhodnutia EUR\u00d3PSKEHO PARLAMENTU A RADY \u010d. 529/2013/E\u00da z 21. m\u00e1ja 2013 o pravidl\u00e1ch zapo\u010d\u00edtavania pre emisie a z\u00e1chyty sklen\u00edkov\u00fdch plynov vypl\u00fdvaj\u00face z \u010dinnost\u00ed s\u00favisiacich s vyu\u017e\u00edvan\u00edm p\u00f4dy, so zmenami vo vyu\u017e\u00edvan\u00ed p\u00f4dy a s lesn\u00fdm hospod\u00e1rstvom a o inform\u00e1ci\u00e1ch t\u00fdkaj\u00facich sa opatren\u00ed s\u00favisiacich s t\u00fdmito \u010dinnos\u0165ami sa NPPC zaober\u00e1 sledovan\u00edm a inventariz\u00e1ciou emisi\u00ed z po\u013enohospod\u00e1rskej p\u00f4dy a zmien vyu\u017e\u00edvania p\u00f4dy ako aj anal\u00fdzou emisn\u00fdch faktorov a emisi\u00ed amoniaku a sklen\u00edkov\u00fdch plynov (CH4 , N2O) z chovu hospod\u00e1rskych zvierat\r\n\r\nV zmysle Smernice Eur\u00f3pskeho parlamentu a Rady 2009/28/ES o podpore obnovite\u013en\u00fdch zdrojov energie sa rie\u0161i \u00faloha \u201eVypracovanie krit\u00e9ri\u00ed udr\u017eate\u013en\u00e9ho vyu\u017e\u00edvania biomasy\u201c\r\n\r\nV r\u00e1mci programu programu HORIZONT 2020 je NPPC zapojen\u00e9 do rie\u0161enia projektu BIOSKOH\u2019s Innovation Stepping Stones for a novel European Second Generation BioEconomy. \r\nZ\u00e1merom projektu BIOSKOH je podpora rie\u0161en\u00ed pre unik\u00e1tne spracovanie a vyu\u017eitie fytomasy na v\u00fdrobu bioetanolu technol\u00f3giou druhej gener\u00e1cie.", + "head_office_post_code": "95141", + "goals": "The National Agricultural and Food Centre focuses on comprehensive research and gathering of knowledge in the sustainable use and protection of natural resources, especially soil and water resources for crop production and animal husbandry, quality and safety, innovation and competitiveness of food and non-food products of agricultural origin, productive and non-productive impact of agriculture on the environment and rural development and the transfer of knowledge from agricultural and food research to end users.", + "members": 10, + "last_update_date": "2016-08-23T15:15:53.294000Z", + "members_fte": 2.5, + "head_office_phone": "421 376546122", + "members_25": 10, + "web_site_url": "http://www.nppc.sk/index.php/sk/", + "sub_category": 41, + "activity_other": null, + "name": "N\u00e1rodn\u00e9 po\u013enohospod\u00e1rske a potravin\u00e1rske centrum", + "created_at": "2016-08-31T02:17:50.591701Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffae9158758a410391d34d6831f01b86", + "identification_code": "509308323113-13", + "legal_status": "\u0161t\u00e1tna pr\u00edspevkov\u00e1 organiz\u00e1cia", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-04-07T00:03:42.963618Z", + "entity": "4c94c490da1e48a6af5d409dad93d2cc", + "number_of_natural_persons": null, + "legal": "923468e984824eb0a525f369e8e03dca", + "native_name": null, + "head_office_country": "Italy", + "id": "ffaa55befc9b477bb35bd635bf458c3c", + "activity_industry_forums": "None", + "contact_country": 108, + "head_office_postbox": null, + "networking": "COPA : Committee of Professional Agricultural Organisations\r\nthrough Confagricoltura", + "members_75": null, + "main_category": 2, + "members_50": 2, + "activity_expert_groups": "None", + "sub_category_title": "Trade unions and professional associations", + "other_code_of_conduct": null, + "head_office_town": "BOLOGNA", + "info_members": "", + "head": "ba011dd23b5240af8f980775e88609a6", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "via del monte 10 ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "PAC", + "registration_date": "2010-04-08T11:17:31.076000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "40126", + "goals": "Confagricoltura Emilia- Romagna is a regional branch of the national organisation representative of agricultural interests, which safeguards local farmer structures, all the associated members and every professional group, trade union and economic category linked to those members.", + "members": 2, + "last_update_date": "2016-04-06T16:35:51.728000Z", + "members_fte": 1.0, + "head_office_phone": "39 051 251866", + "members_25": null, + "web_site_url": "http://www.confagricoltura.org/it/", + "sub_category": 26, + "activity_other": "-Response to Consultations published by European Commission\r\n\r\n- Forwarding of position papers / statements to MEPS \r\n\r\n- Participation in the elaboration of agricultural position papers on the European level", + "name": "CONFAGRICOLTURA EMILIA-ROMAGNA", + "created_at": "2015-04-24T01:53:02.429922Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffaa55befc9b477bb35bd635bf458c3c", + "identification_code": "36395803420-35", + "legal_status": "ASSOCIAZIONE SINDACALE", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-02-11T02:56:07.336686Z", + "entity": "dd0024740d7141a0870688d2aaafe8f6", + "number_of_natural_persons": 12, + "legal": "1cde557356d944059919483fca786984", + "native_name": null, + "head_office_country": "Greece", + "id": "ffa463c6b2d24eb281d08ce34f369730", + "activity_industry_forums": "None", + "contact_country": 85, + "head_office_postbox": null, + "networking": "Member of the INGO network of the Council of Europe", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Thessaloniki", + "info_members": "", + "head": "db7eb8bab6d347b68fea1312a38f3db0", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Krispou 9, Ano Poli Ano Poli", + "activity_inter_groups": "None", + "acronym": "CDRSEE", + "activity_eu_legislative": "DG for Neighbourhood and Enlargement Negotiations\r\nDG for Education and Culture\r\nDG for International Cooperation and Development\r\nDG for Justice and Consumers\r\nDG for Migration and Home Affairs", + "registration_date": "2016-02-10T15:31:14.791000Z", + "activity_relevant_comm": "Joint History Project -- The CDRSEE's flagship project, the JHP is an educational programme that aims to change the way history is taught in high schools across Southeast Europe. The programme, currently in its second phase, provides teachers with workbooks and training so they can offer coursework with multiple perspectives, encouraging students to consider the many aspects of an event and to think critically about information provided. There are currently four workbooks, in 11 languages, covering history up to the Second World War. The next two workbooks, which will address the Cold War and the Wars of the 1990s, are due to be published in July 2016 and launched in September 2016. The programme enjoys the support of nearly all the Ministries of Education across the region, and is considered the gold standard in history teaching.\r\n \r\nOkruzenje (Vicinities) -- The CDRSEE has done what no one thought possible just a few years ago -- created an informative, engaging talk show especially for the Western Balkans that deals with divisive issues in the region. The same programme is broadcast on 10 national television channels and scores of regional channels across the Western Balkans, including all the countries of the former Yugoslavia and Albania. The show, kicking off its fifth season, brings together guests from different countries and backgrounds on the same set. Okruzenje made history at the Western Balkans Summit Vienna 2015 in August when for the first time ever, the Prime Ministers of Albania and Serbia were both guests in a single studio, in this case advocating regional cooperation. \r\n\r\nNetucate -- The CDRSEE is partnering with EUROCLIO for a three-year project on education reform in Southeast Europe. The project leverages the \"Teaching for Learning\" methodology manual produced by the CDRSEE, providing teacher training and materials. Overall the project includes a major education evaluation, a pilot project and a project plan, as well as teacher training and a strengthening of the network of key actors, all focused on enhancing the education system to deal with a global, interactive society. The process will be followed via a special episode series of the \"Okruzenje\" TV talk show. The ultimate goal is educational reform in order to help sustain the democratisation process and enhance sensitivity and understanding, through reforms and changes in the formal school system.\r\n \r\nVicinities Europe -- Vicinities Europe has taken the proven Okruzenje (Vicinities) model and applied it to Europe, where there are certainly ample divisive issues. The idea surfaced from a presentation of Okruzenje in the European Parliament, where MEPs suggested widening the show to Europe, noting its power in fostering reconciliation and understanding among the people. Two pilot shows were produced in October 2015 -- one on the migrant and refugee crisis, and another on the future of the European idea. CIRCOM, the European Association of Regional Televisions, featured Vicinities Europe on its website and offered it to all of its members. So far, the shows have been broadcast in at least nine countries.", + "head_office_post_code": "54634", + "goals": "The Center for Democracy and Reconciliation in Southeast Europe is a non-governmental, non-profit organisation that seeks to foster democratic, pluralist, and peaceful societies in Southeast Europe. We advocate principles of social responsibility, sustainable development, and reconciliation among the peoples in the region. We accomplish these goals via media activities, educational programmes, seminars, publications, conferences, research projects, exchange programmes, and opinion polls.", + "members": 1, + "last_update_date": "2016-02-10T15:32:51.296000Z", + "members_fte": 0.25, + "head_office_phone": "30 2310960820", + "members_25": 1, + "web_site_url": "http://www.cdrsee.org", + "sub_category": 31, + "activity_other": null, + "name": "Stichting Center for Democracy and Reconciliation in Southeast Europe", + "created_at": "2016-02-11T02:56:07.343619Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffa463c6b2d24eb281d08ce34f369730", + "identification_code": "660781520586-28", + "legal_status": "Foundation non-governmental and non-profit", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-07-21T02:08:37.366704Z", + "entity": "8325771f162b45498135a098dfb51cb8", + "number_of_natural_persons": 39582, + "legal": "77b4e80e645c4eb88d42acae1f4fd430", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "ffa09f73d35640b788cf26e335b50d84", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 4, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Academic institutions", + "other_code_of_conduct": null, + "head_office_town": "London", + "info_members": "", + "head": "4d1f631078c3459689f9115858f83163", + "status": "active", + "main_category_title": "IV - Think tanks, research and academic institutions", + "head_office_street": "The Strand ", + "activity_inter_groups": "None", + "acronym": "KCL", + "activity_eu_legislative": "Contribution to consultation and written correspondence", + "registration_date": "2016-07-20T13:28:48.646000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "WC2R 2LS", + "goals": "King's College London is dedicated to the advancement of knowledge, learning and understanding in the service of society.\r\n\r\nThe college's mission is articulated in the College's Strategic Plan 2006 - 2016 (http://www.kcl.ac.uk/aboutkings/strategy/PDFs--Resources/2006-16StrategicPlan.pdf) and in the accompanying suite of linked strategies", + "members": 1, + "last_update_date": "2016-07-20T13:29:14.656000Z", + "members_fte": 0.25, + "head_office_phone": "44 78365454", + "members_25": 1, + "web_site_url": "http://www.kcl.ac.uk", + "sub_category": 42, + "activity_other": "Contribution to consultation and written correspondence", + "name": "King's College London", + "created_at": "2016-07-21T02:08:37.373983Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ffa09f73d35640b788cf26e335b50d84", + "identification_code": "335281522747-30", + "legal_status": "'Exempt' charity under Schedule 3 of the Charities Act 2011 for the purposes of UK charity legislation", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-06-18T01:59:10.877902Z", + "entity": "ea23cc779051402da25cfd080b2a83c4", + "number_of_natural_persons": null, + "legal": "7efa8b08a3d14ea9bce46dda642837da", + "native_name": null, + "head_office_country": "Germany", + "id": "ff95562e4f774e7ba0c4a8ee98403c18", + "activity_industry_forums": "None", + "contact_country": 82, + "head_office_postbox": null, + "networking": "B\u00f6rsenverein des Deutschen Buchhandels.\r\nhttp://www.boersenverein.de/de/portal/index.html", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Berlin", + "info_members": "", + "head": "7efa8b08a3d14ea9bce46dda642837da", + "status": "inactive", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Fredericiastrasse 8 ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "Urheberrecht\r\nVerlagsrecht", + "registration_date": "2016-05-31T15:28:20.995000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "14050", + "goals": "Das Publizieren von B\u00fcchern. Schwerpunkte: Theater, Film und Literatur.", + "members": 3, + "last_update_date": "2016-05-31T15:30:48.897000Z", + "members_fte": 3.0, + "head_office_phone": "49 303021826", + "members_25": null, + "web_site_url": "http://www.alexander-verlag.com", + "sub_category": 21, + "activity_other": null, + "name": "Alexander Verlag Berlin", + "created_at": "2016-06-01T01:55:05.349179Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff95562e4f774e7ba0c4a8ee98403c18", + "identification_code": "052108522024-86", + "legal_status": "Einzelfirma", + "members_100": 3, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-17T01:39:21.520955Z", + "entity": "e736f0e4a6d149459c5a1da0d62af8ec", + "number_of_natural_persons": 1, + "legal": "55203a1b62914a8a8033a633b2a3a2a3", + "native_name": null, + "head_office_country": "Canada", + "id": "ff919bf968eb498bb7af62a1494a49d1", + "activity_industry_forums": "None", + "contact_country": 39, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 3, + "members_50": 1, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": "Michel Georges Abdelahad", + "head_office_town": "St-Jean-sur-Richelieu", + "info_members": "De 1989 \u00e0 2004, nous avons \u00e9t\u00e9 tr\u00e8s actif au Canada. Des raisons personnelles ont conduit un ancien organisme de charit\u00e9 canadien \u00e0 se retir\u00e9.\r\n\r\n( Les Habitations Organisationnelles Mondiales pour la Famille )\r\n\r\nMichel Abdelahad, fondateur et ex-pr\u00e9sident de cet organisme reprendra les activit\u00e9es.", + "head": "0ae64e61a73a431580ea1cb456740bdd", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "1392 Jacques-Cartier Sud ", + "activity_inter_groups": "None", + "acronym": "Michel Abdelahad", + "activity_eu_legislative": "Nous avons les m\u00eames buts que l'Union europ\u00e9enne ou les Nations Unies, soit: C\u2019est en 2000 au sommet du mill\u00e9naire organis\u00e9 par les Nations Unies que les Chefs d\u2019\u00c9tats de 189 pays et des gouvernements du monde entier, se sont mis d\u2019accord pour n\u2019\u00e9pargner aucun effort pour lib\u00e9rer leurs semblables, hommes, femmes et enfants des conditions abjectes et d\u00e9shumanisantes de l\u2019extr\u00eame pauvret\u00e9. L\u2019objectif de l\u2019Union europ\u00e9enne, avec plus de 80 millions de personnes menac\u00e9es de pauvret\u00e9, consistait \u00e0 sortir au moins 20 millions de personnes de la pauvret\u00e9 et de l\u2019exclusion sociale d\u2019ici l\u2019an 2020.", + "registration_date": "2012-04-06T18:28:15.430000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "J3B 6Y8", + "goals": "Une solution \u00e0 la pauvret\u00e9 et au ch\u00f4mage\r\n\r\nNotre projet vise \u00e0 garantir la s\u00e9curit\u00e9 de l\u2019habitation et de l\u2019alimentation de la famille vivant sous le seuil de pauvret\u00e9 \u00e0 la classe moyenne, telle garantie n\u2019\u00e9tant actuellement qu\u2019un avantage de la classes plus nantie. \r\n\r\nEn solvant les probl\u00e8mes de pauvret\u00e9, ce projet va cr\u00e9er un \u00e9quilibre entre ces classes. L\u2019une d\u00e9pendra de l\u2019autre, mais dans des conditions ou contextes diff\u00e9rents.\r\n\r\nL\u2019\u00e9quilibre ainsi cr\u00e9\u00e9 mettra un terme \u00e0 la lutte des classes et aux conflits qui, depuis trop longtemps,\r\nperdurent \u00e0 faire tant de victimes.\r\n\r\nNous consid\u00e9rons que nous avons tous un travail \u00e9galement valable, essentiel et indispensable dans la soci\u00e9t\u00e9. L\u2019habitation et l\u2019alimentation sont des besoins essentiels autant pour le plus bas salari\u00e9 que pour le plus nanti. Pourtant, ces besoins ne sont pas toujours ad\u00e9quatement\r\ncombl\u00e9s.\r\n\r\nLes travailleurs moins salari\u00e9s n\u2019auraient-ils pas droits \u00e0 aux m\u00eames avantages que leur employeur qui s\u2019enrichira \u00e0 leurs d\u00e9pends ?\r\n\r\nNotre projet cr\u00e9era cette \u00e9quilibre\r\n\r\nUne solution concr\u00e8te et r\u00e9aliste \u00e0 ce probl\u00e8me, c\u2019est l\u2019acc\u00e8s \u00e0 l\u2019habitation unifamiliale priv\u00e9e et l\u2019alimentation pour le travailleur soutien de famille bas salari\u00e9 ainsi que pour la classe moyenne. Ce projet a \u00e9t\u00e9 con\u00e7u pour r\u00e9tablir un \u00e9quilibre entres ces classes.\r\n\r\nLe 27 octobre 2014, nous avons fait parvenir une lettre \u00e0 Monsieur Martin Schultz, Pr\u00e9sident du Parlement europ\u00e9en. \u00c9tant canadiens, nous lui demandions dans notre correspondance, le processus afin d\u2019obtenir un ou une d\u00e9put\u00e9(e), dans le but de pr\u00e9senter officiellement notre projet aux membres de l\u2019Union europ\u00e9enne.", + "members": 1, + "last_update_date": "2016-03-15T12:32:49.855000Z", + "members_fte": 0.5, + "head_office_phone": "438 8376023", + "members_25": null, + "web_site_url": "http://www.michelabdelahad.ca", + "sub_category": 31, + "activity_other": "Nous avons fait parvenir une lettre de sensibilisation \u00e0 plus de 120 pays, \u00e0 des milliers de personnes dont des leaders, des administrateurs, des commer\u00e7ants, des industries.\r\n\r\nVoici la Lettre de sensibilisation:\r\n\r\nobjet:Le Projet , une solution \u00e0 la pauvret\u00e9 et au ch\u00f4mage\r\n\r\nMadame, Monsieur,\r\n \r\nCe projet, une solution \u00e0 la pauvret\u00e9 et au ch\u00f4mage, vise \u00e0 s\u00e9curiser l\u2019habitation et l\u2019alimentation pour la classe moyenne, une garantie qui n\u2019est actuellement qu\u2019un avantage de la classes plus nantie. \r\nNous consid\u00e9rons que, l'habitation et l'alimentation ne vont pas au m\u00e9rite, mais sont acquises et essentielles pour l'\u00eatre humain et nous y avons tous droit.\r\nEn apportant une solution aux probl\u00e8mes de pauvret\u00e9 dans le monde, ce projet cr\u00e9era un \u00e9quilibre entre ces classes. L\u2019une d\u00e9pendra de l\u2019autre, mais dans des conditions ou contextes diff\u00e9rents.\r\nL\u2019\u00e9quilibre ainsi cr\u00e9\u00e9 mettra un terme \u00e0 la lutte des classes, aux injustices et aux conflits qui, depuis trop longtemps, perdurent \u00e0 faire tant de victimes.\r\nNous consid\u00e9rons que nous avons tous un travail \u00e9galement valable, essentiel et indispensable dans la soci\u00e9t\u00e9. L\u2019habitation et l\u2019alimentation sont des besoins essentiels autant pour le plus bas salari\u00e9 que pour le plus nanti. Pourtant, ces besoins ne sont pas toujours ad\u00e9quatement combl\u00e9s.\r\nLes travailleurs moins salari\u00e9s n\u2019auraient-ils pas droits aux m\u00eames avantages que leur employeur qui s\u2019enrichira \u00e0 leurs d\u00e9pends ?\r\nNotre projet cr\u00e9era cet \u00e9quilibre. \r\nNous vous invitons \u00e0 venir visiter notre site internet au www.michelabdelahad.ca\r\nNous avons besoin de votre aide.\r\nAu plaisir de vous rencontrer.\r\nVeuillez, agr\u00e9er, Madame, Monsieur, l'expression de nos sentiments les meilleurs.\r\nMichel Abdelahad", + "name": "Michel Abdelahad", + "created_at": "2015-04-24T02:03:29.575210Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff919bf968eb498bb7af62a1494a49d1", + "identification_code": "90135938437-51", + "legal_status": "\u00c9tudiant / retrait\u00e9", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-08-18T02:05:39.164064Z", + "entity": "93355a2361e94cdca6c3109c22d5c021", + "number_of_natural_persons": null, + "legal": "b1ca1ea84ce34faa8cdc85a44adc6532", + "native_name": null, + "head_office_country": "Belgium", + "id": "ff8bf95428b24bfbb473f10d41580e0e", + "activity_industry_forums": "None", + "contact_country": 21, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "Sustainable Transport Forum\r\nMotorcycle Working Group", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Brussel", + "info_members": "", + "head": "ae93dd141fee4dd4b8e52c2ffd293e3e", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Boulevard de la Plaine 2 ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "- Type-approval\r\n- Transport policy\r\n- Energy policy\r\n- Communication on decarbonization of transport\r\n- Review Transport Criteria Green Public Procurement", + "registration_date": "2016-08-17T15:32:40.727000Z", + "activity_relevant_comm": "- Coordinator European Alternative Fuels' Observatory\r\n- Partner in Solutions\r\n- Partner in REE4EU\r\n- Co-organizor EVS", + "head_office_post_code": "1050", + "goals": "AVERE \u2013 founded in 1978 - is a European network comprised of members including Users, NGO\u2019s, Associations, Interest groups, Public Bodies, Research & Development entities, Vehicle and Equipment Manufacturers, Electricity Utilities.\r\n\r\nIts main objective is to promote the use of electric mobility in order to achieve greener mobility for cities and countries.\r\n\r\nThe main activities to achieve these objectives are related to dissemination, networking, monitoring, participation in European and multilateral projects, lobbying, research and development, among other. In public policy, AVERE presents the electric drive industry\u2019s and R&D bodies\u2019 concerns to the European Commission.", + "members": 3, + "last_update_date": "2016-08-17T15:39:52.710000Z", + "members_fte": 0.75, + "head_office_phone": "32 477633923", + "members_25": 3, + "web_site_url": "http://www.avere.org", + "sub_category": 31, + "activity_other": null, + "name": "AVERE", + "created_at": "2016-08-18T02:05:39.168461Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff8bf95428b24bfbb473f10d41580e0e", + "identification_code": "269727723042-29", + "legal_status": "VZW", + "members_100": null, + "head_office_lon": null, + "structure_members": "All AVERE members can be found here:\r\n\r\nhttps://averelev.wordpress.com/avere-lev-task-force-participants/", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-05-20T01:56:04.459713Z", + "entity": "8483b8617edf495ba3a0c548efd0d036", + "number_of_natural_persons": 4, + "legal": "ba47d71f97c6415a95f7adb15969660c", + "native_name": null, + "head_office_country": "Belgium", + "id": "ff8b766c3874481596465f39a7374139", + "activity_industry_forums": "None", + "contact_country": 21, + "head_office_postbox": null, + "networking": null, + "members_75": 0, + "main_category": 3, + "members_50": 3, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Bruxelles", + "info_members": "", + "head": "4a9a2409fc7543b8ab2c7de45cbcbf25", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Boulevard Saint Lazare 11 ", + "activity_inter_groups": "None", + "acronym": "ABF", + "activity_eu_legislative": "EU activities in the field of education", + "registration_date": "2016-05-16T17:32:32.443000Z", + "activity_relevant_comm": "Erasmus+", + "head_office_post_code": "1210", + "goals": "Alphabet Formation, ABF, is a network of European organizations in the field of human capital development. This investment in knowledge, skills and competences will benefit individuals, institutions, organisations and society as a whole by contributing to growth and ensuring equity, prosperity and social inclusion in Europe and beyond.", + "members": 3, + "last_update_date": "2016-05-19T19:24:35.963000Z", + "members_fte": 1.5, + "head_office_phone": "32 488326305", + "members_25": 0, + "web_site_url": "http://www.alphabetformation.org", + "sub_category": 31, + "activity_other": null, + "name": "Alphabet Formation", + "created_at": "2016-05-17T01:52:14.441021Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff8b766c3874481596465f39a7374139", + "identification_code": "348324921710-79", + "legal_status": "ASBL", + "members_100": 0, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "Horizon H2020", + "head_office_lat": null, + "updated_at": "2016-09-18T20:36:33.419121Z", + "entity": "fb567d6ec94d40c7844a2bb9a324b727", + "number_of_natural_persons": null, + "legal": "c9244b6262854fe481ab829974aa01a4", + "native_name": null, + "head_office_country": "France", + "id": "ff893be893604f0e9959c6bb774a97e4", + "activity_industry_forums": "None", + "contact_country": 75, + "head_office_postbox": "34830", + "networking": null, + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Professional consultancies", + "other_code_of_conduct": null, + "head_office_town": "CLAPIERS", + "info_members": "", + "head": "c9244b6262854fe481ab829974aa01a4", + "status": "active", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "45 all\u00e9e Yves Stourdz\u00e9 ", + "activity_inter_groups": "None", + "acronym": "IDATE", + "activity_eu_legislative": "MetisII\r\nEuro5G\r\nCreate-IOT\r\nMagicII\r\nFinancement FEDER", + "registration_date": "2016-09-09T15:48:56.517000Z", + "activity_relevant_comm": "None", + "head_office_post_code": null, + "goals": "IDATE DigiWorld, l\u2019un des instituts europ\u00e9ens de l\u2019\u00e9conomie num\u00e9rique les plus renomm\u00e9s, est sp\u00e9cialis\u00e9 sur les march\u00e9s t\u00e9l\u00e9coms, Internet, m\u00e9dias et les territoires num\u00e9riques. Depuis 1977, nos \u00e9quipes proposent des missions de conseil, des services de veille des march\u00e9s et un programme de d\u00e9bats et de rencontres afin de d\u00e9crypter les enjeux de l\u2019\u00e9conomie num\u00e9rique et d\u2019\u00e9clairer les d\u00e9cisions strat\u00e9giques de nos clients. Nous sommes fiers de travailler chaque ann\u00e9e avec plus de 400 d\u00e9cideurs publics et grandes entreprises qui renouvellent leur confiance dans nos services, au travers de nos trois lignes d\u2019activit\u00e9s :\r\n\u2022\tDigiWorld Research, une offre de prestations d\u2019\u00e9tudes et de conseil\r\n\u2022\tIDATE Consulting, un observatoire ind\u00e9pendant des march\u00e9s et de l\u2019innovation num\u00e9rique\r\n\u2022\tDigiWorld Institute, un think tank europ\u00e9en ouvert sur le monde", + "members": 13, + "last_update_date": "2016-09-09T15:52:37.466000Z", + "members_fte": 3.25, + "head_office_phone": "33 467144444", + "members_25": 13, + "web_site_url": "http://www.idate.org", + "sub_category": 11, + "activity_other": null, + "name": "Institut de l'Audiovisuel et des T\u00e9l\u00e9communications en Europe", + "created_at": "2016-09-18T20:36:33.426290Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff893be893604f0e9959c6bb774a97e4", + "identification_code": "713335923349-24", + "legal_status": "Association Loi 1901", + "members_100": null, + "head_office_lon": null, + "structure_members": "http://www.idate.org/en/Forum/Members/Members-List_42_.html", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 37.5197479, + "updated_at": "2016-03-26T01:50:56.435389Z", + "entity": "241e762235884644aad9cd2ca1b4e4d9", + "number_of_natural_persons": null, + "legal": "ddcefa2c6ed84403a79cf581ef8ae649", + "native_name": null, + "head_office_country": "Italy", + "id": "ff802d6280874fb08e132d662e46f18e", + "activity_industry_forums": "None", + "contact_country": 108, + "head_office_postbox": null, + "networking": null, + "members_75": 1, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "CATANIA", + "info_members": "", + "head": "af5aa34046b24aa79be61c468362d592", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "CORSO DELLE PROVINCE, 203 ", + "activity_inter_groups": "None", + "acronym": "FIPI", + "activity_eu_legislative": "Mobilit\u00e0 lavoratori", + "registration_date": "2015-01-01T13:14:34.261000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "95128", + "goals": "1) la rappresentanza sindacale degli associati, tutelandone gli interessi in tutte le sedi;\r\n2) la promozione dell\u2019attivit\u00e0 di formazione dei lavoratori autonomi e degli imprenditori, a tutela dei valori morali, civili e per la qualificazione;\r\n3) la rappresentanza e tutela dei lavoratori autonomi e delle imprese, nei rapporti con le istituzioni pubbliche e private, la Pubblica Amministrazione, le organizzazioni politiche, sociali, economiche a livello nazionale ed internazionale intervenendo anche attraverso le proprie organizzazioni territoriali e di settore per garantire la tutela e rappresentanza a tutti i livelli;\r\n4) la stipula, anche attraverso organizzazioni di settore, di accordi e contratti collettivi di lavoro fornendo la relativa assistenza alle associazioni territoriali e di settore interessato;\r\n5) l\u2019assistenza sociale e previdenziale di Patronato in Italia ed all\u2019estero, anche in convenzione;\r\n6) la rappresentanza, l\u2019assistenza e la consulenza di ogni aspetto dell\u2019attivit\u00e0 aziendale anche sotto i profili: contabile, amministrativo, legale, tecnico, tributario-fiscale, assicurativo-finanziario, sindacale e di consulenza del lavoro;\r\n7) la costituzione e la promozione di agenzie per l\u2019impiego secondo le norme vigenti, in attuazione del disposto di cui all\u2019art.78 della Legge n. 413 del 30.12.1991 e s.m.i,;\r\n8) la promozione ed assistenza alla creazione di nuove imprese con azioni specifiche, anche nel quadro degli appositi programmi della U.E.;\r\n9) la formazione professionale e continua dei lavoratori autonomi, degli imprenditori della piccola impresa, degli apprendisti, dei dipendenti e quanti operano nelle imprese o che intendano inserirsi nelle attivit\u00e0 aziendali, anche ai sensi del comma 3, art. 8 bis, D.lgs. 626/94 e s.m.i.;\r\n10) la costituzione, il potenziamento e l\u2019organizzazione anche sindacale di organismi economici, cooperativistici, mutualistici e consortili;\r\n11) attivit\u00e0 in materia di immigrazione e formazione interculturale con l\u2019obiettivo di elaborare strategie progettuali che permettano alla comunit\u00e0 locale di relazionarsi in maniera consapevole, aperta e dialogica con il fenomeno migratorio, contribuendo alla formazione di una societ\u00e0 multiculturale retta dalla valorizzazione delle differenze in un contesto di civile e pacifica convivenza.", + "members": 2, + "last_update_date": "2016-03-23T12:09:35.589000Z", + "members_fte": 1.75, + "head_office_phone": "095 449778", + "members_25": null, + "web_site_url": "http://www.fipi.it", + "sub_category": 31, + "activity_other": "Mobilit\u00e0 di persone a scopo lavorativo all'interno della Comunit\u00e0 europea.", + "name": "FEDERAZIONE ITALIANA PICCOLE IMPRESE", + "created_at": "2015-04-24T02:26:23.530723Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff802d6280874fb08e132d662e46f18e", + "identification_code": "681912015411-37", + "legal_status": "ASSOCIAZIONE", + "members_100": 1, + "head_office_lon": 15.0910225, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-04-07T00:37:19.553399Z", + "entity": "a6ec27aa087f4d17afcd58832b92d3a7", + "number_of_natural_persons": 51, + "legal": "2dbc3ce9673b4989b73632e346f8dbf2", + "native_name": null, + "head_office_country": "Ireland", + "id": "ff724deeeaf8408a9ff65a58e605d552", + "activity_industry_forums": "None", + "contact_country": 105, + "head_office_postbox": null, + "networking": "Health and Environment Alliance\r\nInternational Society of Doctors for the Environment\r\nInternational Physicians for the Prevention of Nuclear War\r\nInternational Campaign to Abolish Nuclear Weapons\r\nIrish Environmental Network\r\nIrish Environmental Pillar", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Bandon", + "info_members": "All persons are volunteers (Unpaid)", + "head": "2dbc3ce9673b4989b73632e346f8dbf2", + "status": "inactive", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Castlebernard ", + "activity_inter_groups": "None", + "acronym": "IDEA", + "activity_eu_legislative": "We are involved in many EU environmental issues through our affiliation to the Health and Environment Alliance (HEAL) based in Brussels, and with UN (UNEP) issues, mainly Climate Change, through the International Society of Doctors for the Environment (ISDE).", + "registration_date": "2015-03-31T19:35:05.471000Z", + "activity_relevant_comm": "Letters and articles in the lay and medical press, speaking on local and national radio and on TV when the opportunity arises. Attending various relevant meetings.", + "head_office_post_code": "xxxxx", + "goals": "To highlight the risks of environmental degradation and loss of biodiversity to human health including chemical contamination of the biosphere and climate change to medical professionals, the public and government. To advocate for a better and more sustainable way of life by holding public meetings, writing in lay and medical press/journals, speaking at public meetings, liasing with other NGOs, official organisations and government departments, the EU and the UN.", + "members": 10, + "last_update_date": "2015-04-20T19:17:38.830000Z", + "members_fte": 2.5, + "head_office_phone": "353 23 8844697", + "members_25": 10, + "web_site_url": "http://www.ideaireland.org", + "sub_category": 31, + "activity_other": null, + "name": "Irish Doctors Environmental Association", + "created_at": "2015-04-24T02:20:30.597430Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff724deeeaf8408a9ff65a58e605d552", + "identification_code": "115584716819-62", + "legal_status": "Registered charity", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 52.5151735, + "updated_at": "2016-05-20T00:29:19.114087Z", + "entity": "19db79249b454902a639066e1ec8b07c", + "number_of_natural_persons": null, + "legal": "d5f231312f2644a5b7c8e6983f983ee1", + "native_name": null, + "head_office_country": "Germany", + "id": "ff6ce8c03aee44788ce83a6544cdbb4c", + "activity_industry_forums": "None", + "contact_country": 82, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "MDEG\r\nBorderline Classification Group", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "Berlin", + "info_members": "", + "head": "3cd888fb06694df0b59bdfaf9559a27f", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Werderscher Markt 15 ", + "activity_inter_groups": "None", + "acronym": "EUROM", + "activity_eu_legislative": "Medical Devices Regulation\r\nTTIP\r\nUDI\r\nREACH and RoHS", + "registration_date": "2013-09-27T10:09:10.979000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "10117", + "goals": "The object of EUROM is to represent the joint interests of the precision mechanical and optical industries and to promote cooperation amongst the members.\r\n\r\nMembers of EUROM are the professional organizations which represent the precision mechanical and optical industries in their respective countries (member states of the EU).", + "members": 2, + "last_update_date": "2016-05-19T12:57:55.693000Z", + "members_fte": 0.5, + "head_office_phone": "49 3041402156", + "members_25": 2, + "web_site_url": "http://eurom.org/", + "sub_category": 25, + "activity_other": null, + "name": "European Federation of Precision, Mechanical and Optical Industries", + "created_at": "2015-04-24T02:04:35.541629Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff6ce8c03aee44788ce83a6544cdbb4c", + "identification_code": "585778511937-68", + "legal_status": "nicht-rechtsf\u00e4higer Verein im Sinne des \u00a7 54 BGB", + "members_100": null, + "head_office_lon": 13.3971302, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-04-07T01:00:14.924104Z", + "entity": "abf0273d6186405bac6432a67fd01921", + "number_of_natural_persons": 3, + "legal": "09a75790dd0e4bbfa6b1d043f2cf38ed", + "native_name": null, + "head_office_country": "Netherlands", + "id": "ff6ba0bcb497410fa406c9794206bf37", + "activity_industry_forums": "None", + "contact_country": 177, + "head_office_postbox": "1000-119", + "networking": "ECNAIS is active in an informal platform called European Meeting of Independent Education. EMIE is an informal platform that binds together, once a year all organizations with similar purposes.", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": "Ana Sofia Fialho Coelho dos Reis", + "head_office_town": "Den Haag", + "info_members": "The members of the Company shall be such persons nominated pursuant to the principles of the following named bodies (together referred to as \u201cthe Constituent Associations\u201d) shall so long as they remain in membership have the right to nominate a member for election of the Company. \r\n\r\nIn addition such other National Associations of Independent Schools as the Management Committee shall from time to time approve may each nominate 1 person as a member of the Company.", + "head": "90fdf56cff874f0bb8a213be45db6d2c", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Bezuidenhoutseweg, 251-253 32-1E 32-1E", + "activity_inter_groups": "None", + "acronym": "ECNAIS", + "activity_eu_legislative": "Collaboration between national associations of Independent Schools. \r\n\r\nTo function as a network of National Associations To exchange ideas and information. To hold meetings at which to discuss new initiatives in order to strength the European dimension in independent schools. \r\nTo provide information about European education and to disseminate more knowledge about different educational systems. To assist the establishment of E.U. educational projects. \r\nTo organize in service training for headmasters and teachers. To promote participation in international teacher\u00b4s training progammes. To help mobility and network for teachers, students and educational personnel. \r\n\r\nCoordination of National Associations of Independent Schools. To monitor the changing trends towards the Independent Schools in the different European countries. To monitor the political environment with regard to the Independent Schools in European countries. \r\nTo discuss different educational solutions. To audit both governmental and parliamentary documents. To support EU education organisations. To promote understanding of the rights of pluralism in the national systems of education. \r\n\r\nTo be a Forum for working together to establish a common understanding of freedom of education as well as of parental choice. To illuminate public opinion and the EU instances regarding freedom of education and freedom of parental choice. To promote understanding of the rights of parental choice. \r\nTo promote understanding of the vital role of independent schools in a modern democratic society. To further the interest of a all kinds of independent education whose principles conform to those set out in the Universal Declaration of Human Rights. \r\n\r\nTo be a source of contacts for other European countries (Western, Central and Eastern Europe). To be a meeting point with other National Associations of Independent Schools that share the same principles of freedom of education and freedom of parental choice. \r\nTo make agreed representation to the Council of Europe, the European Parliament and the European Union authorities.", + "registration_date": "2015-01-16T17:29:52.689000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "2594 AM", + "goals": "ECNAIS is a non-political, non-confessional, international association for collaboration between national associations of independent schools in European countries. \r\n\r\nECNAIS Supports and pursues the values embedded in a democratic approach to pluralism in the national educational systems, and the respect of the parental choice. \r\nPROMOTES the interests of all kinds of Independent education, confessional and lay, whose principles conform to those set out in the Universal Declaration of Human rights. \r\nDEVELOPS political statements that promote the understanding of the values of the independent sector, and improve their acceptance and financial support in national legislation. \r\nTARGETS policy makers at an international level by representing the Independent sector at the Council of Europe, the European Parliament, The Commission of the European Union and other international organisations, on matters of common concern, based on an agreed programme. ASSISTS current and potential members in their efforts to promote the understanding of the value of a democratic attitude in a plural society.", + "members": 1, + "last_update_date": "2016-04-06T12:42:40.840000Z", + "members_fte": 0.25, + "head_office_phone": "31 70 3315252", + "members_25": 1, + "web_site_url": "http://www.ecnais.org", + "sub_category": 31, + "activity_other": "ECNAIS is a non-political, non-confessional, international association for collaboration between national associations of independent schools in European countries.\r\n\r\nECNAIS is recognized by the Council of Europe and the European Union Commission as a non-government organisation with consultavie status.\r\nIts principal objects are:\r\n\r\n-To bring together national associations of independent schools in European countries.\r\n-To assist its members in promoting understanding of the rights of pluralism in the national systems, of education and of parental choice of education for their children and of the vital role of independent schools in a modern democratic society.\r\n-To further the interests of all kinds of independent education, confessional and lay, whose principles conform to those set out in the Universal Declaration of Human Rights.\r\n- When so requested, to make agreed representation to the Council of Europe, the European Parliament, the European Union Commission and other international organisations on matters of joint concern.", + "name": "European Council of National Associations of Independent Schools", + "created_at": "2015-04-24T02:33:38.686042Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff6ba0bcb497410fa406c9794206bf37", + "identification_code": "153452315640-05", + "legal_status": "Company limited by guarantee", + "members_100": null, + "head_office_lon": null, + "structure_members": "Association of Independent Schools in the Netherlands(2),\r\nF\u00f6rderverband Freier Schulen(1),\r\nAssociation of Private Schools of Bohemia Moravia and Silesia(1),\r\nBulgarian Association of Private Schools(1),\r\nDanish Council for International Cooperation for Independent Schools(2),\r\nAssiociation of Private Schools in Finland(1),\r\nFoudation pour l'ecole(1),\r\nAssociation of Hungarian Independent Schools(1),\r\nFederation of Independent Schools(1),\r\nNational Forum of Non-public Education(1),\r\nPortuguese Association of Independent Schools(2),\r\nEducati\u00f3n Y Gesti\u00f3n/ Escuelas Catolicas(1),\r\nNational Union for the Development of Private Pre-University Education(1),\r\nFOMENTO Education Centers(1),\r\nAssociation of Catholic Schoolboards(1),\r\nVerus(1),\r\nTurkish Private Schools' Association(1),\r\nUkrainian Association of Private Educational Istitutes(1),\r\nStichting Rijdende School(1),\r\nHellenic Private Schools Association(1),\r\nElternlobby(1)", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-26T01:30:01.606285Z", + "entity": "50c6580582f94a34af348a115a00ae2b", + "number_of_natural_persons": null, + "legal": "a7ffe3422509435fbb15f365747978f8", + "native_name": null, + "head_office_country": "Ireland", + "id": "ff698260d45047178a5e8775547815bc", + "activity_industry_forums": "None", + "contact_country": 105, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Dublin", + "info_members": "", + "head": "2382bd341af34ef786218727e8e6c46b", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Old Central Terminal Building, 1st Floor Dublin Airport Dublin Airport", + "activity_inter_groups": "None", + "acronym": "daa", + "activity_eu_legislative": "Air Passenger Rights, Slots, Aviation Security, General Aviation Policy; Environmental Issues, Energy Union, Infrastructure Development", + "registration_date": "2012-04-27T11:56:55.661000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "N/A", + "goals": "To influence the formulation or implementation of policy and decision making processes of the EU Institutions", + "members": 25, + "last_update_date": "2016-03-24T12:49:27.922000Z", + "members_fte": 6.25, + "head_office_phone": "353 1 8141111", + "members_25": 25, + "web_site_url": "http://www.daa.ie/gns/home.aspx", + "sub_category": 21, + "activity_other": "Engagement on Airport Package", + "name": "daa plc", + "created_at": "2015-04-24T02:07:49.792070Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff698260d45047178a5e8775547815bc", + "identification_code": "64031768679-71", + "legal_status": "Operating", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "Participation in BEPA until 2009", + "activity_high_level_groups": "None", + "head_office_lat": 50.01643435, + "updated_at": "2016-03-09T01:52:57.476417Z", + "entity": "40d6d5612dce4849a8422da8868f0570", + "number_of_natural_persons": 9, + "legal": "0ce76701cd904ea082793e5af8572015", + "native_name": null, + "head_office_country": "Germany", + "id": "ff5e850d10a34a8d9e0b6772f68050b2", + "activity_industry_forums": "None", + "contact_country": 82, + "head_office_postbox": "no", + "networking": "SGI Europe Buddhist Association e.V. is a member of Soka Gakkai International, domiciled in Tokyo, Japan", + "members_75": null, + "main_category": 5, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Organisations representing churches and religious communities", + "other_code_of_conduct": null, + "head_office_town": "M\u00f6rfelden-Walldorf", + "info_members": "Matthias Gr\u00f6ninger (chairperson)\r\nHideaki Takahashi (vice (deputy) chairperson)\r\nRobert Samuels (treasurer)\r\nSuzanne Pritchard (member of the board of directors)\r\nJo\u04eblle Troeder (member of the board of directors)\r\nKazuo Fujii (member of the board of directors)", + "head": "9a6e6bafa8a2494fa169854ef3c6757f", + "status": "active", + "main_category_title": "V - Organisations representing churches and religious communities", + "head_office_street": "Nordendstrasse, 38 ", + "activity_inter_groups": "None", + "acronym": "SGI EBA", + "activity_eu_legislative": "We are active in the fields of peace-building through culture and education based on the humanistic principles of Nichiren Buddhism as practised within the SGI movement", + "registration_date": "2014-06-18T14:44:23.915000Z", + "activity_relevant_comm": "We remain open to involvement in activities and projects", + "head_office_post_code": "64546", + "goals": "We are the European branch of the Soka Gakkai International (SGI) a lay Buddhist movement linking together approximately 140,000 members across Europe. (see www.sgi.org for more information).", + "members": 2, + "last_update_date": "2016-03-08T17:23:38.377000Z", + "members_fte": 0.5, + "head_office_phone": "49 610540910", + "members_25": 2, + "web_site_url": null, + "sub_category": 51, + "activity_other": "Our various constituent national organisations are active in interfaith activities and projects aimed at developing tolerance, understanding and cohesion", + "name": "SGI Europe Buddhist Association", + "created_at": "2015-04-24T02:31:28.178188Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff5e850d10a34a8d9e0b6772f68050b2", + "identification_code": "828340313721-55", + "legal_status": "registered association at district court Darmstadt registration number: VR 83170", + "members_100": null, + "head_office_lon": 8.58259536432507, + "structure_members": "http://www.sgi.org/about-us/sgi-facts/sgi-organizations-registered-constituent.html", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-06-04T01:34:25.606548Z", + "entity": "5de9a6d9a53747f6975b9a445620cba3", + "number_of_natural_persons": null, + "legal": "496705ef71014783a6550f088671bb28", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "ff5de8e3812e48caa9147bed2f17c2d3", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": "Innovate Finance, innovatefinance.com\r\n\r\nFuture 50, futurefifty.com", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "London", + "info_members": "", + "head": "04ac790fa23b4605b043b5fe65caf051", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "186 - 188 City Road London London", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "PSD, AMLD, EMD.", + "registration_date": "2015-06-30T12:34:39.762000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "EC1V 2NT", + "goals": "We\u2019re making the world a bit better by helping to make the financial system fair.\r\n\r\nWhen you transfer money internationally, banks and brokers often hide the real cost so you end up paying more in fees than you thought you were going to.\r\nSometimes this is because of the mark-up they put on the exchange rate or because there are additional fees that they just don\u2019t tell you about upfront.\r\n\r\nAt TransferWise, we\u2019re always completely transparent about the total charge and we make that as low as we can. TransferWise is the cheapest and fairest way of transferring money internationally. We\u2019re making sure that it\u2019s our customers that benefit and not the banking system.", + "members": 2, + "last_update_date": "2016-06-03T14:25:12.105000Z", + "members_fte": 1.25, + "head_office_phone": "44 207 250 3119", + "members_25": 1, + "web_site_url": "http://transferwise.com", + "sub_category": 21, + "activity_other": null, + "name": "TransferWise Ltd", + "created_at": "2015-07-07T00:57:02.084724Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff5de8e3812e48caa9147bed2f17c2d3", + "identification_code": "843309518020-96", + "legal_status": "Corporation", + "members_100": 1, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 41.3989444, + "updated_at": "2015-07-07T00:54:39.651407Z", + "entity": "b710ed84a0714ee6bc51f5802ba6f3d8", + "number_of_natural_persons": null, + "legal": "c008150a897b47e4923badc9114a49f0", + "native_name": null, + "head_office_country": "Spain", + "id": "ff4ffaee340a4512af726094b4ef145d", + "activity_industry_forums": "None", + "contact_country": 209, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Professional consultancies", + "other_code_of_conduct": null, + "head_office_town": "BARCELONA", + "info_members": "", + "head": "c008150a897b47e4923badc9114a49f0", + "status": "inactive", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "LLACUNA 22 ", + "activity_inter_groups": "None", + "acronym": "ENERTIKA", + "activity_eu_legislative": "eficiencia energ\u00e9tica", + "registration_date": "2015-06-12T11:49:46.342000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "08005", + "goals": "Presentar nuestra organizaci\u00f3n.", + "members": 2, + "last_update_date": "2015-06-12T12:04:57.328000Z", + "members_fte": 0.5, + "head_office_phone": "34 030000718", + "members_25": 2, + "web_site_url": "http://WWW.ENERTIKA.COM", + "sub_category": 11, + "activity_other": null, + "name": "INGENIERIA Y SERVICIOS DE EFICIENCIA ENERGETICA S.L.", + "created_at": "2015-06-13T00:49:44.804466Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff4ffaee340a4512af726094b4ef145d", + "identification_code": "580103617803-87", + "legal_status": "SOCIEDAD LIMITADA", + "members_100": null, + "head_office_lon": 2.2017422, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2015-09-30T00:50:25.823162Z", + "entity": "eafd9fd5011c4e9194f1c60a8ae53c5c", + "number_of_natural_persons": null, + "legal": "3cd636d80d5a405e8464dc3f13939169", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "ff3f0e3bc4824efaad758a4b11912dd7", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": null, + "members_75": 1, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "IAS was until summer 2015 member of the EU Alcohol and Health Forum", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "London", + "info_members": "", + "head": "bab6f1f9af8746ce98bacebaabaef791", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Alliance House, 12 Caxton Street, London ", + "activity_inter_groups": "None", + "acronym": "IAS", + "activity_eu_legislative": "IAS is actively involved at the European level regarding alcohol policies, such as the EU Alcohol Strategy, information to consumers, taxation, marketing and AVMSD, road safety.", + "registration_date": "2015-09-29T13:43:09.123000Z", + "activity_relevant_comm": "IAS is member of the European Alcohol Policy Alliance (Eurocare) and holds one board seat in Eurocare. IAS is involved in European projects and conferences on alcohol policies.", + "head_office_post_code": "SW1H 0QS", + "goals": "Our main work is based around helping to bridge the gap between the scientific evidence on alcohol and the wider public. We want to make all of this evidence accessible to anyone with an interest in alcohol - politicians, reporters, health professionals, students, youth workers and others - and to advocate for effective responses that will reduce the toll of alcohol in society.", + "members": 2, + "last_update_date": "2015-09-29T13:43:39.428000Z", + "members_fte": 1.0, + "head_office_phone": "44 2072224001", + "members_25": 1, + "web_site_url": "http://www.ias.org.uk", + "sub_category": 31, + "activity_other": null, + "name": "Institute of Alcohol Studies (UK)", + "created_at": "2015-09-30T00:50:25.830572Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3f0e3bc4824efaad758a4b11912dd7", + "identification_code": "150480218577-06", + "legal_status": "charity", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-06-23T02:00:02.214006Z", + "entity": "14ac306c727745d4ad0c65b940d53322", + "number_of_natural_persons": 8, + "legal": "aa3f7ce935604bdab7b28d94d1553129", + "native_name": null, + "head_office_country": "Poland", + "id": "ff3e2e39d8424ab198a14c1ed74b92fc", + "activity_industry_forums": "None", + "contact_country": 176, + "head_office_postbox": null, + "networking": "Sie\u0107 Szk\u00f3\u0142 Nauk Politycznych Rady Europy\r\nhttp://www.schoolsofpoliticalstudies.eu/list-of-schools.aspx", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Warszawa", + "info_members": "", + "head": "b4065d1f8823493092c8a2f7a970cdde", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Oleandr\u00f3w 6 ", + "activity_inter_groups": "None", + "acronym": "EAD", + "activity_eu_legislative": "EU Global Strategy on Foreign and Security Policy", + "registration_date": "2016-06-20T10:41:54.877000Z", + "activity_relevant_comm": "Wsp\u00f3lna Polityka Zagraniczna i Bezpiecze\u0144stwa, aktywno\u015b\u0107 Europejskiej S\u0142u\u017cby Dzia\u0142a\u0144 Zewn\u0119trznych, EU Public Diplomacy, Europejska Polityka S\u0105siedztwa, Partnerstwo Wschodnie", + "head_office_post_code": "00-629", + "goals": "Celem Fundacji jest:\r\na) Kszta\u0142cenie m\u0142odych os\u00f3b zainteresowanych prac\u0105 w administracji krajowej i\r\nzagranicznej ze szczeg\u00f3lnym uwzgl\u0119dnieniem dyplomacji;\r\nb) Promowanie pozytywnego wizerunku Polski w kraju i za granic\u0105;\r\nc) Promowanie wiedzy z zakresu stosunk\u00f3w mi\u0119dzynarodowych;\r\nd) Dzia\u0142alno\u015b\u0107 na rzecz wsp\u00f3\u0142pracy mi\u0119dzynarodowej; \r\n\r\n\r\nFundacja realizuje swoje cele poprzez:\r\na) prowadzenie systematycznych zaj\u0119\u0107 edukacyjnych w charakterze studi\u00f3w;\r\nb) wspieranie i organizowanie kurs\u00f3w, szkole\u0144, seminari\u00f3w, warsztat\u00f3w tematycznych;\r\nc) organizowanie wyk\u0142ad\u00f3w, seminari\u00f3w i konferencji s\u0142u\u017c\u0105cych przekazywaniu wiedzy, gromadzeniu danych i informacji z zakresu dzia\u0142alno\u015bci Fundacji;\r\nd) inicjowanie i wspieranie program\u00f3w szkolenia specjalist\u00f3w r\u00f3\u017cnych dziedzin dla powstaj\u0105cych i rozwijaj\u0105cych si\u0119 instytucji rynku, demokracji i samorz\u0105du lokalnego;\r\ne) inicjowanie i wspieranie program\u00f3w badawczych maj\u0105cych dostarczy\u0107 wiedzy na temat zjawisk spo\u0142ecznych, ekonomicznych i politycznych, w zakresie o\u015bwiaty, kultury, ochrony \u015brodowiska oraz ochrony zdrowia i pomocy spo\u0142ecznej;\r\nf) inicjowanie i wspieranie program\u00f3w i przedsi\u0119wzi\u0119\u0107 podejmowanych przez plac\u00f3wki prowadz\u0105ce dzia\u0142alno\u015b\u0107 naukow\u0105, naukowo-techniczn\u0105, o\u015bwiatow\u0105, kulturaln\u0105\r\n(tak\u017ce kultury fizycznej i sportu), ochrony \u015brodowiska, dobroczynno\u015bci, ochrony zdrowia i pomocy spo\u0142ecznej oraz rehabilitacji zawodowej i spo\u0142ecznej inwalid\u00f3w;\r\ng) inicjowanie i wspieranie kontakt\u00f3w mi\u0119dzynarodowych, s\u0142u\u017c\u0105cych nawi\u0105zywaniu wsp\u00f3\u0142pracy na rzecz rozwoju demokracji, rynku, nauki, kultury, sztuki i o\u015bwiaty oraz\r\nwymiany informacji;\r\nh) Inicjowanie i wspieranie program\u00f3w informacyjnych, s\u0142u\u017c\u0105cych krzewieniu wiedzy na temat mechanizm\u00f3w rynkowych, instytucji demokracji, praw obywatelskich, a tak\u017ce propagowaniu postawy obywatelskiej oraz ekonomicznej samodzielno\u015bci i inicjatywy;\r\ni) wsp\u00f3\u0142prac\u0119 z w\u0142adzami samorz\u0105dowymi, rz\u0105dowymi i organizacjami pozarz\u0105dowymi w zakresie wymienionym w celach dzia\u0142ania Fundacji;\r\nj) organizowanie i koordynowanie pilota\u017cowych program\u00f3w badawczych oraz pracy grup ekspert\u00f3w;\r\nk) wspomaganie spo\u0142ecznych inicjatyw zbie\u017cnych z celami Fundacji;\r\nl) dzia\u0142ania na rzecz interes\u00f3w grup marginalizowanych spo\u0142ecznie; \r\nm) organizowanie i finansowanie bada\u0144 dotycz\u0105cych tworzenia i stosowania prawa;\r\nn) wsp\u00f3\u0142prac\u0119 z osobami, instytucjami krajowymi oraz zagranicznymi prowadz\u0105cymi dzia\u0142alno\u015b\u0107 w zakresie obj\u0119tym dzia\u0142alno\u015bci\u0105 Fundacji; \r\n\r\nOpr\u00f3cz realizacji inicjowanych przez siebie przedsi\u0119wzi\u0119\u0107, Fundacja wsp\u00f3\u0142dzia\u0142a z innymi instytucjami, organizacjami i osobami dla osi\u0105gania wsp\u00f3lnych cel\u00f3w\r\nstatutowych. Wsp\u00f3\u0142dzia\u0142anie to mo\u017ce mie\u0107 charakter wsparcia organizacyjnego, cz\u0119\u015bciowego lub ca\u0142kowitego finansowania przedsi\u0119wzi\u0119cia albo pomocy w uzyskaniu\r\nniezb\u0119dnych funduszy z innych \u017ar\u00f3de\u0142.", + "members": 1, + "last_update_date": "2016-06-22T10:16:21.966000Z", + "members_fte": 0.25, + "head_office_phone": "48 22 205 06 18", + "members_25": 1, + "web_site_url": "http://diplomats.pl/", + "sub_category": 31, + "activity_other": null, + "name": "Europejska Akademia Dyplomacji", + "created_at": "2016-06-21T02:01:15.432879Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3e2e39d8424ab198a14c1ed74b92fc", + "identification_code": "397716222322-37", + "legal_status": "Fundacja", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-09T01:47:07.392731Z", + "entity": "e1f1e5abffaf4f109f38d141ab6191d9", + "number_of_natural_persons": 33, + "legal": "75619ec6640248049fe0c5d325c6e2d0", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "ff3d3f236e4747af9fc50ff58ddb4377", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": "1376", + "networking": "Religious Liberty Partnership", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Luton", + "info_members": "Vicki Salkin, Advocacy and Development Manager", + "head": "234619020a0847b9be2d14b8b0b4a707", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "PO Box 1376 ", + "activity_inter_groups": "Contact with the Intergroup on Freedom of Religion and Belief and Religious Tolerance, and attendance at hearings and other activities hosted by this Intergroup.", + "acronym": "MEC", + "activity_eu_legislative": "Activities of the EEAS, and the Foreign Affairs and Human Rights Committees, with a special focus on freedom of religion and belief.", + "registration_date": "2014-05-20T13:25:59.855000Z", + "activity_relevant_comm": "Policy implementation of EU Guidelines on the promotion and protection of freedom of religion or belief.", + "head_office_post_code": "LU1 9PP", + "goals": "Middle East Concern is a coalition of Christian organisations and individuals that promotes religious freedom in the Middle East and North Africa region, with a special focus on the Christian communities.", + "members": 1, + "last_update_date": "2016-03-08T10:33:23.289000Z", + "members_fte": 0.25, + "head_office_phone": "44 7408 884 202", + "members_25": 1, + "web_site_url": "http://www.meconcern.org", + "sub_category": 31, + "activity_other": "Engagement with MEPs and the European External Action Service to assist victims in individual cases of Freedom of Religion or Belief violations, and to address underlying causes of these violations in the Middle East and North Africa region.\r\n\r\nParticipation in European Parliament hearings, consultations and other meetings in Brussels relevant to our mandate.", + "name": "Middle East Concern", + "created_at": "2015-04-24T02:28:02.887563Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3d3f236e4747af9fc50ff58ddb4377", + "identification_code": "814728213659-93", + "legal_status": "Not for profit / NGO", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 53.1389846, + "be_office_lat": 50.84595215, + "updated_at": "2016-08-31T01:28:06.743898Z", + "entity": "7486afe72dcd45dc9ed4331ac4b87b84", + "number_of_natural_persons": null, + "legal": "7e9d854f81624abfb77aa212a7a7a9f3", + "native_name": null, + "head_office_country": "Germany", + "id": "ff3855a7d5c54d27947ce7773f6b3357", + "activity_industry_forums": "None", + "contact_country": 82, + "head_office_postbox": null, + "networking": "EWE ist aufgrund seiner Struktur Mitglied in zahlreichen Verb\u00e4nden und Foren, wie u.a. dem Bundesverband der Energie- und Wasserwirtschaft (bdew), dem Verband kommunaler Unternehmen (VKU), dem Bundesverband Breitbandkommunikation (BREKO), dem European Energy Forum (EEF) oder der European Federation of Energy Traders (EFET). \u00dcber die Mitgliedschaften im VKU und bdew, ist EWE im Rahmen des Europ\u00e4ischen Dachverbandes der lokalen und regionalen Energieunternehmen (CEDEC) sowie EURELECTRIC aktiv. Die Mitgliedschaften unterst\u00fctzen die Arbeit der EWE auf Ebene der Europ\u00e4ischen Union.", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "Task Force Smart Grid (EG 3)", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Oldenburg", + "info_members": "Sebastian Schulte-Derne, Beauftragter Br\u00fcssel\r\nDr. Eberhard Meller (Senior Counselor, part-time)", + "head": "61d6249ecf2e4d1cadcc5a37599949e6", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Tirpitzstra\u00dfe, 39 ", + "be_office_post_code": "1040", + "activity_inter_groups": "None", + "acronym": "EWE AG", + "activity_eu_legislative": "Dossiers v.a. der EU-Energiepolitik, u.a. der Rahmen f\u00fcr die Klima- und Energiepolitik 2030, der Vorschlag zur Einrichtung und Anwendung einer Marktstabilit\u00e4tsreserve f\u00fcr das EU-System f\u00fcr den Handel mit Treibhausgasemissionszertifikaten; die Richtlinie \u00fcber M\u00e4rkte f\u00fcr Finanzinstrumente; die Verordnung \u00fcber die Integrit\u00e4t und Transparenz des Energiegro\u00dfhandelsmarktes (REMIT) sowie die Richtlinie \u00fcber den Aufbau der Infrastruktur f\u00fcr alternative Kraftstoffe.", + "registration_date": "2012-02-06T15:22:29.163000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "26122", + "goals": "Als innovativer Dienstleister mit regionaler Ausrichtung ist EWE in den Gesch\u00e4ftsbereichen Energie, Telekommunikation und Informationstechnologie aktiv. \r\n\r\nDie Vereinigung dieser drei Felder unter einem Dach erm\u00f6glicht es dem Konzern intelligente Energiesysteme zu entwickeln und zu betreiben. Durch eine Reihe von innovativen Produkten f\u00fcr Privat- und Gesch\u00e4ftskunden gestaltet EWE auf diese Weise die Energieversorgung der Zukunft mit gr\u00f6\u00dftm\u00f6glicher Nachhaltigkeit, Effizienz und Zuverl\u00e4ssigkeit. \r\n\r\nMit mehr als 9.000 Mitarbeitern und \u00fcber acht Milliarden Euro Umsatz geh\u00f6rt EWE zu den gro\u00dfen Energieunternehmen in Deutschland. Der Konzern mit Hauptsitz im nieders\u00e4chsischen Oldenburg befindet sich \u00fcberwiegend in kommunaler Hand. Er beliefert im Nordwesten Deutschlands, in Brandenburg und auf R\u00fcgen sowie international in Teilen Polens und der T\u00fcrkei rund 1,5 Millionen Kunden mit Strom und Gas sowie rund 700.000 Kunden mit Telekommunikationsdienstleistungen. Hierf\u00fcr betreiben verschiedene Unternehmen der EWE-Gruppe mehr als 180.000 Kilometer Energie- und Telekommunikationsnetze.", + "members": 2, + "last_update_date": "2016-08-30T09:56:43.802000Z", + "members_fte": 2.0, + "head_office_phone": "49 0441 480500", + "be_office_town": "Br\u00fcssel", + "members_25": null, + "web_site_url": "http://www.ewe.com", + "sub_category": 21, + "activity_other": null, + "be_office_postbox": null, + "name": "EWE Aktiengesellschaft", + "be_office_street": "Avenue de Cortenbergh 172 ", + "created_at": "2015-05-07T21:24:27.391519Z", + "be_office_country": "Belgium", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff3855a7d5c54d27947ce7773f6b3357", + "identification_code": "00741337988-18", + "legal_status": "Aktiengesellschaft", + "members_100": 2, + "be_office_phone": "32 27438110", + "be_office_lon": 4.39140462709525, + "head_office_lon": 8.1962705, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 52.2070386, + "updated_at": "2016-07-22T01:38:25.249158Z", + "entity": "3ba2dd6a9fa8476287958f7e5c9fe427", + "number_of_natural_persons": null, + "legal": "bb554fda058e4557b86b4aa85f1dee23", + "native_name": null, + "head_office_country": "Poland", + "id": "ff2e01dcb4264779be6aad1d601392b7", + "activity_industry_forums": "None", + "contact_country": 176, + "head_office_postbox": null, + "networking": "Stowarzyszenie Kreatywna Polska www.kreatywnapolska.pl", + "members_75": null, + "main_category": 2, + "members_50": 1, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "Warszawa", + "info_members": "", + "head": "bb554fda058e4557b86b4aa85f1dee23", + "status": "inactive", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "St\u0119pi\u0144ska 22/30 ", + "activity_inter_groups": "None", + "acronym": "Sygna\u0142", + "activity_eu_legislative": "1. Digital Single Market Strategy\r\n2. Przegl\u0105d Dyrektywy Audiowizualnej\r\n3. Reforma Prawa Autorskiego", + "registration_date": "2015-07-20T14:21:47.515000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "00-739", + "goals": "Stowarzyszenie Sygna\u0142 dzia\u0142a na rzecz poszanowania w\u0142asno\u015bci intelektualnej, praw nadawc\u00f3w, dystrybutor\u00f3w, licencjodawc\u00f3w oraz odbiorc\u00f3w program\u00f3w telewizyjnych i innych tre\u015bci multimedialnych. Jego pocz\u0105tki si\u0119gaj\u0105 2001 roku. Obecnie w sk\u0142ad Stowarzyszenia wchodz\u0105 22 firmy dzia\u0142aj\u0105ce w bran\u017cy medi\u00f3w i telekomunikacji.\r\n\r\nSygna\u0142 skupia swoje dzia\u0142ania wok\u00f3\u0142 propagowania konieczno\u015bci efektywnej ochrony w\u0142asno\u015bci intelektualnej. Realizuje swoje cele poprzez organizacj\u0119 szkole\u0144 i warsztat\u00f3w (w tym dla firm cz\u0142onkowskich oraz organ\u00f3w \u015bcigania), prowadzenie kampanii edukacyjnych, przygotowywanie raport\u00f3w, bada\u0144 i stanowisk na tematy zwi\u0105zane z ochron\u0105 w\u0142asno\u015bci intelektualnej.", + "members": 3, + "last_update_date": "2015-07-20T14:23:51.987000Z", + "members_fte": 1.0, + "head_office_phone": "48 22 848 51 29", + "members_25": 2, + "web_site_url": "http://sygnal.org.pl", + "sub_category": 25, + "activity_other": null, + "name": "Stowarzyszenie Sygna\u0142", + "created_at": "2015-07-21T01:03:37.663899Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff2e01dcb4264779be6aad1d601392b7", + "identification_code": "208598218249-90", + "legal_status": "Stowarzyszenie", + "members_100": null, + "head_office_lon": 21.0375624, + "structure_members": "A+E Networks\r\nBBC Worldwide Polska\r\nCyfrowy Polsat\r\nDiscovery Polska\r\nFOX International Channels Poland\r\nHBO Polska\r\nIrdeto\r\nITI Neovision\r\nKino Polska TV\r\nMTG World Ltd\r\nMultimedia Polska\r\nNAGRA\r\nGrupa Onet\r\nSony Pictures Television\r\nTelewizja Polsat\r\nTurner Broadcasting System Poland\r\nTVN\r\nUniversal Networks International\r\nViacom International Media Networks Northern Europe\r\nThe Walt Disney Company (Polska)\r\nZPR Media", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-06-01T01:18:27.242764Z", + "entity": "83e2a7225e074cda8317a50c35512eb0", + "number_of_natural_persons": null, + "legal": "7461491a69334e6f9b4c31663a0a1512", + "native_name": null, + "head_office_country": "Belgium", + "id": "ff2dcae924f245828146c2bb86178fde", + "activity_industry_forums": "None", + "contact_country": 21, + "head_office_postbox": null, + "networking": "NEANT", + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Self-employed consultants", + "other_code_of_conduct": "Code de conduite de la Sophrologie", + "head_office_town": "BEUZET", + "info_members": "NEANT", + "head": "7461491a69334e6f9b4c31663a0a1512", + "status": "inactive", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "12 A rue des Taillettes ", + "activity_inter_groups": "None", + "acronym": "JYL", + "activity_eu_legislative": "NEANT", + "registration_date": "2014-04-23T14:00:43.123000Z", + "activity_relevant_comm": "NEANT", + "head_office_post_code": "5030", + "goals": "- Pr\u00e9vention des risques fiscaux transnationaux infra et extra europ\u00e9ens\r\n- Exercice des principes de subsidiarit\u00e9 dans les rapports transnationaux sociaux infra et extra europ\u00e9ens", + "members": 1, + "last_update_date": "2015-04-30T17:25:18.573000Z", + "members_fte": 1.0, + "head_office_phone": "32 478693508", + "members_25": null, + "web_site_url": null, + "sub_category": 13, + "activity_other": "NEANT", + "name": "Jacques Y. LEIBOVITCH", + "created_at": "2015-05-07T21:41:48.375353Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff2dcae924f245828146c2bb86178fde", + "identification_code": "520259613506-88", + "legal_status": "ind\u00e9pendant", + "members_100": 1, + "head_office_lon": null, + "structure_members": "NEANT", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-01-23T02:47:18.371076Z", + "entity": "dcb5ab6757054a2ba6dab325168c035f", + "number_of_natural_persons": null, + "legal": "e1faea297e1049c4a965b66fec482503", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "ff2c0482fa3f45f2a7f6b111849f11a9", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Self-employed consultants", + "other_code_of_conduct": null, + "head_office_town": "London", + "info_members": "", + "head": "e1faea297e1049c4a965b66fec482503", + "status": "inactive", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "Suite 177 372 Old street 372 Old street", + "activity_inter_groups": "The years I have been lobbying I have mostly followed the ITREE committee", + "acronym": null, + "activity_eu_legislative": "Contribute with input to different committees as ITRE, INTA and the Commission.", + "registration_date": "2015-12-02T12:13:12.207000Z", + "activity_relevant_comm": "Somerco have handed out several draft proposals to the MEPs in the European Parliament and also the Commission. See the list below:\r\nDraft proposals Enhance the competitiveness of EU member states \r\nPart 1 \u2013 Designated tax to science Enhance the competitiveness of EU member states \r\nPart 2 \u2013 Strategy to support the software industry Enhance the competitiveness of EU member states \r\nPart 3 \u2013 Actions to support women in ICT Enhance the competitiveness of EU member states \r\nPart 4 \u2013 Going abroad\u2013Competitive assets Enhance the competitiveness of EU member states \r\nPart 5 \u2013 Business incubators, financial recycling and incentives into reward Enhance the competitiveness of EU member states \r\nPart 6 \u2013 Standardization as a tool to increase competitiveness Enhance the competitiveness of EU member states \r\nPart 7 \u2013 Different types of innovations Enhance the competitiveness of EU member states \r\nPart 8 \u2013 Open source from science to society Enhance the competitiveness of EU member states \r\nPart 9 \u2013 Crowd sourcing and crowd funding Enhance the competitiveness of EU member states \r\nPart 10 \u2013 Green VAT for business Enhance the competitiveness of EU member states \r\nPart 11 \u2013 Keep talent in Europe Enhance the competitiveness of EU member states \r\nPart 12 \u2013 Research leftovers Enhance the competitiveness of EU member states \r\nPart 13 \u2013 Science Parks - Specializations Enhance the competitiveness of EU member states \r\nPart 14 \u2013 Patent trolls Enhance the competitiveness of EU member states \r\nPart 15 \u2013 Science e - Parks Enhance the competitiveness of EU member states \r\nPart 16 \u2013 Expansion options Enhance the competitiveness of EU member states \r\nPart 17 \u2013 The locally developed infrastructure Enhance the competitiveness of EU member states \r\nPart 18 \u2013 Treaty (Knowledge transfer) Enhance the competitiveness of EU member states \r\nPart 19 \u2013 Different types of infrastructure Enhance the competitiveness of EU member states \r\nPart 20 \u2013 Build infrastructure Enhance the competitiveness of EU member states \r\nPart 21 \u2013 Energy infrastructure (elsewhere) (In progress) \r\nEnhance the competitiveness of EU member states \r\nPart 22 \u2013 Quick market entry (Medical) Enhance the competitiveness of EU member states \r\nPart 23 \u2013 Innovation, Commercialization, Growth Enhance the competitiveness of EU member states \r\nPart 24 \u2013 External energy dependencies Enhance the competitiveness of EU member states \r\nPart 25 \u2013 Old innovations Enhance the competitiveness of EU member states \r\nPart 26 \u2013 The non-IP Parks Enhance the competitiveness of EU member states \r\nPart 27 \u2013 Digital inequality into prosperous society Enhance the competitiveness of EU member states \r\nPart 28 \u2013 Digital Magna Carta \u2013 exemptions in privacy Enhance the competitiveness of EU member states \r\nPart 29 \u2013 The networked subsidiarity (In progress) Enhance the competitiveness of EU member states \r\nPart 30 \u2013 Artic route (counterbalance) Enhance the competitiveness of EU member states \r\nOverview \u2013 Old and new key areas in order to increase the competitiveness of the industry (In progress) \r\nInput on threats against information society.", + "head_office_post_code": "EC1V 9LT", + "goals": "Somerco aims to help companies, governmental organisations and persons to succeed with increasing trade. It will create job growth. We do this online and offline.", + "members": 1, + "last_update_date": "2015-12-02T13:05:30.145000Z", + "members_fte": 0.25, + "head_office_phone": "44 7733824711", + "members_25": 1, + "web_site_url": null, + "sub_category": 13, + "activity_other": "I do not know if theer was a mistake doen when it was time for a renewal. Somerco has been registered in the Transparency register a few years before.", + "name": "Somerco", + "created_at": "2015-12-03T02:37:11.313688Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff2c0482fa3f45f2a7f6b111849f11a9", + "identification_code": "035508519773-34", + "legal_status": "Limitied company", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "Analysis, monitoring, communicating with DGs officers or theme related sub-sections (e.g. Executive Agencies) or external national services which are commisioned through the European Commission, related to the above mentioned policy fields in relation to the aforementioned ICCM program initiative.", + "head_office_lat": null, + "updated_at": "2016-08-02T02:02:57.823297Z", + "entity": "7a85467a724b420a9943dedced251363", + "number_of_natural_persons": null, + "legal": "bea73ab6ec8c4ae3863da0a781add3ed", + "native_name": null, + "head_office_country": "Germany", + "id": "ff1ddb8bfd7149b6888de10daaac1839", + "activity_industry_forums": "None", + "contact_country": 82, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Self-employed consultants", + "other_code_of_conduct": null, + "head_office_town": "Berlin", + "info_members": "The operational workload including research, communication, administration and further tasks generated through engagement for European Union themes and affairs, should be basically considered as a contribution of the private sector and as such must be basically compensated. In particular, if the workload is rendered by smallest market participants.", + "head": "bea73ab6ec8c4ae3863da0a781add3ed", + "status": "active", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "Borsigstr. 9 ", + "activity_inter_groups": "None", + "acronym": "gmjw", + "activity_eu_legislative": "Culture and Education; Entrepreneurship; External Relations; Neighbouring Policies; Sustainable Development; Coherency; Internal Markets; Research;", + "registration_date": "2016-06-26T20:35:55.739000Z", + "activity_relevant_comm": "Program initiative for Intercivilizational / Intercultural Dialogue, Development and Cooperation (ICCM)\r\n\r\n(in development)", + "head_office_post_code": null, + "goals": "gmjw consulting is dedicated to the diversity of cultures and creativity as the central root and expression of human abilities, social interrelations, identity, intercultural dialogue and exchange, and as a key driving factor for development, progress, wealth, community building, civil societies and stability.\r\n\r\ngmjw consulting develops, contributes and carries out operational and strategic value for content, individuals, projects, organisations and frameworks, in particular - but not limited - for smaller organisations, small business and single professionals.\r\n\r\ngmjw consulting supports the encouragement and promotion of cultural entrepreneurship through strategic and operational contributions such as,\r\n\r\n- assistance and support by accompanied consultancy and mentorship,\r\n- project-oriented or temporarily aligned services and mandates,\r\n- contributions and research for the development and improvement of sector and segment specific policy and advocacy frameworks, and\r\n- commitment for cooperation, networking and community building.", + "members": 1, + "last_update_date": "2016-08-01T10:16:17.440000Z", + "members_fte": 1.0, + "head_office_phone": "49 3020008400", + "members_25": null, + "web_site_url": "http://www.gmjw.net", + "sub_category": 13, + "activity_other": "I am not sure which other group may be right to be selected. As so far, I have dealt only with groups as described above.", + "name": "gmjw consulting - Martin JW Hannemann", + "created_at": "2016-06-28T02:12:32.449916Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff1ddb8bfd7149b6888de10daaac1839", + "identification_code": "176405522467-72", + "legal_status": "Sole entrepreneur", + "members_100": 1, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-06-17T02:04:41.455253Z", + "entity": "fa393bf592b94f44ac194ad7275d1227", + "number_of_natural_persons": 15, + "legal": "bf45cc3122db432e98f7dbfbdbaec6a4", + "native_name": null, + "head_office_country": "Hungary", + "id": "ff1754756bf64805831e8bb4c762109a", + "activity_industry_forums": "None", + "contact_country": 99, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Budapest", + "info_members": "", + "head": "78d06c33eef140bb996ab3d36ac294cd", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Damjanich utca 51 ", + "activity_inter_groups": "None", + "acronym": "K-Monitor", + "activity_eu_legislative": "Public procurement, access to information, copyright, anti-corruption, whistleblowing", + "registration_date": "2016-06-15T11:00:43.648000Z", + "activity_relevant_comm": "k-monitor.hu\r\nredflags.eu\r\nk.blog.hu", + "head_office_post_code": "1071", + "goals": "K-Monitor is an anti-corruption grass root NGO founded in 2007. K-Monitor strives against corruption and promotes the transparency of public spending in Hungary. K-Monitor operates open data websites, conducts research and advocates for legal reform. With the contribution of our researches, analyses and recommendations, we aim to challenge and overcome the social indifference to corruption, to raise awareness and disseminate knowledge. We truly believe that information technology can contribute to a more open, more transparent and more democratic way of governing. Therefore K-Monitor develops databases and online tools by which public expenses become trackable, and decision makers can be hold accountable.\r\nPrinciples of our operation are openness, independence and a critical approach.", + "members": 1, + "last_update_date": "2016-06-15T11:01:31.597000Z", + "members_fte": 0.25, + "head_office_phone": "36 17895005", + "members_25": 1, + "web_site_url": "http://k-monitor.hu", + "sub_category": 31, + "activity_other": null, + "name": "K-Monitor K\u00f6zhaszn\u00fa Egyes\u00fclet", + "created_at": "2016-06-17T02:04:41.460045Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff1754756bf64805831e8bb4c762109a", + "identification_code": "745636122335-90", + "legal_status": "public benefit assiciation", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2015-10-15T00:50:17.979238Z", + "entity": "068450584cd44111b84e342ff687d122", + "number_of_natural_persons": null, + "legal": "0e3d7caca9d34f01891a740bde3f91b0", + "native_name": null, + "head_office_country": "United States", + "id": "ff1152a3aa88470388abb9d823c78a3d", + "activity_industry_forums": "None", + "contact_country": 234, + "head_office_postbox": null, + "networking": "U.S. Chamber of Commerce", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": "DC Bar Association, Missouri Bar Association", + "head_office_town": "Washinghton DC", + "info_members": "", + "head": "1c3ebb576bba4e1abba16bcdf6e7363b", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "1150 Connecticut Avenue NW 12th Floor 12th Floor", + "activity_inter_groups": "None", + "acronym": "NAMI", + "activity_eu_legislative": "Food safety, trade, food labeling", + "registration_date": "2015-10-14T15:06:35.057000Z", + "activity_relevant_comm": "Nothing in the EU to date.", + "head_office_post_code": "22101", + "goals": "NAMI represents the North American meat industry. Our goal is to be the voice of that industry on public policy issues.", + "members": 1, + "last_update_date": "2015-10-14T15:07:37.490000Z", + "members_fte": 0.25, + "head_office_phone": "1 2025874200", + "members_25": 1, + "web_site_url": "http://meatinstitute.org", + "sub_category": 25, + "activity_other": null, + "name": "North American Meat Institute", + "created_at": "2015-10-15T00:50:17.984658Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff1152a3aa88470388abb9d823c78a3d", + "identification_code": "863092419193-72", + "legal_status": "501(c)(6) under U.S. law trade association", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-09T01:49:38.223999Z", + "entity": "7614fa2ab8db4b7db6a7e5f9fa306793", + "number_of_natural_persons": null, + "legal": "d942401f93b84f98848b89a649d2e9b5", + "native_name": null, + "head_office_country": "Spain", + "id": "ff0fb4adff974d2aa5b69dae56b23639", + "activity_industry_forums": "None", + "contact_country": 209, + "head_office_postbox": null, + "networking": "Deloitte Espa\u00f1a es miembro del Instituto de Censores Jurados de Cuentas de Espa\u00f1a.", + "members_75": null, + "main_category": 1, + "members_50": 2, + "activity_expert_groups": "None", + "sub_category_title": "Professional consultancies", + "other_code_of_conduct": "Estamos sujetos a un C\u00f3digo de Conducta interno de nuestra empresa.", + "head_office_town": "Madrid", + "info_members": "", + "head": "6f47b0aa751a49a59be60e8d06db0144", + "status": "active", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "Pza. Pablo Ruiz Picasso, 1, ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "Contabilidad y Auditor\u00eda\r\nCorporate reporting y gobierno Corporativo\r\nCapital Markets Union\r\nData security, cyber security y protection of business privacy\r\nTax \r\nTrade", + "registration_date": "2015-03-06T10:58:07.343000Z", + "activity_relevant_comm": "Deloitte S.L. realiza actos a nivel nacional de las implicaciones de las pol\u00edticas europeas para las empresas espa\u00f1olas; estos actos son, fundamentalmente relativos a regulaci\u00f3n financiera.", + "head_office_post_code": null, + "goals": "Realizaci\u00f3n de auditor\u00edas de cuentas econ\u00f3micas, financieras, inform\u00e1ticas, de transacciones y saldos en internet, de gesti\u00f3n y operativas para cualquier persona f\u00edsica o jur\u00eddica.\r\nRealizaci\u00f3n de auditor\u00edas y asesor\u00edas medioambientales y consultor\u00eda de gesti\u00f3n de patrimonio y proyectos inmobiliarios, as\u00ed como auditor\u00edas y evaluaciones externas de sistemas de prevenci\u00f3n de riesgos laborales.\r\nRealizaci\u00f3n de consultor\u00edas, asesoramientos, estudios sectoriales o empresariales sobre temas econ\u00f3micos, financieros, contables, sectoriales y de gesti\u00f3n de empresas y, en general, sobre todos aquellos relacionados con la informaci\u00f3n, organizaci\u00f3n y planificaci\u00f3n empresarial y de instituciones, incluidos lo servicios de consultor\u00eda y asesoramiento relativos al dise\u00f1o y mejora de los procesos de gesti\u00f3n, an\u00e1lisis y estructura de costes, valoraci\u00f3n de puestos de trabajo, gesti\u00f3n de recursos humanos, planificaci\u00f3n estrat\u00e9gica, gesti\u00f3n de calidad, gesti\u00f3n medioambiental, mejora del conocimiento organizativo, dise\u00f1o e implementaci\u00f3n de sistemas de informaci\u00f3n, gesti\u00f3n y control de tesorer\u00eda y derivados financieros, exteriorizaci\u00f3n de los departamentos de auditor\u00eda interna y mejora de su funcionamiento, an\u00e1lisis sobre la viabilidad de las empresas, gesti\u00f3n del riesgo inform\u00e1tico y an\u00e1lisis de seguridad en el tratamiento informatizado de datos. o en el tratamiento de informaci\u00f3n en internet y en su transmisi\u00f3n y comunicaci\u00f3n, dise\u00f1o de sistemas de control interno y para el control de riesgos de todo tipo y an\u00e1lisis financieros.\r\nRealizaci\u00f3n de actividades de formaci\u00f3n empresarial y profesional.\r\nPrestaci\u00f3n de servicios en el \u00e1mbito de las Tecnolog\u00edas de la informaci\u00f3n y las Comunicaciones.", + "members": 2, + "last_update_date": "2016-03-08T10:30:27.376000Z", + "members_fte": 1.0, + "head_office_phone": "34 915145000", + "members_25": null, + "web_site_url": "http://www.deloitte.es", + "sub_category": 11, + "activity_other": null, + "name": "Deloitte, S.L.", + "created_at": "2015-04-24T02:29:54.491452Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff0fb4adff974d2aa5b69dae56b23639", + "identification_code": "727712916372-77", + "legal_status": "Sociedad Limitada", + "members_100": null, + "head_office_lon": null, + "structure_members": "Deloitte se refiere a Deloitte Touche Tohmatsu Limited, (private company limited by guarantee, de acuerdo con la legislaci\u00f3n del Reino Unido) y a su red de firmas miembro, cada una de las cuales es una entidad independiente. En www.deloitte.com/about se ofrece una descripci\u00f3n detallada de la estructura legal de Deloitte Touche Tohmatsu Limited y sus firmas miembro.", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "Our experts participate on as needed bases in the activities on various consultative boards within FoodDrinkEurope. \r\nThe positions are then communicated to the relevant part of the EU Commission.", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-02-23T02:22:42.262586Z", + "entity": "81752ab16ef6415b8f9861232e0910a6", + "number_of_natural_persons": null, + "legal": "28df51c6a18a46c69de34b8e5a59f999", + "native_name": null, + "head_office_country": "Croatia", + "id": "ff0cfa2add0f430d8b3d980ee89d9571", + "activity_industry_forums": "None", + "contact_country": 54, + "head_office_postbox": null, + "networking": "FoodDrinksEurope (http://www.fooddrinkeurope.eu/)\r\nCroatian Employers' Association (http://www.hup.hr)\r\nEurocommerce (http://www.eurocommerce.eu/)", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Zagreb", + "info_members": "", + "head": "bd190039cd2f4b1cbd62892aa15bf7d1", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Trg Dra\u017eena Petrovi\u0107a 3 ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "High Level Forum for a Better Functioning Food Supply Chain\r\n\r\nEU Platform on Added Sugar\r\n\r\nRoadmap for Action of the Food Product Improvement", + "registration_date": "2016-02-22T17:25:57.643000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "10000", + "goals": "The Agrokor Group is the largest privately owned company in Croatia and one of the leading regional companies with almost 60,000 employees and reported consolidated total revenues reaching HRK 49 billion. \r\n\r\nThe Agrokor Group's core businesses are the production and distribution of food and beverages and retail. Corporate members include Jamnica d.d., Croatia's largest producer of mineral water, Ledo d.d., Croatia\u2019s leading ice cream company, Zvijezda d.d., the biggest domestic producer of oil, margarine and mayonnaise, the largest Croatian meat industry PIK Vrbovec d.d., Croatia\u2019s leading agricultural and industrial company Belje, and leading largest retail chains Konzum d.d. and Poslovni sistemi Mercator d.d.\r\n\r\nThe leading positions of Agrokor's companies are reflected in their dominant market shares. Ledo dominates Croatia\u2019s ice cream market. Zvijezda enjoys the biggest share of the margarine and edible oils market, while Jamnica fronts Croatia\u2019s bottled water market. Konzum is Croatia\u2019s biggest retail chain and PIK Vrbovec is the leading meat company in the region. Since it was established 30 years ago, due to a clear business vision, a consistently applied company-wide strategy and well-planned investment projects, Agrokor has grown from a small family-owned company for the production and sale of flowers into the leading food industry and retail group in the region today. \r\n\r\nHaving achieved and strengthened its indisputable leadership in the domestic marketplace by staying ahead of changing market demands, Agrokor is now focused on making a step further in an attempt to realize its long-term strategic goal \u2013 becoming a major player throughout the region.", + "members": 1, + "last_update_date": "2016-02-22T17:26:43.984000Z", + "members_fte": 0.25, + "head_office_phone": "385 1 489 4111", + "members_25": 1, + "web_site_url": "http://www.agrokor.hr", + "sub_category": 21, + "activity_other": null, + "name": "Agrokor d.d.", + "created_at": "2016-02-23T02:22:42.269992Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff0cfa2add0f430d8b3d980ee89d9571", + "identification_code": "656353020755-88", + "legal_status": "Private Company", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "be_office_lat": null, + "updated_at": "2016-07-09T02:07:53.609887Z", + "entity": "f83b1695de83443980ec94b4dba61a34", + "number_of_natural_persons": null, + "legal": "88525dc2b8c54a48bd2ea6918cedf357", + "native_name": null, + "head_office_country": "Italy", + "id": "ff091717a1254ae3876bed6b1042569b", + "activity_industry_forums": "None", + "contact_country": 108, + "head_office_postbox": "1", + "networking": null, + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Law firms", + "other_code_of_conduct": null, + "head_office_town": "Milano", + "info_members": "", + "head": "88525dc2b8c54a48bd2ea6918cedf357", + "status": "active", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "Via Barozzi ", + "be_office_post_code": "1000", + "activity_inter_groups": "None", + "acronym": "BE", + "activity_eu_legislative": "Iniziative nel campo del diritto doganale e del diritto fiscale dell'Unione europea", + "registration_date": "2016-06-03T18:28:30.515000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "20122", + "goals": "Studio legale", + "members": 2, + "last_update_date": "2016-07-08T10:47:26.957000Z", + "members_fte": 0.5, + "head_office_phone": "39 02771131", + "be_office_town": "Bruxelles", + "members_25": 2, + "web_site_url": "http://www.belex.com", + "sub_category": 12, + "activity_other": null, + "be_office_postbox": "40", + "name": "Bonelli Erede Pappalardo", + "be_office_street": "Square de Meeus ", + "created_at": "2016-06-04T02:01:11.176016Z", + "be_office_country": "Belgium", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff091717a1254ae3876bed6b1042569b", + "identification_code": "205283422093-55", + "legal_status": "Associazione", + "members_100": null, + "be_office_phone": "32 25520070", + "be_office_lon": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 50.8693821, + "updated_at": "2016-04-07T00:34:47.370083Z", + "entity": "fb4895a76cd84605be4c79a469edd40d", + "number_of_natural_persons": 0, + "legal": "24e8db86b4ac4bdaa00596d0dfab2f6b", + "native_name": null, + "head_office_country": "Belgium", + "id": "ff04fc2f7330408a9b773b91b8272c86", + "activity_industry_forums": "None", + "contact_country": 21, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Brussels", + "info_members": "", + "head": "5b5587fb2bd24c618e7063c1ad838edd", + "status": "inactive", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Avenue des Olympiades 2 ", + "activity_inter_groups": "None", + "acronym": "EFQM", + "activity_eu_legislative": "Horizon 2020- \"Peer Learning for Innovation Agencies\"\r\nEFQM Framework for Innovation Agencies\r\nEuropean Commission\r\nEASME/DG ENTR", + "registration_date": "2015-03-10T10:24:10.228000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "1140", + "goals": "EFQM is a not-for-profit membership foundation based in Brussels, Belgium. With around 450 members covering more than 55 countries and 50 sectors, we provide a unique platform for organisations to learn from each other and improve performance. EFQM is the custodian of the EFQM Excellence Model, a business model which is helping over 30,000 organisations around the globe to strive for Sustainable Excellence.", + "members": 1, + "last_update_date": "2015-11-27T11:33:41.380000Z", + "members_fte": 0.25, + "head_office_phone": "32 27753511", + "members_25": 1, + "web_site_url": "http://www.efqm.org/", + "sub_category": 31, + "activity_other": null, + "name": "EFQM European Foundation for Quality Management", + "created_at": "2015-04-24T02:17:54.703255Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/ff04fc2f7330408a9b773b91b8272c86", + "identification_code": "409256516428-39", + "legal_status": "PRIVATE FOUNDATION", + "members_100": null, + "head_office_lon": 4.4046716, + "structure_members": "http://www.efqm.org/about-us/our-community/our-members", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-26T01:43:17.917951Z", + "entity": "a8e3ccebeae64920945fdec5c3e833ff", + "number_of_natural_persons": null, + "legal": "72d60a38b9954adb9f237dbf2abc079d", + "native_name": null, + "head_office_country": "United States", + "id": "fefa665da246486fa7b4d6f8fd7a3c5a", + "activity_industry_forums": "None", + "contact_country": 234, + "head_office_postbox": null, + "networking": "Intertanko, BIMCO", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Vienna", + "info_members": "", + "head": "2dcd8a7c3d234b9993a25c45420f6470", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "8619 Westwood Center Drive Suite 402 Suite 402", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "YCF Maritime promotes the EU shipping sector by offering EU flag solutions to shipowners which combine responsive and efficient customer service with in-depth technical expertise to ensure their vessels comply with EU and international regulatory requirements. \r\n\r\nYCF Maritime is a keen supporter of EU efforts to achieve a level global playing field for the European shipping industry. YCF Maritime is committed to the principle of a level-playing field within the EU, particularly regarding seafarer social security.\r\n\r\nKey organisations served by our group include EuroFlag Services, SeaNet Maritime Services, Liberian International Ship & Corporate Registry, EMA Manning Agency and EMTI.", + "registration_date": "2015-04-17T10:16:37.333000Z", + "activity_relevant_comm": "Concrete EU policy developments followed by YCF Maritime include the EU Review of Maritime Transport Strategy, Maritime Social Package, Recognized Organisations and Ship Emissions.", + "head_office_post_code": "22182", + "goals": "YCF Maritime is an international service provider with experience in a broad range of ocean shipping matters including vessel ownership, management and operations as well as seafarer training, the development of financial structures and regulatory administration and enforcement. Through its regional offices worldwide, YCF Maritime provides shipowners with comprehensive flag administration options on a global scale.", + "members": 1, + "last_update_date": "2016-03-24T16:27:57.827000Z", + "members_fte": 0.25, + "head_office_phone": "1703 2512406", + "members_25": 1, + "web_site_url": "http://www.ycfgroupllc.com/ycfmaritime.html", + "sub_category": 21, + "activity_other": null, + "name": "YCF Maritime LLC", + "created_at": "2015-04-24T02:21:04.322364Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fefa665da246486fa7b4d6f8fd7a3c5a", + "identification_code": "128313216890-32", + "legal_status": "Limited Liability Company", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-08T02:30:33.883110Z", + "entity": "9a583b6ad41c49bcbb93db186b4408d3", + "number_of_natural_persons": null, + "legal": "2b89e910695c400a93951065b2a46a2a", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "feefe27755c74f6ca7df54e5d2b8b733", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "London", + "info_members": "", + "head": "361ba97fdc614463bc751fb184bc7238", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "160 Queen Victoria Street ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "Key financial markets EU initiatives impacting our clients and funds: \r\nEMIR (European Market Infrastructure Regulation), MiFIR (Markets in Financial Instruments Regulation), CRDIV (Capital Requirements Directive IV), \r\nCMU (Capital Markets Union), \r\nSFTR (The Securities Financing Transactions Regulation), \r\nMMFs (Money Market Fund Regulations), \r\nAIFMD (Alternative Investment Fund Managers Directive), \r\nUCITS (Undertakings for Collective Investments in Transferable Securities), and\r\nFTT (Financial Transaction Tax)", + "registration_date": "2016-03-07T18:47:15.067000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "EC4V 4LA", + "goals": "Insight Investment is a leading global asset manager for institutional investors, particularly pension funds. Our investment management approach is focused on delivering solutions for our clients to provide greater certainty of financial outcome, and a large proportion of our assets is managed on behalf of pension funds in the form of liability risk management mandates, which positions us as one of the largest managers of European pension funds. We closely follow key financial market regulatory initiatives that would have an impact on our clients, and wish to positively engage in this process by providing a voice for European pension funds and other institutional clients.", + "members": 1, + "last_update_date": "2016-03-07T18:47:46.318000Z", + "members_fte": 0.25, + "head_office_phone": "44 207 163 0000", + "members_25": 1, + "web_site_url": "http://www.insightinvestment.com", + "sub_category": 21, + "activity_other": null, + "name": "Insight Investment Management", + "created_at": "2016-03-08T02:30:33.890643Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/feefe27755c74f6ca7df54e5d2b8b733", + "identification_code": "283171720947-78", + "legal_status": "corporation", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 50.68241005, + "updated_at": "2016-03-26T01:46:55.801398Z", + "entity": "af42fc73d40e4bc4bef06e7482ee015d", + "number_of_natural_persons": null, + "legal": "a08398a128c243ac84d2f2bb92299987", + "native_name": null, + "head_office_country": "Germany", + "id": "feed2f70644144b48b258eafe5efae0c", + "activity_industry_forums": "None", + "contact_country": 82, + "head_office_postbox": null, + "networking": "The BfT is a corporate member of the German Association of the Chemical Industry (VCI) and of IFAH (International Federation for Animal Health), the global association of the animal health industry and the European Federation of Animal Health Industry (IFAH Europe).", + "members_75": null, + "main_category": 2, + "members_50": 2, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": "Verbandsinterner Kodex", + "head_office_town": "Bonn", + "info_members": "National association which follows and contributes to relevant european development through involvement in the work of the european sector association.", + "head": "a08398a128c243ac84d2f2bb92299987", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Schwertbergerstr., 14 ", + "activity_inter_groups": "None", + "acronym": "BfT", + "activity_eu_legislative": "Review Veterinary Medicines Regulation\r\nReview Medicated Feed Directive\r\nAnimal Health Regulation\r\n[ VERORDNUNG zur \u00c4nderung der Verordnung (EG) Nr. 726/2004 (Bundesrats-Drucksache 418/14) und den weiteren zugeh\u00f6rigen Vorschl\u00e4gen VERORDNUNG des Europ\u00e4ischen Parlamentes und des Rates \u00fcber die Herstellung, das Inverkehrbringen und die Verwendung von Arzneifuttermitteln sowie zur Aufhebung der Richtlinie 90/167/EWG des Rates (Bundesrats-Drucksache 417/14) und Vorschlag f\u00fcr eine VERORDNUNG des Europ\u00e4ischen Parlaments und des Rates \u00fcber Tierarzneimittel (Bundesrats-Drucksache 420/14) ].", + "registration_date": "2014-08-14T18:07:37.568000Z", + "activity_relevant_comm": "Quarterly newsletter Tiergesundheit im Blickpunkt", + "head_office_post_code": "53177", + "goals": "BfT represents the leading manufacturers of veterinary medicines in Germany.The BfT is a corporate member of the German Association of the Chemical Industry (VCI) and of IFAH (International Federation for Animal Health), the global association of the animal health industry and the European Federation of Animal Health Industry (IFAH Europe). Activities include representing members' interests with legislators, government agencies and professional organizations, supporting high standards of animal health and in the entire food production, sharing information with member companies about relevant latest developments, and informing the public about animal health issues and products.", + "members": 3, + "last_update_date": "2016-03-23T15:04:20.288000Z", + "members_fte": 1.25, + "head_office_phone": "49228 318296", + "members_25": 1, + "web_site_url": "http://www.bft-online.de", + "sub_category": 25, + "activity_other": null, + "name": "Bundesverband fuer Tiergesundheit", + "created_at": "2015-04-24T02:23:50.056410Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/feed2f70644144b48b258eafe5efae0c", + "identification_code": "369699114231-49", + "legal_status": "e.V. (Eingetragener Verein)", + "members_100": null, + "head_office_lon": 7.15161428929912, + "structure_members": "http://www.bft-online.de/mitglieder/", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-17T02:10:27.679053Z", + "entity": "f67d92acd4d54ce192d076051a8ceed4", + "number_of_natural_persons": null, + "legal": "57e1b8f4c48d4974afcbf9d5727c3732", + "native_name": null, + "head_office_country": "Denmark", + "id": "feec5f95637641aa83f9fa5076cd259d", + "activity_industry_forums": "None", + "contact_country": 59, + "head_office_postbox": null, + "networking": "Member of the EURELECTRIC (delegated through the Danish Energy Association)", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "Frederiksberg", + "info_members": "", + "head": "57e1b8f4c48d4974afcbf9d5727c3732", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Vodroffsvej 59, Frederiksberg C ", + "activity_inter_groups": "None", + "acronym": "DEA", + "activity_eu_legislative": "The Alternative Fuels Infrastructure Directive\r\nCO2 Emisssions from Passenger Cars\r\nClean Power for Transport Initiative\r\nWLTP\r\nJuncker Investment Plan", + "registration_date": "2014-11-04T08:35:59.078000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "DK-1900", + "goals": "The Danish Electric Vehicle Alliance works to promote a better political environment for mass roll out of Electric Vehicles, namely battery powered cars and plug in hybrid electric cars, both in Denmark and the EU.\r\n\r\nWe work through providing political incentives for first movers, promoting infrastructure for EV's and educating the public of the possibilities provided by the new electric technology.\r\n\r\nWe are (as of March 2016) four people in an legally autonomous organisation, physically situated within the Danish Energy Association. We represent 47 member companies, Danish and foreign, along every link of the EV value chain.", + "members": 1, + "last_update_date": "2016-03-10T11:11:03.952000Z", + "members_fte": 0.25, + "head_office_phone": "0045 35300491", + "members_25": 1, + "web_site_url": "http://www.danskelbilalliance.dk", + "sub_category": 25, + "activity_other": null, + "name": "Danish Electric Vehicle Alliance", + "created_at": "2015-04-24T02:30:39.870639Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/feec5f95637641aa83f9fa5076cd259d", + "identification_code": "583653114856-56", + "legal_status": "Dansk Elbil Alliance", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2015-07-29T23:29:35.253216Z", + "entity": "403f6e713ed24f529b2e77e909a8e56f", + "number_of_natural_persons": 13, + "legal": "15ce760f485642eaa70fe3e1e639c017", + "native_name": null, + "head_office_country": "Italy", + "id": "fee73f7916f94c36b2f90c4e1b294a51", + "activity_industry_forums": "None", + "contact_country": 108, + "head_office_postbox": null, + "networking": "UNFCCC\r\nGEF\r\nECOSOC of United Nations\r\nUNODC", + "members_75": null, + "main_category": 3, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "casoria", + "info_members": "", + "head": "15ce760f485642eaa70fe3e1e639c017", + "status": "inactive", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Via E. Fermi, 18 ", + "activity_inter_groups": "None", + "acronym": "APK", + "activity_eu_legislative": "Attivita nel settore dell'ambiente a livello comunitario", + "registration_date": "2012-09-29T23:51:11.196000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "80026", + "goals": "Protection of the environment", + "members": 2, + "last_update_date": "2015-02-05T18:27:53.562000Z", + "members_fte": 2.0, + "head_office_phone": "377 9430541", + "members_25": null, + "web_site_url": null, + "sub_category": 31, + "activity_other": "Attivita'di divugazione delle politiche comunitarie nel campo dell'ambiente", + "name": "Amigos do Protocolo de Kyoto", + "created_at": "2015-04-24T02:08:08.971885Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fee73f7916f94c36b2f90c4e1b294a51", + "identification_code": "82132839724-37", + "legal_status": "ONLUS", + "members_100": 2, + "head_office_lon": null, + "structure_members": "APK Italy(4),\r\nAPK Poland(3),\r\nAPK Hungary(2),\r\nAPK Brazil(4)", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-05-25T01:22:39.194553Z", + "entity": "2188e813114a4dd6ad7e3e6e101a2b76", + "number_of_natural_persons": null, + "legal": "2d44c0cba0794197ac8315978742b9b5", + "native_name": null, + "head_office_country": "Netherlands", + "id": "fedf6bda46184c118b81b1950746a169", + "activity_industry_forums": "None", + "contact_country": 155, + "head_office_postbox": null, + "networking": null, + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Bruinehaar", + "info_members": "Taak bovenop reguliere werkzaamheden.", + "head": "2d44c0cba0794197ac8315978742b9b5", + "status": "inactive", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Driehoeksweg 9 ", + "activity_inter_groups": "None", + "acronym": "Pl. EDV", + "activity_eu_legislative": "N2000 dossier en Vogel- en habitatrichtlijn.", + "registration_date": "2015-05-20T21:53:23.653000Z", + "activity_relevant_comm": "Zienswijzen insturen, inspraakprocedure`s benutten,\r\npolitici en pers informeren, contacten onderhouden en informatie uitwisselen met relevante organisatie`s.", + "head_office_post_code": "7675 TA", + "goals": "Het Platform Engbertsdijksvenen (EDV) behartigd de belangen van haar leden die grenzen aan het N2000 gebied het Engbertsdijksvenen.", + "members": 4, + "last_update_date": "2015-05-20T22:07:08.277000Z", + "members_fte": 1.0, + "head_office_phone": "31 620366362", + "members_25": 4, + "web_site_url": null, + "sub_category": 21, + "activity_other": null, + "name": "Platform Engbertsdijksvenen", + "created_at": "2015-05-24T21:45:42.617388Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fedf6bda46184c118b81b1950746a169", + "identification_code": "020890017437-27", + "legal_status": "geen", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-08-18T02:05:44.790468Z", + "entity": "9e06d7fb83cb44588093ab4606de4b74", + "number_of_natural_persons": null, + "legal": "02b132016c10414581d14ba40423cb57", + "native_name": null, + "head_office_country": "Poland", + "id": "fed7ebf4abe64ddaa22834b1e4776fd7", + "activity_industry_forums": "None", + "contact_country": 176, + "head_office_postbox": null, + "networking": "European Rail Freight Association http://www.erfarail.eu/home.asp", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "IGTL jest cz\u0142onkiem European Rail Freight Association, kt\u00f3re jest podmiotem wsp\u00f3\u0142pracuj\u0105cym z KE", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "Warszawa", + "info_members": "", + "head": "02b132016c10414581d14ba40423cb57", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Aleje Jerozolimskie 125/127 ", + "activity_inter_groups": "None", + "acronym": "IGTL", + "activity_eu_legislative": "polityka transportowa, polityka sp\u00f3jno\u015bci, czwarty pakiet kolejowy, TSI, interoperacyjno\u015b\u0107, jednolity europejski obszar kolejowy, sie\u0107 TEN-T, rozporz\u0105dzenie 913/2010 RFC, CEF, RID, CIM,", + "registration_date": "2016-08-17T13:23:06.070000Z", + "activity_relevant_comm": "IGTL wsp\u00f3\u0142pracuje z administracj\u0105 publiczn\u0105 (ministerstwa, Urz\u0105d Transportu Kolejowego, Transportowy Doz\u00f3r Techniczny), reprezentuj\u0105c stanowisko bran\u017cy w szeregu dyskusji na temat regulacji dotycz\u0105cych transportu kolejowego - jest podmiotem bior\u0105cym udzia\u0142 w konsultacjach publicznych w procesie legislacyjnym (ustawy, rozporz\u0105dzenia) oraz dokument\u00f3w i program\u00f3w rz\u0105dowych. IGTL wsp\u00f3\u0142pracuje z narodowym zarz\u0105dc\u0105 infrastruktury, m.in. poprzez udzia\u0142 w Forum Inwestycyjnym (Prezes Izby jest cz\u0142onkiem Prezydium Forum). Izba prowadzi dzia\u0142alno\u015b\u0107 szkoleniow\u0105 dla cz\u0142onk\u00f3w (seminaria, konferencje), obejmuje patronatem najwa\u017cniejsze wydarzenia kolejowe w Polsce i udziela merytorycznego wsparcia poprzez publikacj\u0119 stanowisk i udzia\u0142 przedstawicieli Izby jako prelegent\u00f3w, panelist\u00f3w, itd. Izba prowadzi r\u00f3wnie\u017c dzia\u0142alno\u015bci wydawnicz\u0105 oraz wsp\u00f3\u0142pracuje z bran\u017cowymi wydawcami i pras\u0105, dostarczaj\u0105c stanowisk merytorycznych do publikacji. Izba wsp\u00f3\u0142pracuje z innymi organizacjami bran\u017cowymi w zakresie opisanym powy\u017cej.", + "head_office_post_code": "02-017", + "goals": "Izba Gospodarcza Transportu L\u0105dowego (Land Transport Chamber of Commerce) jest organizacj\u0105 samorz\u0105du gospodarczego dzia\u0142aj\u0105c\u0105 od 1995r. na mocy Ustawy z 30 maja 1989r. o izbach gospodarczych. Izba pe\u0142ni rol\u0119 reprezentanta firm zwi\u0105zanych z transportem kolejowym wobec administracji pa\u0144stwowej oraz r\u00f3\u017cnego rodzaju organizacji krajowych i zagranicznych maj\u0105cych wp\u0142yw na dzia\u0142alno\u015b\u0107 tych przedsi\u0119biorstw. \r\nIzba skupia kilkadziesi\u0105t przedsi\u0119biorstw z ca\u0142ego kraju zwi\u0105zanych z bran\u017c\u0105 kolejow\u0105. Celem Izby jest przede wszystkim ochrona interes\u00f3w firm oraz wyst\u0119powanie do organ\u00f3w administracji pa\u0144stwowej i samorz\u0105dowej z wnioskami i opiniami w zakresie regulacji dotycz\u0105cych szeroko rozumianego transportu kolejowego.\r\nIGTL u\u0142atwia swoim cz\u0142onkom dost\u0119p do wiedzy o aktualnych procesach gospodarczych, szczeg\u00f3lnie tych dotycz\u0105cych transportu i infrastruktury kolejowej. Wsp\u00f3\u0142praca z Izb\u0105 daje cz\u0142onkom mo\u017cliwo\u015b\u0107 bezpo\u015bredniego wp\u0142ywu na kszta\u0142towanie warunk\u00f3w dzia\u0142alno\u015bci i rozwoju transportu kolejowego, a tak\u017ce integruje bran\u017c\u0119 kolejow\u0105.\r\nW IGTL funkcjonuj\u0105 trzy sekcje bran\u017cowe: Przewo\u017anik\u00f3w Kolejowych, Wagon\u00f3w i Spedycji, Budownictwa Kolejowego \r\nCz\u0142onkiem Izby mo\u017ce zosta\u0107 podmiot gospodarczy prowadz\u0105cy dzia\u0142alno\u015b\u0107 gospodarcz\u0105 zgodnie z zasadami etyki zawodowej, z wy\u0142\u0105czeniem os\u00f3b fizycznych prowadz\u0105cych tak\u0105 dzia\u0142alno\u015b\u0107 jako zaj\u0119cie uboczne.", + "members": 8, + "last_update_date": "2016-08-17T13:23:42.060000Z", + "members_fte": 2.75, + "head_office_phone": "48 6540942", + "members_25": 7, + "web_site_url": "http://www.igtl.pl", + "sub_category": 25, + "activity_other": null, + "name": "Izba Gospodarcza Transportu L\u0105dowego", + "created_at": "2016-08-18T02:05:44.797758Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fed7ebf4abe64ddaa22834b1e4776fd7", + "identification_code": "501998723038-69", + "legal_status": "izba gospodarcza", + "members_100": 1, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2015-12-01T02:42:19.420436Z", + "entity": "7abf0809a837474485cfcc035b933d5b", + "number_of_natural_persons": null, + "legal": "5eb772ccd2e04cde9ae9ba82a2b4f16f", + "native_name": null, + "head_office_country": "Italy", + "id": "fed17c17924045649b1e30abb8afd3f3", + "activity_industry_forums": "None", + "contact_country": 108, + "head_office_postbox": null, + "networking": "U.C.E.E. Unione Camere Esperti Europei\r\nwww.ucee.be\r\n\r\nNAFOP National Association Fee Only Planner\r\nwww.nafop.org\r\n\r\nLAPET - Associazione Nazionale Tributaristi\r\nwww.iltributaristalapet.it", + "members_75": 1, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Self-employed consultants", + "other_code_of_conduct": null, + "head_office_town": "Laurenzana", + "info_members": "Dott. Giuseppe Lettini", + "head": "5eb772ccd2e04cde9ae9ba82a2b4f16f", + "status": "active", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "III\u00b0 Vico Vittorio Emanuele 4 ", + "activity_inter_groups": "None", + "acronym": "Studio Lettini", + "activity_eu_legislative": "FINANZIAMENTI EUROPEI\r\nFINANZIAMENTI NAZIONALI\r\nFINANZIAMENTI REGIONALI\r\nINTERNAZIONALIZZAZIONE\r\nSTART UP IMPRESE\r\n\r\nLe attivit\u00e0 che lo studio segue riguardano principalmente il supporto ai clienti nella presentazione di domande di finanziamento per i programmi Horizon 2020, Cosme, Creative Europe.\r\nLa normativa finanziamenti agevolati a favore di piccole medie e grandi imprese coinvolge tutti i settori, da quello industriale a quello turistico, commercio, servizi, agricoltura.\r\n\r\nL\u2019obiettivo \u00e8 lo sviluppo dell\u2019imprenditorialit\u00e0 come avvio d\u2019impresa e/o sviluppo d\u2019impresa", + "registration_date": "2015-11-25T13:36:23.400000Z", + "activity_relevant_comm": "Europrogetti e comunicazioni inerenti i bandi", + "head_office_post_code": "85014", + "goals": "Lo Studio Lettini, offre un servizio di consulenza altamente specializzato nel mondo della finanza pubblica e del controllo di gestione individuando le migliori soluzioni per le innumerevoli necessit\u00e0 finanziarie di ogni tipo di imprese, ente, ecc. Lo studio di consulenza permette e offre soluzioni ed assistenza all\u2019imprenditore o di chi ha un\u2019idea imprenditoriale, attraverso una attenta analisi delle esigenze aziendali, l\u2019individuazione del tipo di finanziamento ottimale, la definizione delle opportune soluzioni organizzative, la creazione del sistema di controllo interno, la compilazione del relativo dossier per una istruttoria in linea con i requisiti legislativi richiesti, \u00e8 sufficiente programmare un qualsiasi intervento aziendale perch\u00e8 l\u2019intervento di Studio Lettini possa far emergere sostanziali utilit\u00e0 per l\u2019impresa.", + "members": 1, + "last_update_date": "2015-11-30T17:01:26.337000Z", + "members_fte": 0.75, + "head_office_phone": "39 3899873276", + "members_25": null, + "web_site_url": "http://www.studiolettini.it", + "sub_category": 13, + "activity_other": "Consulenza in europrogettazione finalizzata al successo nella partecipazione ai bandi europei nella nuova programmazione 2014-2020.", + "name": "Lettini Giuseppe", + "created_at": "2015-12-01T02:42:19.427576Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fed17c17924045649b1e30abb8afd3f3", + "identification_code": "731027919621-04", + "legal_status": "Consulente autonomo", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-07-29T01:38:12.539457Z", + "entity": "a402743e5808426db003a7f1948dbe99", + "number_of_natural_persons": null, + "legal": "1301c3d6c89347b1ab9fc84c383e847e", + "native_name": null, + "head_office_country": "Netherlands", + "id": "fecde2aeabb843f4a8a55a4b3b92de50", + "activity_industry_forums": "None", + "contact_country": 155, + "head_office_postbox": null, + "networking": "cumula", + "members_75": null, + "main_category": 2, + "members_50": 1, + "activity_expert_groups": "None", + "sub_category_title": "Companies & groups", + "other_code_of_conduct": null, + "head_office_town": "Appingedam", + "info_members": "", + "head": "1301c3d6c89347b1ab9fc84c383e847e", + "status": "inactive", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "1ste Industrieweg 16 ", + "activity_inter_groups": "None", + "acronym": "HW", + "activity_eu_legislative": "Klimaat onderwerken, paludicultuur, natuurbeheer", + "registration_date": "2015-07-27T17:07:14.809000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "9902 AM", + "goals": "Wij zijn een bedrijf met als core business the oogst van biomassa en een machinefabriek en we gaan richting een bedrijf in de biobased economie. In die zin bestaan we uit een bedrijf dat een loonbedrijf heeft in de natte gebieden, een machine fabriek en een consultancy.", + "members": 3, + "last_update_date": "2015-07-27T17:35:38.170000Z", + "members_fte": 1.75, + "head_office_phone": "316 36109878", + "members_25": 1, + "web_site_url": "http://hanzewetlands.com", + "sub_category": 21, + "activity_other": null, + "name": "Hanze Wetlands", + "created_at": "2015-07-28T01:16:50.660106Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fecde2aeabb843f4a8a55a4b3b92de50", + "identification_code": "200438718349-72", + "legal_status": "BV", + "members_100": 1, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": 50.8248068, + "updated_at": "2016-03-26T01:19:06.631263Z", + "entity": "e0bb8dab8e9e4bec9a05f9c6a9244b53", + "number_of_natural_persons": 0, + "legal": "3eba6f061ca649d0a4046654ee392dfe", + "native_name": null, + "head_office_country": "Belgium", + "id": "fec76a9f6e224986b3edb9b89e8afad3", + "activity_industry_forums": "None", + "contact_country": 21, + "head_office_postbox": null, + "networking": "WFTO-Europe is one of the five regional branches of the World Fair Trade Organization global network, the other four being: WFTO-Africa/COFTA (the Cooperation for Fair Trade in Africa), WFTO-Asia (World Fair Trade Organization - Asia), WFTO-LA (World Fair Trade Organization \u2013 Latin America) and WFTO Pacific Rim. Together, the five WFTO regional networks come together as regional chapters to represent over 450 members within 75 countries worldwide, that are committed 100% to Fair Trade and its principles.\r\n\r\nFor a detailed view on the WFTO global network, its members and structure, please visit WFTO global website at: http://www.wfto.com/ \r\n\r\nAt European level, WFTO-Europe is a member organization of the Fair Trade Advocacy Office (FTAO) in Brussels. The FTAO is a joint initiative of World Fair Trade Organization \u2013 Europe (WFTO-Europe), Fairtrade International (FLO) and the European Fair Trade Association (EFTA). Through these three networks the FTAO represents an estimate of 2.5 million Fair Trade producers and workers from 70 countries, 24 labelling initiatives, over 500 specialised Fair Trade importers, 4.000 World Shops and more than 100.000 volunteers. The Fair Trade Advocacy Office speaks out for Fair Trade and trade justice with the aim to improve the livelihoods of marginalised producers and workers, especially in the South. \r\n\r\nFor a detailed view on the FTAO\u2019s activities, please visit its website at: http://www.fairtrade-advocacy.org/\r\n\r\nWFTO-Europe is a member of the European inter-network of ethical and responsible initiatives (IRIS, www.irisnetwork.eu), a network create by European networks and organisations, aimed at promoting synergies between them, in order to implement solidarity economy initiatives and to fight against poverty and social exclusion, through a sustainable development and responsible economic approach. IRIS represents different families of responsible economic initiatives: responsible finance (FEBEA, INAISE), Fair Trade (WFTO-Europe), responsible consumption (ASECO), local partnerships between farmers and consumers (URGENCI) and Social Integration Enterprises (ENSIE), with the participation and support of institutional partners (Council of Europe and the Trento Autonomous Province, Italy).\r\n\r\nWFTO-Europe is also a member of the \"Federation of European & International associations based in Belgium\" (FAIB).", + "members_75": null, + "main_category": 3, + "members_50": 1, + "activity_expert_groups": "None", + "sub_category_title": "Non-governmental organisations, platforms and networks and similar", + "other_code_of_conduct": null, + "head_office_town": "Bruxelles", + "info_members": "", + "head": "3eba6f061ca649d0a4046654ee392dfe", + "status": "active", + "main_category_title": "III - Non-governmental organisations", + "head_office_street": "Rue Washington, 40 ", + "activity_inter_groups": "None", + "acronym": "WFTO-Europe", + "activity_eu_legislative": "WFTO-Europe has been following the EU directive on public procurement as well as the main communication and initiatives related to Fair Trade via the Fair Trade Advocacy Office (FTAO).", + "registration_date": "2012-12-18T15:24:10.203000Z", + "activity_relevant_comm": "WFTO-Europe is currently involved in one project at European level: \"Food Smart Cities for Development\".", + "head_office_post_code": "1050", + "goals": "WFTO-Europe, formerly known as IFAT Europe (International Federation for Alternative Trade), represents the European branch of the World Fair Trade Organization (WFTO). It is currently formed by 74 members from 15 countries, amongst them Fair Trade Organizations, Fair Trade Networks and Support Organizations.\r\n\r\nWFTO-Europe stands by WFTO global network\u2019s vision and mission.\r\n\r\nWFTO\u2019s vision: a world in which trade structures and practices have been transformed to work in favour of the poor and promote sustainable development and justice.\r\n \r\nWFTO\u2019s mission: to enable producers to improve their livelihoods and communities through Fair Trade. WFTO will advocate for Fair Trade, ensuring producer voices are heard. The interests of producers, especially small farmers and artisans, should be the main focus in all the policies, governance, structures and decision-making within the World Fair Trade Organization.\r\n\r\nIn its status of regional branch, WFTO-Europe has four strategic aims: \r\n\r\n1.\tSupport the growth and consolidation of WFTO global network.\r\n2.\tBe the reference for Fair Trade in Europe, its representative organ and its voice.\r\n3.\tProtect the noble values of Fair Trade and the 100% commitment to it.\r\n4.\tSupport Fair Trade policies and support the legality of the office.\r\n\r\nIn this respect, one of the most important initiatives of WFTO-Europe is that of facilitating a framework for producer assistance and product development, by:\r\n\r\n- Supporting the monitoring process and WFTO system;\r\n- Serving as a facilitator between members who want to work on producer assistance and product development in a structured and articulated way. Also by facilitating bilateral and multilateral work between them;\r\n- Facilitating and bridging other initiatives and actors working on these key issues (WFTO global and other regional offices, Fair Trade Organizations, other civil society organisations) and informing southern Fair Trade partners on market tendencies in a structured and articulated way. \r\n\r\n\r\nWFTO global network\u2019s aims at large, to which WFTO-Europe shall contribute from a regional level, are to improve the livelihoods of marginalized producers and workers, especially in the South. To change unfair structures of international trade, mainly by means of Fair Trade, to improve and co-ordinate the co-operation of its member organizations and to promote the interests of and provide services to its member organizations and individuals (Source: The Constitution of the World Fair Trade Organization)", + "members": 2, + "last_update_date": "2016-03-23T17:16:01.371000Z", + "members_fte": 1.5, + "head_office_phone": "32 2 640 63 86", + "members_25": null, + "web_site_url": "http://www.wfto-europe.org", + "sub_category": 31, + "activity_other": "Project with local authorities", + "name": "World Fair Trade Organization - Europe", + "created_at": "2015-04-24T01:57:44.867858Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fec76a9f6e224986b3edb9b89e8afad3", + "identification_code": "725848610338-68", + "legal_status": "ASBL - Association Sans But Lucratif (Non-profit association)", + "members_100": 1, + "head_office_lon": 4.36371042912679, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2015-10-30T01:56:56.246954Z", + "entity": "7b46510f154947128c02d05bd79a3358", + "number_of_natural_persons": null, + "legal": "a42346118a234821a8de93818be55c95", + "native_name": null, + "head_office_country": "Switzerland", + "id": "fec607c127414c259cbf2f7f86eb041c", + "activity_industry_forums": "None", + "contact_country": 215, + "head_office_postbox": "CP246", + "networking": null, + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "geneve", + "info_members": "", + "head": "4d7fa8f59ace457388b82ac625f9ef2d", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "maison de la paix, WBCSD chemin Eug\u00e8ne Rigot 2 chemin Eug\u00e8ne Rigot 2", + "activity_inter_groups": "None", + "acronym": "WBCSD", + "activity_eu_legislative": "- Climate Change Strategy\r\n- CSR Strategy\r\n- Biodiversity Strategy\r\n- Sustainability Strategy\r\n- Water and Food and Forest Strategy\r\n- Sustainable City Strategy\r\n- Mobility Strategy", + "registration_date": "2015-10-22T14:38:03.288000Z", + "activity_relevant_comm": "WBCSD is directly involved with the EU Commission on above topics via direct meetings and workshops. \r\nIndirectly the organisation is represented by associated organisations such as Econsense or IETA.\r\nIndirectly the organisation is also represented by its about 200 member companies.", + "head_office_post_code": "1211", + "goals": "The World Business Council for Sustainable Development (WBCSD) is a CEO-led organization of forward-thinking companies that galvanizes the global business community to create a sustainable future for business, society and the environment. Through its members, the Council applies its respected thought leadership and effective advocacy to generate constructive solutions and take shared action to drive business action on sustainability in the coming decade and beyond. The WBCSD aims to be the leading voice of business that will support companies in scaling up true value-added business solutions and in creating the conditions where more sustainable companies will succeed and be recognized. \r\n\r\nMembers work together across sectors, geographies and value chains to explore, develop and scale up business solutions to address the world\u2019s most pressing sustainability challenges. Through our work to change the rules of the game and drive measurable impact, WBCSD is emerging as the leading and most compelling sustainable development business voice with multilateral institutions such as the United Nations, World Bank, UNFCCC, as well as with global platforms like the UN Climate Summit and COP negotiations. \r\n\r\nThe WBCSD is unique because its output is developed and road tested by its members. Its comprehensive work program enables it to cover all aspects of sustainable development in business. To deal effectively with all issues the work program is divided into six Action2020 Clusters , sector and value chain projects, systems solutions and capacity building.\r\n\r\nWe also benefit from a Global Network of 65+ independent national and regional business councils and partner organizations, involving thousands of business leaders, two-thirds in developing countries and emerging economies.", + "members": 1, + "last_update_date": "2015-10-29T16:41:14.433000Z", + "members_fte": 0.25, + "head_office_phone": "41 228393100", + "members_25": 1, + "web_site_url": "http://www.wbcsd.org/home.aspx", + "sub_category": 25, + "activity_other": "WBCSD as a non-profit organisation represents the business voice of it's members based on solid scientific evidence to enhance and facilitate the understanding and direction setting between companies and policy making towards a sustainable society. It is important for policy makers to fully understand the actual potential of advanced business solutions as these are crucial for the successful implementation of policies and strategies mentioned above.", + "name": "World Business Council For Sustainable Development", + "created_at": "2015-10-23T00:55:45.123574Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fec607c127414c259cbf2f7f86eb041c", + "identification_code": "074000219282-17", + "legal_status": "association", + "members_100": null, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-03-05T02:28:51.723088Z", + "entity": "7252c50b894d41e9bf6079782137f31f", + "number_of_natural_persons": null, + "legal": "7cf0eca1988e48ee9021a79332f3f7f9", + "native_name": null, + "head_office_country": "Belgium", + "id": "fec5815bf76348d69521bc170db3d77c", + "activity_industry_forums": "None", + "contact_country": 21, + "head_office_postbox": null, + "networking": "Ei ole.", + "members_75": null, + "main_category": 1, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Professional consultancies", + "other_code_of_conduct": null, + "head_office_town": "Bruxelles", + "info_members": "", + "head": "7cf0eca1988e48ee9021a79332f3f7f9", + "status": "active", + "main_category_title": "I - Professional consultancies/law firms/self-employed consultants", + "head_office_street": "Chauss\u00e9e de Charleroi 143, box 3 ", + "activity_inter_groups": "None", + "acronym": null, + "activity_eu_legislative": "S\u00e4hk\u00f6isen viestinn\u00e4n s\u00e4\u00e4ntely, digitaaliset sis\u00e4markkinat.", + "registration_date": "2016-03-04T14:27:41.702000Z", + "activity_relevant_comm": "J\u00e4rjest\u00e4mme tapaamisia ja harjoitamme tiedonvaihtoa EU-vaikuttajien ja s\u00e4hk\u00f6isen viestinn\u00e4n alan yrityksen kesken.", + "head_office_post_code": "B-1060", + "goals": "Petri Lahesmaa Consulting on EU-vaikuttajaviestint\u00e4\u00e4n erikoistunut yritys. Toimialaamme on EU-vaikuttaminen, s\u00e4hk\u00f6isen viestinn\u00e4n s\u00e4\u00e4ntelyasiat ja EU-journalismi. Petri Lahesmaalla on yli 16 vuoden kokemus EU-vaikuttamisesta sek\u00e4 Brysseliss\u00e4 ett\u00e4 Suomessa.", + "members": 1, + "last_update_date": "2016-03-04T14:35:08.052000Z", + "members_fte": 0.25, + "head_office_phone": "32 0476909496", + "members_25": 1, + "web_site_url": null, + "sub_category": 11, + "activity_other": null, + "name": "Petri Lahesmaa Consulting", + "created_at": "2016-03-05T02:28:51.726617Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fec5815bf76348d69521bc170db3d77c", + "identification_code": "344894120925-87", + "legal_status": "Une entreprise personne physique", + "members_100": null, + "head_office_lon": null, + "structure_members": "Ei ole.", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "be_office_lat": 50.84178695, + "updated_at": "2016-03-09T00:56:50.059467Z", + "entity": "44f5ad8112524b51a08db529e8753272", + "number_of_natural_persons": null, + "legal": "f4a66136f5634ec68be50672e3f2dfa4", + "native_name": null, + "head_office_country": "Denmark", + "id": "feac8ce68d3142848d501f1bf11bf46a", + "activity_industry_forums": "None", + "contact_country": 59, + "head_office_postbox": null, + "networking": "European Energy Forum http://www.europeanenergyforum.eu/\r\nEurelectric http://www.eurelectric.org/\r\n\r\nThe Danish Energy Association also participates in a number of informal networks in Brussels.", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "Frederiksberg C", + "info_members": "", + "head": "5bde983ce5cd4a8ea7d87b79ece7bbc0", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "Rosen\u00f8rns All\u00e9, 9 ", + "be_office_post_code": "1040", + "activity_inter_groups": "None", + "acronym": "DEA", + "activity_eu_legislative": "Energy Union \r\n2030 governance\r\nETS reform\r\nRetail Energy Market: Action Plan\r\nCapacity Mechanisms", + "registration_date": "2008-09-10T13:21:30.828000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "1970", + "goals": "The Danish Energy Association (Dansk Energi) is a commercial and professional organisation for Danish energy companies. It is managed and financed by its member companies, mainly the electricity companies, and works to secure for them the most free and favourable conditions for competition in order to ensure development, growth and business friendly environment in Denmark.\r\n\r\nThe Danish Energy Association represents the interests of its member companies and thus conducts regular contacts with government, authorities etc. nationally and within the EU.", + "members": 2, + "last_update_date": "2016-03-08T09:35:15.467000Z", + "members_fte": 2.0, + "head_office_phone": "45 35300400", + "be_office_town": "Bruxelles", + "members_25": null, + "web_site_url": "http://www.danskenergi.dk", + "sub_category": 25, + "activity_other": "Energy, climate, transport and environmental policy.", + "be_office_postbox": null, + "name": "Danish Energy Association / Dansk Energi", + "be_office_street": "Rue de la Loi 227 ", + "created_at": "2015-04-24T01:47:43.770790Z", + "be_office_country": "Belgium", + "uri": "http://api.lobbyfacts.eu/api/1/representative/feac8ce68d3142848d501f1bf11bf46a", + "identification_code": "1733114388-50", + "legal_status": "Association", + "members_100": 2, + "be_office_phone": "32 491 25 30 23", + "be_office_lon": 4.38526824209953, + "head_office_lon": null, + "structure_members": "", + "code_of_conduct": "European Commission's code of conduct for interest representative" + }, + { + "activity_consult_committees": "None", + "activity_high_level_groups": "None", + "head_office_lat": null, + "updated_at": "2016-07-01T01:37:23.590560Z", + "entity": "3ed6121ae7b54e19bcc1ce7371a0c218", + "number_of_natural_persons": null, + "legal": "9780c60b13234d82b65e1b32c10bbc08", + "native_name": null, + "head_office_country": "United Kingdom", + "id": "fea393c1edda4541847f16497b8d35a8", + "activity_industry_forums": "None", + "contact_country": 233, + "head_office_postbox": null, + "networking": "ENA is a member of EURELECTRIC, GEODE and Eurogas.", + "members_75": null, + "main_category": 2, + "members_50": null, + "activity_expert_groups": "None", + "sub_category_title": "Trade and business organisations", + "other_code_of_conduct": null, + "head_office_town": "London", + "info_members": "", + "head": "f5f91b124a08449ebefe428af0978bcf", + "status": "active", + "main_category_title": "II - In-house lobbyists and trade/professional associations", + "head_office_street": "6th Floor Dean Bradley House Dean Bradley House", + "activity_inter_groups": "None", + "acronym": "ENA", + "activity_eu_legislative": "Single Energy Market and Future Market Design\r\nDSO/TSO Interface\r\nFlexibility services\r\nNetwork Tariffs\r\nInnovation\r\nFuture role for Gas\r\n2030 climate and energy framework\r\nRenewable Sources of Energy\r\nEnergy Efficiency\r\nLow carbon transport", + "registration_date": "2015-07-22T15:58:48.209000Z", + "activity_relevant_comm": "None", + "head_office_post_code": "SW1P 2AF", + "goals": "Energy Networks Association (ENA) is the voice of the networks, representing the electricity and gas transmission and distribution network operators in the UK and Ireland. Our members are diverse, from major international companies to independent network operators. \r\nENA is actively engaged with government, regulators and the EU Commission as well as producing a wide range of industry standards. The impact of regulation, the influence of European legislation, the challenge of new technologies and the importance of securing our energy future, all against the background of national low carbon targets, are just some issues ENA deals with.", + "members": 1, + "last_update_date": "2016-06-30T15:09:08.535000Z", + "members_fte": 1.0, + "head_office_phone": "44 02077065131", + "members_25": null, + "web_site_url": "http://www.energynetworks.org", + "sub_category": 25, + "activity_other": null, + "name": "Energy Networks Association", + "created_at": "2015-07-23T01:03:14.242168Z", + "uri": "http://api.lobbyfacts.eu/api/1/representative/fea393c1edda4541847f16497b8d35a8", + "identification_code": "247299118284-24", + "legal_status": "Private Limited Company", + "members_100": 1, + "head_office_lon": null, + "structure_members": "http://www.energynetworks.org/", + "code_of_conduct": "European Commission's code of conduct for interest representative" + } + ], + "next": "http://api.lobbyfacts.eu/api/1/representative?limit=50&offset=50", + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/misc/77392.json b/test/inputs/json/misc/77392.json index e702f5249..ec2c58d27 100644 --- a/test/inputs/json/misc/77392.json +++ b/test/inputs/json/misc/77392.json @@ -1,202 +1,2401 @@ -[{"designation":"419880 (2011 AH37)","discovery_date":"2011-01-07T00:00:00.000","h_mag":"19.7","i_deg":"9.65","moid_au":"0.035","orbit_class":"Apollo","period_yr":"4.06","pha":"Y","q_au_1":"0.84","q_au_2":"4.26"} -,{"designation":"419624 (2010 SO16)","discovery_date":"2010-09-17T00:00:00.000","h_mag":"20.5","i_deg":"14.52","moid_au":"0.028","orbit_class":"Apollo","period_yr":"1","pha":"Y","q_au_1":"0.93","q_au_2":"1.08"} -,{"designation":"414772 (2010 OC103)","discovery_date":"2010-07-28T00:00:00.000","h_mag":"19","i_deg":"23.11","moid_au":"0.333","orbit_class":"Apollo","period_yr":"1.31","pha":"N","q_au_1":"0.39","q_au_2":"2"} -,{"designation":"414746 (2010 EH20)","discovery_date":"2010-03-06T00:00:00.000","h_mag":"18","i_deg":"23.89","moid_au":"0.268","orbit_class":"Amor","period_yr":"4.24","pha":"N","q_au_1":"1.25","q_au_2":"3.99"} -,{"designation":"407324 (2010 OB101)","discovery_date":"2010-07-18T00:00:00.000","h_mag":"20.7","i_deg":"9.12","moid_au":"0.111","orbit_class":"Apollo","period_yr":"2.06","pha":"N","q_au_1":"0.77","q_au_2":"2.46"} -,{"designation":"398188 (2010 LE15)","discovery_date":"2010-06-03T00:00:00.000","h_mag":"19.5","i_deg":"13.25","moid_au":"0.024","orbit_class":"Aten","period_yr":"0.8","pha":"Y","q_au_1":"0.63","q_au_2":"1.1"} -,{"designation":"395207 (2010 HQ80)","discovery_date":"2010-04-25T00:00:00.000","h_mag":"19.6","i_deg":"27.85","moid_au":"0.007","orbit_class":"Apollo","period_yr":"1.96","pha":"Y","q_au_1":"0.8","q_au_2":"2.34"} -,{"designation":"386847 (2010 LR33)","discovery_date":"2010-06-06T00:00:00.000","h_mag":"18","i_deg":"5.84","moid_au":"0.029","orbit_class":"Apollo","period_yr":"2.2","pha":"Y","q_au_1":"0.91","q_au_2":"2.48"} -,{"designation":"381989 (2010 HR80)","discovery_date":"2010-04-28T00:00:00.000","h_mag":"19.9","i_deg":"26.71","moid_au":"0.104","orbit_class":"Apollo","period_yr":"1.56","pha":"N","q_au_1":"0.68","q_au_2":"2.02"} -,{"designation":"369454 (2010 NZ1)","discovery_date":"2010-07-09T00:00:00.000","h_mag":"19.4","i_deg":"32.78","moid_au":"0.275","orbit_class":"Apollo","period_yr":"1.61","pha":"N","q_au_1":"0.49","q_au_2":"2.26"} -,{"designation":"365449 (2010 NJ1)","discovery_date":"2010-07-03T00:00:00.000","h_mag":"20.3","i_deg":"11.23","moid_au":"0.155","orbit_class":"Aten","period_yr":"0.95","pha":"N","q_au_1":"0.44","q_au_2":"1.49"} -,{"designation":"365424 (2010 KX7)","discovery_date":"2010-05-16T00:00:00.000","h_mag":"21.9","i_deg":"21.49","moid_au":"0.034","orbit_class":"Aten","period_yr":"0.98","pha":"Y","q_au_1":"0.82","q_au_2":"1.16"} -,{"designation":"356394 (2010 QD2)","discovery_date":"2010-08-21T00:00:00.000","h_mag":"17.4","i_deg":"10.64","moid_au":"0.061","orbit_class":"Apollo","period_yr":"2.85","pha":"N","q_au_1":"0.43","q_au_2":"3.59"} -,{"designation":"(2015 HF11)","discovery_date":"2015-04-17T00:00:00.000","h_mag":"19.2","i_deg":"34.89","moid_au":"0.225","orbit_class":"Amor","period_yr":"2.99","pha":"N","q_au_1":"1.22","q_au_2":"2.93"} -,{"designation":"(2015 GK50)","discovery_date":"2015-04-05T00:00:00.000","h_mag":"20.5","i_deg":"19.07","moid_au":"0.237","orbit_class":"Amor","period_yr":"5.39","pha":"N","q_au_1":"1.03","q_au_2":"5.12"} -,{"designation":"(2015 GJ46)","discovery_date":"2015-04-11T00:00:00.000","h_mag":"19.3","i_deg":"18.22","moid_au":"0.238","orbit_class":"Apollo","period_yr":"4.85","pha":"N","q_au_1":"0.67","q_au_2":"5.06"} -,{"designation":"(2015 FT344)","discovery_date":"2015-03-23T00:00:00.000","h_mag":"20.5","i_deg":"12.55","moid_au":"0.203","orbit_class":"Amor","period_yr":"4.07","pha":"N","q_au_1":"1.09","q_au_2":"4.01"} -,{"designation":"(2015 FD341)","discovery_date":"2015-03-27T00:00:00.000","h_mag":"18","i_deg":"20.55","moid_au":"0.124","orbit_class":"Aten","period_yr":"0.93","pha":"N","q_au_1":"0.31","q_au_2":"1.6"} -,{"designation":"(2015 FU332)","discovery_date":"2015-03-31T00:00:00.000","h_mag":"17.3","i_deg":"36.11","moid_au":"0.269","orbit_class":"Apollo","period_yr":"4.27","pha":"N","q_au_1":"0.67","q_au_2":"4.59"} -,{"designation":"(2015 FE120)","discovery_date":"2015-03-23T00:00:00.000","h_mag":"21.1","i_deg":"22.8","moid_au":"0.013","orbit_class":"Apollo","period_yr":"3.38","pha":"Y","q_au_1":"1.01","q_au_2":"3.49"} -,{"designation":"(2015 FY117)","discovery_date":"2015-03-20T00:00:00.000","h_mag":"21.2","i_deg":"24.33","moid_au":"0.15","orbit_class":"Amor","period_yr":"2.87","pha":"N","q_au_1":"1.14","q_au_2":"2.9"} -,{"designation":"(2015 DX198)","discovery_date":"2015-02-17T00:00:00.000","h_mag":"22.1","i_deg":"11.05","moid_au":"0.074","orbit_class":"Amor","period_yr":"2.1","pha":"N","q_au_1":"1.02","q_au_2":"2.25"} -,{"designation":"(2015 BY516)","discovery_date":"2015-01-30T00:00:00.000","h_mag":"22.3","i_deg":"12.71","moid_au":"0.139","orbit_class":"Apollo","period_yr":"3.66","pha":"N","q_au_1":"0.97","q_au_2":"3.77"} -,{"designation":"(2015 AK280)","discovery_date":"2015-01-15T00:00:00.000","h_mag":"21.8","i_deg":"11.37","moid_au":"0.049","orbit_class":"Apollo","period_yr":"4.33","pha":"Y","q_au_1":"0.79","q_au_2":"4.53"} -,{"designation":"(2015 AY245)","discovery_date":"2015-01-14T00:00:00.000","h_mag":"21.2","i_deg":"13.59","moid_au":"0.019","orbit_class":"Apollo","period_yr":"1.2","pha":"Y","q_au_1":"1","q_au_2":"1.25"} -,{"designation":"(2015 AC17)","discovery_date":"2015-01-03T00:00:00.000","h_mag":"19.9","i_deg":"29.25","moid_au":"0.238","orbit_class":"Amor","period_yr":"3.39","pha":"N","q_au_1":"1.22","q_au_2":"3.29"} -,{"designation":"(2014 YR43)","discovery_date":"2014-12-26T00:00:00.000","h_mag":"19.5","i_deg":"26.46","moid_au":"0.303","orbit_class":"Apollo","period_yr":"3.92","pha":"N","q_au_1":"0.97","q_au_2":"4"} -,{"designation":"(2014 YS14)","discovery_date":"2014-12-24T00:00:00.000","h_mag":"21.1","i_deg":"18.29","moid_au":"0.127","orbit_class":"Apollo","period_yr":"3.87","pha":"N","q_au_1":"0.84","q_au_2":"4.09"} -,{"designation":"(2014 XX31)","discovery_date":"2014-12-11T00:00:00.000","h_mag":"17.5","i_deg":"35.78","moid_au":"0.475","orbit_class":"Apollo","period_yr":"4.73","pha":"N","q_au_1":"0.36","q_au_2":"5.28"} -,{"designation":"(2014 XX7)","discovery_date":"2014-12-10T00:00:00.000","h_mag":"19.7","i_deg":"36.71","moid_au":"0.183","orbit_class":"Amor","period_yr":"4.94","pha":"N","q_au_1":"1.17","q_au_2":"4.64"} -,{"designation":"(2014 XQ7)","discovery_date":"2014-12-06T00:00:00.000","h_mag":"20.6","i_deg":"31.05","moid_au":"0.312","orbit_class":"Apollo","period_yr":"4.32","pha":"N","q_au_1":"0.66","q_au_2":"4.65"} -,{"designation":"(2014 VP35)","discovery_date":"2014-11-14T00:00:00.000","h_mag":"23.3","i_deg":"9.17","moid_au":"0.026","orbit_class":"Apollo","period_yr":"1.78","pha":"N","q_au_1":"0.95","q_au_2":"1.98"} -,{"designation":"(2014 UH210)","discovery_date":"2014-10-20T00:00:00.000","h_mag":"21.1","i_deg":"22.06","moid_au":"0.099","orbit_class":"Apollo","period_yr":"4.11","pha":"N","q_au_1":"0.89","q_au_2":"4.25"} -,{"designation":"(2014 UF206)","discovery_date":"2014-10-31T00:00:00.000","h_mag":"18.8","i_deg":"48.05","moid_au":"0.136","orbit_class":"Amor","period_yr":"3.78","pha":"N","q_au_1":"1.11","q_au_2":"3.74"} -,{"designation":"(2014 UG176)","discovery_date":"2014-10-25T00:00:00.000","h_mag":"21.5","i_deg":"16.3","moid_au":"0.16","orbit_class":"Apollo","period_yr":"4.44","pha":"N","q_au_1":"0.78","q_au_2":"4.62"} -,{"designation":"(2014 TJ64)","discovery_date":"2014-10-07T00:00:00.000","h_mag":"21.2","i_deg":"14.91","moid_au":"0.154","orbit_class":"Amor","period_yr":"4.24","pha":"N","q_au_1":"1.05","q_au_2":"4.19"} -,{"designation":"(2014 TF64)","discovery_date":"2014-10-05T00:00:00.000","h_mag":"20.1","i_deg":"52.66","moid_au":"0.131","orbit_class":"Apollo","period_yr":"2.05","pha":"N","q_au_1":"0.94","q_au_2":"2.29"} -,{"designation":"(2014 TW57)","discovery_date":"2014-10-10T00:00:00.000","h_mag":"20.1","i_deg":"6.75","moid_au":"0.062","orbit_class":"Apollo","period_yr":"3.21","pha":"N","q_au_1":"0.57","q_au_2":"3.78"} -,{"designation":"(2014 SR339)","discovery_date":"2014-09-30T00:00:00.000","h_mag":"18.6","i_deg":"29.79","moid_au":"0.036","orbit_class":"Apollo","period_yr":"1.48","pha":"Y","q_au_1":"0.9","q_au_2":"1.69"} -,{"designation":"(2014 RH12)","discovery_date":"2014-09-03T00:00:00.000","h_mag":"23.5","i_deg":"7.23","moid_au":"0.045","orbit_class":"Apollo","period_yr":"3.22","pha":"N","q_au_1":"1.01","q_au_2":"3.35"} -,{"designation":"(2014 QK433)","discovery_date":"2014-08-28T00:00:00.000","h_mag":"18.2","i_deg":"39.22","moid_au":"0.18","orbit_class":"Amor","period_yr":"5.16","pha":"N","q_au_1":"1.19","q_au_2":"4.78"} -,{"designation":"(2014 PP69)","discovery_date":"2014-08-05T00:00:00.000","h_mag":"20","i_deg":"93.63","moid_au":"1.617","orbit_class":"Amor","period_yr":"99.82","pha":"N","q_au_1":"1.25","q_au_2":"41.78"} -,{"designation":"(2014 PF68)","discovery_date":"2014-08-15T00:00:00.000","h_mag":"18.2","i_deg":"22.75","moid_au":"0.17","orbit_class":"Amor","period_yr":"4.81","pha":"N","q_au_1":"1.17","q_au_2":"4.53"} -,{"designation":"(2014 PC68)","discovery_date":"2014-08-08T00:00:00.000","h_mag":"20.4","i_deg":"40.68","moid_au":"0.104","orbit_class":"Amor","period_yr":"1.87","pha":"N","q_au_1":"1.09","q_au_2":"1.95"} -,{"designation":"(2014 OZ1)","discovery_date":"2014-07-20T00:00:00.000","h_mag":"21","i_deg":"18","moid_au":"0.231","orbit_class":"Amor","period_yr":"2.24","pha":"N","q_au_1":"1.08","q_au_2":"2.35"} -,{"designation":"(2014 OY1)","discovery_date":"2014-07-21T00:00:00.000","h_mag":"19.1","i_deg":"23.01","moid_au":"0.042","orbit_class":"Apollo","period_yr":"4.14","pha":"Y","q_au_1":"0.97","q_au_2":"4.19"} -,{"designation":"(2014 NM64)","discovery_date":"2014-07-11T00:00:00.000","h_mag":"22.6","i_deg":"28.78","moid_au":"0.051","orbit_class":"Amor","period_yr":"4.79","pha":"N","q_au_1":"1.06","q_au_2":"4.62"} -,{"designation":"(2014 NE64)","discovery_date":"2014-07-07T00:00:00.000","h_mag":"18.8","i_deg":"41.63","moid_au":"0.39","orbit_class":"Amor","period_yr":"3.06","pha":"N","q_au_1":"1.2","q_au_2":"3.01"} -,{"designation":"(2014 NC64)","discovery_date":"2014-07-13T00:00:00.000","h_mag":"20.2","i_deg":"22.68","moid_au":"0.196","orbit_class":"Apollo","period_yr":"3.23","pha":"N","q_au_1":"0.8","q_au_2":"3.57"} -,{"designation":"(2014 NF3)","discovery_date":"2014-07-01T00:00:00.000","h_mag":"20.8","i_deg":"13.53","moid_au":"0.215","orbit_class":"Apollo","period_yr":"1.48","pha":"N","q_au_1":"0.66","q_au_2":"1.94"} -,{"designation":"C/2014 N3 (NEOWISE)","discovery_date":"2014-07-04T00:00:00.000","i_deg":"61.63","moid_au":"2.888","orbit_class":"Comet","period_yr":"745640.58","pha":"n/a","q_au_1":"3.88","q_au_2":"16441.51"} -,{"designation":"(2014 MQ18)","discovery_date":"2014-06-22T00:00:00.000","h_mag":"15.6","i_deg":"35.09","moid_au":"0.192","orbit_class":"Amor","period_yr":"4.93","pha":"N","q_au_1":"1.16","q_au_2":"4.63"} -,{"designation":"(2014 LQ25)","discovery_date":"2014-06-08T00:00:00.000","h_mag":"20","i_deg":"33.57","moid_au":"0.099","orbit_class":"Apollo","period_yr":"2.88","pha":"N","q_au_1":"0.65","q_au_2":"3.39"} -,{"designation":"P/2014 L2 (NEOWISE)","discovery_date":"2014-06-07T00:00:00.000","i_deg":"5.18","moid_au":"1.224","orbit_class":"Jupiter-family Comet","period_yr":"15.91","pha":"n/a","q_au_1":"2.23","q_au_2":"10.42"} -,{"designation":"(2014 JN57)","discovery_date":"2014-05-11T00:00:00.000","h_mag":"20.6","i_deg":"28.59","moid_au":"0.051","orbit_class":"Amor","period_yr":"1.39","pha":"N","q_au_1":"1.03","q_au_2":"1.45"} -,{"designation":"(2014 JH57)","discovery_date":"2014-05-10T00:00:00.000","h_mag":"16.2","i_deg":"26.54","moid_au":"0.418","orbit_class":"Apollo","period_yr":"6.13","pha":"N","q_au_1":"0.43","q_au_2":"6.27"} -,{"designation":"(2014 JL25)","discovery_date":"2014-05-04T00:00:00.000","h_mag":"23","i_deg":"15.75","moid_au":"0.012","orbit_class":"Apollo","period_yr":"4.94","pha":"N","q_au_1":"1","q_au_2":"4.8"} -,{"designation":"(2014 HJ129)","discovery_date":"2014-04-24T00:00:00.000","h_mag":"21.1","i_deg":"8.44","moid_au":"0.212","orbit_class":"Amor","period_yr":"4.16","pha":"N","q_au_1":"1.13","q_au_2":"4.04"} -,{"designation":"(2014 HQ124)","discovery_date":"2014-04-23T00:00:00.000","h_mag":"18.9","i_deg":"26.37","moid_au":"0.007","orbit_class":"Aten","period_yr":"0.78","pha":"Y","q_au_1":"0.63","q_au_2":"1.07"} -,{"designation":"(2014 EQ49)","discovery_date":"2014-03-15T00:00:00.000","h_mag":"21.8","i_deg":"15.18","moid_au":"0.026","orbit_class":"Apollo","period_yr":"1.23","pha":"Y","q_au_1":"0.91","q_au_2":"1.39"} -,{"designation":"(2014 EN45)","discovery_date":"2014-03-06T00:00:00.000","h_mag":"21.2","i_deg":"14.03","moid_au":"0.156","orbit_class":"Amor","period_yr":"3.82","pha":"N","q_au_1":"1.06","q_au_2":"3.83"} -,{"designation":"(2014 ED)","discovery_date":"2014-03-01T00:00:00.000","h_mag":"19.3","i_deg":"21.77","moid_au":"0.365","orbit_class":"Apollo","period_yr":"1.92","pha":"N","q_au_1":"0.56","q_au_2":"2.53"} -,{"designation":"(2014 CF14)","discovery_date":"2014-02-07T00:00:00.000","h_mag":"18.1","i_deg":"29.41","moid_au":"0.149","orbit_class":"Apollo","period_yr":"2.83","pha":"N","q_au_1":"0.82","q_au_2":"3.17"} -,{"designation":"(2014 CY4)","discovery_date":"2014-02-04T00:00:00.000","h_mag":"21.1","i_deg":"15.02","moid_au":"0.042","orbit_class":"Apollo","period_yr":"4.32","pha":"Y","q_au_1":"0.48","q_au_2":"4.82"} -,{"designation":"C/2014 C3 (NEOWISE)","discovery_date":"2014-02-14T00:00:00.000","i_deg":"151.78","moid_au":"0.866","orbit_class":"Comet","period_yr":"1128.89","pha":"n/a","q_au_1":"1.86","q_au_2":"214.97"} -,{"designation":"(2014 BE63)","discovery_date":"2014-01-23T00:00:00.000","h_mag":"23.2","i_deg":"8.59","moid_au":"0.133","orbit_class":"Apollo","period_yr":"3.08","pha":"N","q_au_1":"0.75","q_au_2":"3.48"} -,{"designation":"(2014 BG60)","discovery_date":"2014-01-25T00:00:00.000","h_mag":"20.1","i_deg":"8.61","moid_au":"0.227","orbit_class":"Amor","period_yr":"5.27","pha":"N","q_au_1":"1.17","q_au_2":"4.89"} -,{"designation":"(2014 AA53)","discovery_date":"2014-01-13T00:00:00.000","h_mag":"19.8","i_deg":"12.45","moid_au":"0.14","orbit_class":"Apollo","period_yr":"3.66","pha":"N","q_au_1":"0.78","q_au_2":"3.97"} -,{"designation":"(2014 AQ46)","discovery_date":"2014-01-02T00:00:00.000","h_mag":"20.1","i_deg":"24.6","moid_au":"0.205","orbit_class":"Amor","period_yr":"3.75","pha":"N","q_au_1":"1.13","q_au_2":"3.7"} -,{"designation":"(2013 YP139)","discovery_date":"2013-12-29T00:00:00.000","h_mag":"21.6","i_deg":"0.82","moid_au":"0.004","orbit_class":"Apollo","period_yr":"3.73","pha":"Y","q_au_1":"0.76","q_au_2":"4.05"} -,{"designation":"(2011 BN59)","discovery_date":"2011-01-29T00:00:00.000","h_mag":"20.4","i_deg":"20.32","moid_au":"0.326","orbit_class":"Amor","period_yr":"5.36","pha":"N","q_au_1":"1.16","q_au_2":"4.97"} -,{"designation":"(2011 BY24)","discovery_date":"2011-01-24T00:00:00.000","h_mag":"22.6","i_deg":"13.95","moid_au":"0.017","orbit_class":"Apollo","period_yr":"2.6","pha":"N","q_au_1":"0.96","q_au_2":"2.83"} -,{"designation":"(2010 YD3)","discovery_date":"2010-12-26T00:00:00.000","h_mag":"20","i_deg":"24.61","moid_au":"0.195","orbit_class":"Amor","period_yr":"4.14","pha":"N","q_au_1":"1.11","q_au_2":"4.05"} -,{"designation":"(2010 YC1)","discovery_date":"2010-12-21T00:00:00.000","h_mag":"21.3","i_deg":"17.66","moid_au":"0.163","orbit_class":"Apollo","period_yr":"1.68","pha":"N","q_au_1":"0.83","q_au_2":"2"} -,{"designation":"(2010 XY82)","discovery_date":"2010-12-14T00:00:00.000","h_mag":"19.1","i_deg":"26.73","moid_au":"0.294","orbit_class":"Amor","period_yr":"3.24","pha":"N","q_au_1":"1.12","q_au_2":"3.26"} -,{"designation":"(2010 XP69)","discovery_date":"2010-12-08T00:00:00.000","h_mag":"21.4","i_deg":"14.6","moid_au":"0.015","orbit_class":"Apollo","period_yr":"1.88","pha":"Y","q_au_1":"1","q_au_2":"2.05"} -,{"designation":"(2010 XZ67)","discovery_date":"2010-12-10T00:00:00.000","h_mag":"19.7","i_deg":"11.84","moid_au":"0.063","orbit_class":"Amor","period_yr":"2.96","pha":"N","q_au_1":"1.04","q_au_2":"3.08"} -,{"designation":"(2010 WE9)","discovery_date":"2010-11-23T00:00:00.000","h_mag":"20","i_deg":"42.12","moid_au":"0.256","orbit_class":"Amor","period_yr":"1.94","pha":"N","q_au_1":"1.17","q_au_2":"1.94"} -,{"designation":"(2010 UB8)","discovery_date":"2010-10-27T00:00:00.000","h_mag":"19.7","i_deg":"30.97","moid_au":"0.194","orbit_class":"Amor","period_yr":"5.15","pha":"N","q_au_1":"1.11","q_au_2":"4.85"} -,{"designation":"(2010 UY6)","discovery_date":"2010-10-23T00:00:00.000","h_mag":"20.1","i_deg":"19.98","moid_au":"0.062","orbit_class":"Amor","period_yr":"4.34","pha":"N","q_au_1":"1.04","q_au_2":"4.28"} -,{"designation":"(2010 TK7)","discovery_date":"2010-10-01T00:00:00.000","h_mag":"20.8","i_deg":"20.89","moid_au":"0.087","orbit_class":"Aten","period_yr":"1","pha":"N","q_au_1":"0.81","q_au_2":"1.19"} -,{"designation":"(2010 QA5)","discovery_date":"2010-08-29T00:00:00.000","h_mag":"22.5","i_deg":"33.45","moid_au":"0.065","orbit_class":"Amor","period_yr":"4.97","pha":"N","q_au_1":"1.07","q_au_2":"4.76"} -,{"designation":"(2010 QE2)","discovery_date":"2010-08-25T00:00:00.000","h_mag":"17.2","i_deg":"64.75","moid_au":"0.056","orbit_class":"Apollo","period_yr":"6.19","pha":"N","q_au_1":"0.88","q_au_2":"5.86"} -,{"designation":"(2010 PY75)","discovery_date":"2010-08-15T00:00:00.000","h_mag":"18.7","i_deg":"31.29","moid_au":"0.243","orbit_class":"Apollo","period_yr":"4.34","pha":"N","q_au_1":"0.6","q_au_2":"4.72"} -,{"designation":"(2010 PU66)","discovery_date":"2010-08-03T00:00:00.000","h_mag":"22.1","i_deg":"18.09","moid_au":"0.148","orbit_class":"Apollo","period_yr":"1.81","pha":"N","q_au_1":"0.91","q_au_2":"2.07"} -,{"designation":"(2010 PW58)","discovery_date":"2010-08-05T00:00:00.000","h_mag":"21.3","i_deg":"14.24","moid_au":"0.021","orbit_class":"Aten","period_yr":"0.84","pha":"Y","q_au_1":"0.7","q_au_2":"1.08"} -,{"designation":"(2010 PP58)","discovery_date":"2010-08-05T00:00:00.000","h_mag":"22.1","i_deg":"4.55","moid_au":"0.014","orbit_class":"Apollo","period_yr":"2.81","pha":"N","q_au_1":"0.99","q_au_2":"3"} -,{"designation":"(2010 PM58)","discovery_date":"2010-08-01T00:00:00.000","h_mag":"20.9","i_deg":"13.6","moid_au":"0.096","orbit_class":"Apollo","period_yr":"1.61","pha":"N","q_au_1":"0.74","q_au_2":"2"} -,{"designation":"P/2010 P4 (WISE)","discovery_date":"2010-08-06T00:00:00.000","i_deg":"24.1","moid_au":"0.854","orbit_class":"Jupiter-family Comet","period_yr":"7.13","pha":"n/a","q_au_1":"1.86","q_au_2":"5.55"} -,{"designation":"(2010 OK126)","discovery_date":"2010-07-30T00:00:00.000","h_mag":"20.7","i_deg":"52.56","moid_au":"0.149","orbit_class":"Amor","period_yr":"2.74","pha":"N","q_au_1":"1.08","q_au_2":"2.83"} -,{"designation":"(2010 OH126)","discovery_date":"2010-07-31T00:00:00.000","h_mag":"21.4","i_deg":"14.38","moid_au":"0.068","orbit_class":"Apollo","period_yr":"2.62","pha":"N","q_au_1":"0.95","q_au_2":"2.85"} -,{"designation":"(2010 ON101)","discovery_date":"2010-07-30T00:00:00.000","h_mag":"20.2","i_deg":"9.31","moid_au":"0.044","orbit_class":"Apollo","period_yr":"2.08","pha":"Y","q_au_1":"0.96","q_au_2":"2.3"} -,{"designation":"(2010 OL101)","discovery_date":"2010-07-27T00:00:00.000","h_mag":"20.4","i_deg":"26.11","moid_au":"0.298","orbit_class":"Amor","period_yr":"4.22","pha":"N","q_au_1":"1.05","q_au_2":"4.17"} -,{"designation":"(2010 OF101)","discovery_date":"2010-07-23T00:00:00.000","h_mag":"19.6","i_deg":"23.37","moid_au":"0.062","orbit_class":"Aten","period_yr":"0.93","pha":"N","q_au_1":"0.64","q_au_2":"1.26"} -,{"designation":"(2010 OD101)","discovery_date":"2010-07-23T00:00:00.000","h_mag":"20.7","i_deg":"15.39","moid_au":"0.19","orbit_class":"Amor","period_yr":"2.06","pha":"N","q_au_1":"1.04","q_au_2":"2.2"} -,{"designation":"(2010 OC101)","discovery_date":"2010-07-22T00:00:00.000","h_mag":"20.7","i_deg":"13.6","moid_au":"0.092","orbit_class":"Apollo","period_yr":"1.35","pha":"N","q_au_1":"0.94","q_au_2":"1.5"} -,{"designation":"(2010 OL100)","discovery_date":"2010-07-28T00:00:00.000","h_mag":"19.6","i_deg":"22.16","moid_au":"0.129","orbit_class":"Apollo","period_yr":"3.4","pha":"N","q_au_1":"0.78","q_au_2":"3.74"} -,{"designation":"(2010 OE22)","discovery_date":"2010-07-17T00:00:00.000","h_mag":"21.3","i_deg":"14.32","moid_au":"0.178","orbit_class":"Apollo","period_yr":"4.28","pha":"N","q_au_1":"0.97","q_au_2":"4.31"} -,{"designation":"(2010 NY65)","discovery_date":"2010-07-14T00:00:00.000","h_mag":"21.4","i_deg":"11.74","moid_au":"0.017","orbit_class":"Aten","period_yr":"1","pha":"Y","q_au_1":"0.63","q_au_2":"1.37"} -,{"designation":"(2010 NG3)","discovery_date":"2010-07-08T00:00:00.000","h_mag":"17.2","i_deg":"26.96","moid_au":"0.127","orbit_class":"Amor","period_yr":"4.2","pha":"N","q_au_1":"1.13","q_au_2":"4.08"} -,{"designation":"(2010 NB2)","discovery_date":"2010-07-10T00:00:00.000","h_mag":"20.3","i_deg":"28.66","moid_au":"0.102","orbit_class":"Apollo","period_yr":"3.01","pha":"N","q_au_1":"0.5","q_au_2":"3.67"} -,{"designation":"(2010 NU1)","discovery_date":"2010-07-06T00:00:00.000","h_mag":"21.2","i_deg":"34.58","moid_au":"0.336","orbit_class":"Apollo","period_yr":"3.74","pha":"N","q_au_1":"0.48","q_au_2":"4.33"} -,{"designation":"(2010 NT1)","discovery_date":"2010-07-04T00:00:00.000","h_mag":"19.4","i_deg":"39.52","moid_au":"0.208","orbit_class":"Amor","period_yr":"1.76","pha":"N","q_au_1":"1.14","q_au_2":"1.78"} -,{"designation":"(2010 NG1)","discovery_date":"2010-07-02T00:00:00.000","h_mag":"20.4","i_deg":"24.74","moid_au":"0.081","orbit_class":"Aten","period_yr":"0.78","pha":"N","q_au_1":"0.57","q_au_2":"1.13"} -,{"designation":"P/2010 N1 (WISE)","discovery_date":"2010-07-05T00:00:00.000","i_deg":"12.88","moid_au":"0.491","orbit_class":"Jupiter-family Comet","period_yr":"5.74","pha":"n/a","q_au_1":"1.49","q_au_2":"4.92"} -,{"designation":"(2010 MA113)","discovery_date":"2010-06-25T00:00:00.000","h_mag":"19.2","i_deg":"39.85","moid_au":"0.081","orbit_class":"Apollo","period_yr":"3.46","pha":"N","q_au_1":"0.89","q_au_2":"3.68"} -,{"designation":"(2010 MZ112)","discovery_date":"2010-06-23T00:00:00.000","h_mag":"19.8","i_deg":"30.18","moid_au":"0.221","orbit_class":"Apollo","period_yr":"2.36","pha":"N","q_au_1":"0.49","q_au_2":"3.06"} -,{"designation":"(2010 MY112)","discovery_date":"2010-06-23T00:00:00.000","h_mag":"21","i_deg":"38.49","moid_au":"0.156","orbit_class":"Apollo","period_yr":"1.1","pha":"N","q_au_1":"0.8","q_au_2":"1.33"} -,{"designation":"(2010 MU112)","discovery_date":"2010-06-30T00:00:00.000","h_mag":"20.7","i_deg":"48.02","moid_au":"0.0002","orbit_class":"Apollo","period_yr":"2.33","pha":"Y","q_au_1":"0.81","q_au_2":"2.71"} -,{"designation":"(2010 MU111)","discovery_date":"2010-06-23T00:00:00.000","h_mag":"18.7","i_deg":"41.53","moid_au":"0.059","orbit_class":"Apollo","period_yr":"3.7","pha":"N","q_au_1":"0.92","q_au_2":"3.86"} -,{"designation":"(2010 MR87)","discovery_date":"2010-06-22T00:00:00.000","h_mag":"19.5","i_deg":"34.98","moid_au":"0.15","orbit_class":"Amor","period_yr":"2.28","pha":"N","q_au_1":"1.06","q_au_2":"2.41"} -,{"designation":"(2010 LU134)","discovery_date":"2010-06-14T00:00:00.000","h_mag":"19.5","i_deg":"27.39","moid_au":"0.146","orbit_class":"Apollo","period_yr":"2.61","pha":"N","q_au_1":"0.86","q_au_2":"2.93"} -,{"designation":"(2010 LV108)","discovery_date":"2010-06-14T00:00:00.000","h_mag":"22.6","i_deg":"5.43","moid_au":"0.006","orbit_class":"Apollo","period_yr":"4.64","pha":"N","q_au_1":"1.01","q_au_2":"4.55"} -,{"designation":"(2010 LU108)","discovery_date":"2010-06-15T00:00:00.000","h_mag":"20","i_deg":"9.51","moid_au":"0.126","orbit_class":"Apollo","period_yr":"3.35","pha":"N","q_au_1":"0.41","q_au_2":"4.08"} -,{"designation":"(2010 LT108)","discovery_date":"2010-06-13T00:00:00.000","h_mag":"19.7","i_deg":"31.87","moid_au":"0.138","orbit_class":"Apollo","period_yr":"1.57","pha":"N","q_au_1":"0.85","q_au_2":"1.85"} -,{"designation":"(2010 LO97)","discovery_date":"2010-06-13T00:00:00.000","h_mag":"18.7","i_deg":"21.65","moid_au":"0.233","orbit_class":"Amor","period_yr":"4.14","pha":"N","q_au_1":"1.22","q_au_2":"3.94"} -,{"designation":"(2010 LF86)","discovery_date":"2010-06-11T00:00:00.000","h_mag":"17.2","i_deg":"13.55","moid_au":"0.318","orbit_class":"Amor","period_yr":"3.73","pha":"N","q_au_1":"1.3","q_au_2":"3.51"} -,{"designation":"(2010 LR68)","discovery_date":"2010-06-08T00:00:00.000","h_mag":"18.3","i_deg":"4.58","moid_au":"0.216","orbit_class":"Amor","period_yr":"5.29","pha":"N","q_au_1":"1.19","q_au_2":"4.88"} -,{"designation":"(2010 LL68)","discovery_date":"2010-06-12T00:00:00.000","h_mag":"22.9","i_deg":"10.48","moid_au":"0.139","orbit_class":"Apollo","period_yr":"2.99","pha":"N","q_au_1":"0.98","q_au_2":"3.16"} -,{"designation":"(2010 LK68)","discovery_date":"2010-06-12T00:00:00.000","h_mag":"22.5","i_deg":"22.08","moid_au":"0.025","orbit_class":"Apollo","period_yr":"1.27","pha":"N","q_au_1":"0.61","q_au_2":"1.73"} -,{"designation":"(2010 LJ68)","discovery_date":"2010-06-11T00:00:00.000","h_mag":"22.7","i_deg":"17.01","moid_au":"0.031","orbit_class":"Apollo","period_yr":"2.32","pha":"N","q_au_1":"0.97","q_au_2":"2.54"} -,{"designation":"(2010 LG64)","discovery_date":"2010-06-05T00:00:00.000","h_mag":"20.2","i_deg":"42.28","moid_au":"0.043","orbit_class":"Amor","period_yr":"4.36","pha":"Y","q_au_1":"1.04","q_au_2":"4.3"} -,{"designation":"(2010 LF64)","discovery_date":"2010-06-03T00:00:00.000","h_mag":"21.6","i_deg":"18.54","moid_au":"0.192","orbit_class":"Amor","period_yr":"1.59","pha":"N","q_au_1":"1.13","q_au_2":"1.59"} -,{"designation":"(2010 LJ61)","discovery_date":"2010-06-08T00:00:00.000","h_mag":"20.9","i_deg":"10.24","moid_au":"0.054","orbit_class":"Apollo","period_yr":"1.12","pha":"N","q_au_1":"0.57","q_au_2":"1.59"} -,{"designation":"(2010 LQ33)","discovery_date":"2010-06-04T00:00:00.000","h_mag":"19.3","i_deg":"24.63","moid_au":"0.228","orbit_class":"Amor","period_yr":"3.42","pha":"N","q_au_1":"1.23","q_au_2":"3.31"} -,{"designation":"(2010 LM14)","discovery_date":"2010-06-02T00:00:00.000","h_mag":"21.5","i_deg":"25.92","moid_au":"0.312","orbit_class":"Apollo","period_yr":"1.17","pha":"N","q_au_1":"0.69","q_au_2":"1.53"} -,{"designation":"(2010 LH14)","discovery_date":"2010-06-02T00:00:00.000","h_mag":"22","i_deg":"4.66","moid_au":"0.054","orbit_class":"Apollo","period_yr":"3.26","pha":"N","q_au_1":"0.93","q_au_2":"3.46"} -,{"designation":"C/2010 L5 (WISE)","discovery_date":"2010-06-14T00:00:00.000","i_deg":"147.05","moid_au":"0.114","orbit_class":"Halley-type Comet*","period_yr":"23.56","pha":"n/a","q_au_1":"0.79","q_au_2":"15.64"} -,{"designation":"C/2010 L4 (WISE)","discovery_date":"2010-06-15T00:00:00.000","i_deg":"102.82","moid_au":"2.53","orbit_class":"Comet","period_yr":"716.78","pha":"n/a","q_au_1":"2.83","q_au_2":"157.36"} -,{"designation":"245P/WISE","discovery_date":"2010-06-02T00:00:00.000","i_deg":"21.09","moid_au":"1.172","orbit_class":"Jupiter-family Comet","period_yr":"8.04","pha":"n/a","q_au_1":"2.14","q_au_2":"5.88"} -,{"designation":"(2010 KY127)","discovery_date":"2010-05-31T00:00:00.000","h_mag":"17","i_deg":"60.29","moid_au":"0.703","orbit_class":"Apollo","period_yr":"3.95","pha":"N","q_au_1":"0.3","q_au_2":"4.7"} -,{"designation":"(2010 KK127)","discovery_date":"2010-05-21T00:00:00.000","h_mag":"20.7","i_deg":"6.94","moid_au":"0.282","orbit_class":"Amor","period_yr":"3.33","pha":"N","q_au_1":"1.28","q_au_2":"3.18"} -,{"designation":"(2010 KZ117)","discovery_date":"2010-05-18T00:00:00.000","h_mag":"19.2","i_deg":"33.17","moid_au":"0.166","orbit_class":"Amor","period_yr":"3.42","pha":"N","q_au_1":"1.1","q_au_2":"3.43"} -,{"designation":"(2010 KB61)","discovery_date":"2010-05-26T00:00:00.000","h_mag":"20.5","i_deg":"44.6","moid_au":"0.051","orbit_class":"Apollo","period_yr":"1.44","pha":"N","q_au_1":"0.98","q_au_2":"1.57"} -,{"designation":"(2010 KY39)","discovery_date":"2010-05-18T00:00:00.000","h_mag":"20.1","i_deg":"25.51","moid_au":"0.303","orbit_class":"Amor","period_yr":"2.3","pha":"N","q_au_1":"1.05","q_au_2":"2.43"} -,{"designation":"C/2010 KW7 (WISE)","discovery_date":"2010-05-16T00:00:00.000","i_deg":"147.06","moid_au":"1.625","orbit_class":"Comet","period_yr":"997.65","pha":"n/a","q_au_1":"2.57","q_au_2":"197.11"} -,{"designation":"317P/WISE","discovery_date":"2010-05-27T00:00:00.000","i_deg":"10.65","moid_au":"0.204","orbit_class":"Jupiter-family Comet","period_yr":"5.01","pha":"n/a","q_au_1":"1.2","q_au_2":"4.65"} -,{"designation":"(2010 KH)","discovery_date":"2010-05-16T00:00:00.000","h_mag":"19.4","i_deg":"14.57","moid_au":"0.367","orbit_class":"Amor","period_yr":"4.59","pha":"N","q_au_1":"1.24","q_au_2":"4.28"} -,{"designation":"(2010 JM151)","discovery_date":"2010-05-14T00:00:00.000","h_mag":"19.6","i_deg":"16.65","moid_au":"0.111","orbit_class":"Apollo","period_yr":"2.21","pha":"N","q_au_1":"0.88","q_au_2":"2.52"} -,{"designation":"(2010 JH87)","discovery_date":"2010-05-11T00:00:00.000","h_mag":"19.6","i_deg":"43.78","moid_au":"0.221","orbit_class":"Apollo","period_yr":"1.91","pha":"N","q_au_1":"0.71","q_au_2":"2.37"} -,{"designation":"(2010 JG87)","discovery_date":"2010-05-11T00:00:00.000","h_mag":"19.1","i_deg":"16.91","moid_au":"0.209","orbit_class":"Apollo","period_yr":"4.59","pha":"N","q_au_1":"0.14","q_au_2":"5.38"} -,{"designation":"(2010 JF87)","discovery_date":"2010-05-11T00:00:00.000","h_mag":"19.2","i_deg":"24.93","moid_au":"0.053","orbit_class":"Apollo","period_yr":"3.8","pha":"N","q_au_1":"0.92","q_au_2":"3.95"} -,{"designation":"(2010 JE87)","discovery_date":"2010-05-10T00:00:00.000","h_mag":"20.8","i_deg":"16.92","moid_au":"0.035","orbit_class":"Aten","period_yr":"0.86","pha":"Y","q_au_1":"0.51","q_au_2":"1.3"} -,{"designation":"(2010 JD87)","discovery_date":"2010-05-07T00:00:00.000","h_mag":"19.2","i_deg":"24.6","moid_au":"0.283","orbit_class":"Apollo","period_yr":"1.71","pha":"N","q_au_1":"0.51","q_au_2":"2.34"} -,{"designation":"P/2010 JC81 (WISE)","discovery_date":"2010-05-10T00:00:00.000","i_deg":"38.69","moid_au":"0.828","orbit_class":"Halley-type Comet*","period_yr":"23.19","pha":"n/a","q_au_1":"1.81","q_au_2":"14.46"} -,{"designation":"(2010 JA43)","discovery_date":"2010-05-04T00:00:00.000","h_mag":"20.9","i_deg":"36.46","moid_au":"0.186","orbit_class":"Amor","period_yr":"2.23","pha":"N","q_au_1":"1.03","q_au_2":"2.38"} -,{"designation":"(2010 JN33)","discovery_date":"2010-05-03T00:00:00.000","h_mag":"20.4","i_deg":"53.15","moid_au":"0.257","orbit_class":"Amor","period_yr":"1.94","pha":"N","q_au_1":"1.11","q_au_2":"2"} -,{"designation":"C/2010 J4 (WISE)","discovery_date":"2010-05-12T00:00:00.000","i_deg":"162.3","moid_au":"0.307","orbit_class":"Parabolic Comet","pha":"n/a","q_au_1":"1.09"} -,{"designation":"(2010 HZ108)","discovery_date":"2010-04-25T00:00:00.000","h_mag":"20.9","i_deg":"22.88","moid_au":"0.108","orbit_class":"Apollo","period_yr":"1.39","pha":"N","q_au_1":"0.99","q_au_2":"1.51"} -,{"designation":"(2010 HX107)","discovery_date":"2010-04-20T00:00:00.000","h_mag":"23.6","i_deg":"3.36","moid_au":"0.014","orbit_class":"Aten","period_yr":"0.72","pha":"N","q_au_1":"0.56","q_au_2":"1.04"} -,{"designation":"(2010 HZ104)","discovery_date":"2010-04-23T00:00:00.000","h_mag":"22.5","i_deg":"20.24","moid_au":"0.029","orbit_class":"Apollo","period_yr":"3.37","pha":"N","q_au_1":"0.97","q_au_2":"3.52"} -,{"designation":"(2010 HW81)","discovery_date":"2010-04-25T00:00:00.000","h_mag":"21.4","i_deg":"12.77","moid_au":"0.117","orbit_class":"Apollo","period_yr":"1.33","pha":"N","q_au_1":"0.33","q_au_2":"2.1"} -,{"designation":"(2010 HD33)","discovery_date":"2010-04-20T00:00:00.000","h_mag":"18.3","i_deg":"24.43","moid_au":"0.372","orbit_class":"Amor","period_yr":"4.24","pha":"N","q_au_1":"1.27","q_au_2":"3.97"} -,{"designation":"(2010 GV147)","discovery_date":"2010-04-14T00:00:00.000","h_mag":"18.5","i_deg":"44.05","moid_au":"0.316","orbit_class":"Aten","period_yr":"0.94","pha":"N","q_au_1":"0.33","q_au_2":"1.59"} -,{"designation":"(2010 GR75)","discovery_date":"2010-04-13T00:00:00.000","h_mag":"19.6","i_deg":"17.78","moid_au":"0.299","orbit_class":"Apollo","period_yr":"2.27","pha":"N","q_au_1":"0.63","q_au_2":"2.82"} -,{"designation":"(2010 GQ75)","discovery_date":"2010-04-12T00:00:00.000","h_mag":"20.2","i_deg":"43.23","moid_au":"0.598","orbit_class":"Apollo","period_yr":"3.79","pha":"N","q_au_1":"0.33","q_au_2":"4.53"} -,{"designation":"(2010 GP67)","discovery_date":"2010-04-11T00:00:00.000","h_mag":"22.3","i_deg":"13.27","moid_au":"0.018","orbit_class":"Apollo","period_yr":"1.18","pha":"N","q_au_1":"0.99","q_au_2":"1.23"} -,{"designation":"(2010 GH65)","discovery_date":"2010-04-10T00:00:00.000","h_mag":"18.8","i_deg":"21.04","moid_au":"0.15","orbit_class":"Amor","period_yr":"4.45","pha":"N","q_au_1":"1.05","q_au_2":"4.36"} -,{"designation":"(2010 GX62)","discovery_date":"2010-04-10T00:00:00.000","h_mag":"20","i_deg":"21.66","moid_au":"0.013","orbit_class":"Apollo","period_yr":"5.07","pha":"Y","q_au_1":"0.87","q_au_2":"5.03"} -,{"designation":"(2010 GW62)","discovery_date":"2010-04-09T00:00:00.000","h_mag":"19.4","i_deg":"32.43","moid_au":"0.44","orbit_class":"Apollo","period_yr":"1.43","pha":"N","q_au_1":"0.54","q_au_2":"2"} -,{"designation":"(2010 GF25)","discovery_date":"2010-04-02T00:00:00.000","h_mag":"19.1","i_deg":"38.49","moid_au":"0.399","orbit_class":"Apollo","period_yr":"1.7","pha":"N","q_au_1":"0.37","q_au_2":"2.47"} -,{"designation":"(2010 GE25)","discovery_date":"2010-04-01T00:00:00.000","h_mag":"20","i_deg":"21.66","moid_au":"0.22","orbit_class":"Amor","period_yr":"2.97","pha":"N","q_au_1":"1.1","q_au_2":"3.03"} -,{"designation":"(2010 GK23)","discovery_date":"2010-04-05T00:00:00.000","h_mag":"19.7","i_deg":"34.77","moid_au":"0.097","orbit_class":"Apollo","period_yr":"4.32","pha":"N","q_au_1":"0.87","q_au_2":"4.43"} -,{"designation":"C/2010 G3 (WISE)","discovery_date":"2010-04-14T00:00:00.000","i_deg":"108.27","moid_au":"4.492","orbit_class":"Comet","period_yr":"135070.2","pha":"n/a","q_au_1":"4.91","q_au_2":"5260.08"} -,{"designation":"C/2010 FB87 (WISE-Garradd)","discovery_date":"2010-03-28T00:00:00.000","i_deg":"107.63","moid_au":"2.538","orbit_class":"Comet","period_yr":"5176.82","pha":"n/a","q_au_1":"2.84","q_au_2":"595.66"} -,{"designation":"(2010 FJ81)","discovery_date":"2010-03-31T00:00:00.000","h_mag":"20.8","i_deg":"42.54","moid_au":"0.128","orbit_class":"Amor","period_yr":"6.82","pha":"N","q_au_1":"1.14","q_au_2":"6.06"} -,{"designation":"(2010 FH81)","discovery_date":"2010-03-31T00:00:00.000","h_mag":"21.6","i_deg":"16.79","moid_au":"0.034","orbit_class":"Apollo","period_yr":"1.36","pha":"Y","q_au_1":"0.97","q_au_2":"1.48"} -,{"designation":"(2010 FG81)","discovery_date":"2010-03-26T00:00:00.000","h_mag":"23.3","i_deg":"7.97","moid_au":"0.019","orbit_class":"Apollo","period_yr":"2.14","pha":"N","q_au_1":"1.01","q_au_2":"2.31"} -,{"designation":"(2010 FC81)","discovery_date":"2010-03-30T00:00:00.000","h_mag":"21.8","i_deg":"1.68","moid_au":"0.027","orbit_class":"Apollo","period_yr":"4.38","pha":"Y","q_au_1":"1.01","q_au_2":"4.35"} -,{"designation":"(2010 FB81)","discovery_date":"2010-03-30T00:00:00.000","h_mag":"21.4","i_deg":"9.48","moid_au":"0.096","orbit_class":"Amor","period_yr":"4.14","pha":"N","q_au_1":"1.02","q_au_2":"4.14"} -,{"designation":"(2010 FA81)","discovery_date":"2010-03-29T00:00:00.000","h_mag":"22.3","i_deg":"15.48","moid_au":"0.035","orbit_class":"Apollo","period_yr":"1.31","pha":"N","q_au_1":"1.01","q_au_2":"1.38"} -,{"designation":"(2010 FZ80)","discovery_date":"2010-03-28T00:00:00.000","h_mag":"20.3","i_deg":"27.34","moid_au":"0.297","orbit_class":"Apollo","period_yr":"4.56","pha":"N","q_au_1":"0.7","q_au_2":"4.8"} -,{"designation":"(2010 FY80)","discovery_date":"2010-03-28T00:00:00.000","h_mag":"19.7","i_deg":"18.81","moid_au":"0.14","orbit_class":"Amor","period_yr":"4.42","pha":"N","q_au_1":"1.05","q_au_2":"4.35"} -,{"designation":"(2010 FX80)","discovery_date":"2010-03-27T00:00:00.000","h_mag":"20.6","i_deg":"36.96","moid_au":"0.535","orbit_class":"Amor","period_yr":"3.19","pha":"N","q_au_1":"1.18","q_au_2":"3.15"} -,{"designation":"(2010 EX119)","discovery_date":"2010-03-13T00:00:00.000","h_mag":"19.4","i_deg":"15.57","moid_au":"0.159","orbit_class":"Apollo","period_yr":"2.63","pha":"N","q_au_1":"0.77","q_au_2":"3.04"} -,{"designation":"(2010 EN44)","discovery_date":"2010-03-12T00:00:00.000","h_mag":"24.3","i_deg":"10.18","moid_au":"0.023","orbit_class":"Apollo","period_yr":"1.22","pha":"N","q_au_1":"0.96","q_au_2":"1.33"} -,{"designation":"(2010 EX11)","discovery_date":"2010-03-03T00:00:00.000","h_mag":"24.1","i_deg":"9.75","moid_au":"0.029","orbit_class":"Aten","period_yr":"0.93","pha":"N","q_au_1":"0.85","q_au_2":"1.06"} -,{"designation":"C/2010 E3 (WISE)","discovery_date":"2010-03-05T00:00:00.000","i_deg":"96.48","moid_au":"1.546","orbit_class":"Parabolic Comet","pha":"n/a","q_au_1":"2.27"} -,{"designation":"(2010 DJ77)","discovery_date":"2010-02-20T00:00:00.000","h_mag":"21.6","i_deg":"24.98","moid_au":"0.05","orbit_class":"Aten","period_yr":"0.93","pha":"Y","q_au_1":"0.75","q_au_2":"1.16"} -,{"designation":"(2010 DH77)","discovery_date":"2010-02-19T00:00:00.000","h_mag":"21.8","i_deg":"34.38","moid_au":"0.146","orbit_class":"Apollo","period_yr":"5.9","pha":"N","q_au_1":"0.95","q_au_2":"5.58"} -,{"designation":"(2010 DG77)","discovery_date":"2010-02-19T00:00:00.000","h_mag":"21.4","i_deg":"14.81","moid_au":"0.009","orbit_class":"Apollo","period_yr":"3.02","pha":"Y","q_au_1":"0.96","q_au_2":"3.22"} -,{"designation":"(2010 DM56)","discovery_date":"2010-02-19T00:00:00.000","h_mag":"19.9","i_deg":"25.61","moid_au":"0.006","orbit_class":"Apollo","period_yr":"1.49","pha":"Y","q_au_1":"0.92","q_au_2":"1.69"} -,{"designation":"(2010 DJ56)","discovery_date":"2010-02-23T00:00:00.000","h_mag":"19.3","i_deg":"34.84","moid_au":"0.028","orbit_class":"Apollo","period_yr":"1.4","pha":"Y","q_au_1":"0.94","q_au_2":"1.56"} -,{"designation":"(2010 DH56)","discovery_date":"2010-02-20T00:00:00.000","h_mag":"20.3","i_deg":"33.67","moid_au":"0.333","orbit_class":"Apollo","period_yr":"3.35","pha":"N","q_au_1":"0.97","q_au_2":"3.51"} -,{"designation":"C/2010 DG56 (WISE)","discovery_date":"2010-02-18T00:00:00.000","i_deg":"160.42","moid_au":"0.65","orbit_class":"Comet","period_yr":"555.03","pha":"n/a","q_au_1":"1.59","q_au_2":"133.48"} -,{"designation":"(2010 DK34)","discovery_date":"2010-02-20T00:00:00.000","h_mag":"20.4","i_deg":"27.34","moid_au":"0.333","orbit_class":"Apollo","period_yr":"4.54","pha":"N","q_au_1":"0.65","q_au_2":"4.83"} -,{"designation":"(2010 DM21)","discovery_date":"2010-02-16T00:00:00.000","h_mag":"20.2","i_deg":"21.15","moid_au":"0.26","orbit_class":"Apollo","period_yr":"4.85","pha":"N","q_au_1":"0.98","q_au_2":"4.74"} -,{"designation":"C/2010 D4 (WISE)","discovery_date":"2010-02-28T00:00:00.000","i_deg":"105.66","moid_au":"6.373","orbit_class":"Comet","period_yr":"520.06","pha":"n/a","q_au_1":"7.15","q_au_2":"122.19"} -,{"designation":"C/2010 D3 (WISE)","discovery_date":"2010-02-26T00:00:00.000","i_deg":"76.39","moid_au":"3.586","orbit_class":"Comet","period_yr":"1254179.62","pha":"n/a","q_au_1":"4.25","q_au_2":"23255.11"} -,{"designation":"P/2010 D2 (WISE)","discovery_date":"2010-02-25T00:00:00.000","i_deg":"57.18","moid_au":"2.945","orbit_class":"Jupiter-family Comet*","period_yr":"17.3","pha":"n/a","q_au_1":"3.66","q_au_2":"9.72"} -,{"designation":"P/2010 D1 (WISE)","discovery_date":"2010-02-17T00:00:00.000","i_deg":"9.65","moid_au":"1.683","orbit_class":"Jupiter-family Comet","period_yr":"8.45","pha":"n/a","q_au_1":"2.67","q_au_2":"5.63"} -,{"designation":"(2010 CN141)","discovery_date":"2010-02-14T00:00:00.000","h_mag":"22.4","i_deg":"23.8","moid_au":"0.06","orbit_class":"Apollo","period_yr":"1.87","pha":"N","q_au_1":"0.91","q_au_2":"2.12"} -,{"designation":"(2010 CP140)","discovery_date":"2010-02-13T00:00:00.000","h_mag":"19.5","i_deg":"14.47","moid_au":"0.097","orbit_class":"Apollo","period_yr":"2.62","pha":"N","q_au_1":"0.88","q_au_2":"2.92"} -,{"designation":"(2010 CC55)","discovery_date":"2010-02-11T00:00:00.000","h_mag":"22.5","i_deg":"6.78","moid_au":"0.079","orbit_class":"Apollo","period_yr":"1.92","pha":"N","q_au_1":"0.82","q_au_2":"2.27"} -,{"designation":"(2010 CA55)","discovery_date":"2010-02-05T00:00:00.000","h_mag":"21.3","i_deg":"58.85","moid_au":"0.151","orbit_class":"Apollo","period_yr":"12.13","pha":"N","q_au_1":"0.67","q_au_2":"9.89"} -,{"designation":"(2010 CH18)","discovery_date":"2010-02-09T00:00:00.000","h_mag":"19","i_deg":"27.15","moid_au":"0.333","orbit_class":"Amor","period_yr":"4.21","pha":"N","q_au_1":"1.12","q_au_2":"4.09"} -,{"designation":"(2010 CG18)","discovery_date":"2010-02-06T00:00:00.000","h_mag":"20.8","i_deg":"10.15","moid_au":"0.13","orbit_class":"Amor","period_yr":"1.73","pha":"N","q_au_1":"1.11","q_au_2":"1.76"} -,{"designation":"(2010 CO1)","discovery_date":"2010-02-01T00:00:00.000","h_mag":"21.5","i_deg":"24.03","moid_au":"0.023","orbit_class":"Apollo","period_yr":"1.02","pha":"Y","q_au_1":"0.79","q_au_2":"1.23"} -,{"designation":"P/2010 B2 (WISE)","discovery_date":"2010-01-22T00:00:00.000","i_deg":"8.93","moid_au":"0.63","orbit_class":"Encke-type Comet","period_yr":"5.49","pha":"n/a","q_au_1":"1.62","q_au_2":"4.6"} -,{"designation":"(2010 AU118)","discovery_date":"2010-01-13T00:00:00.000","h_mag":"17.7","i_deg":"43.73","moid_au":"0.147","orbit_class":"Amor","period_yr":"2.06","pha":"N","q_au_1":"1.13","q_au_2":"2.12"} -,{"designation":"(2010 AG79)","discovery_date":"2010-01-13T00:00:00.000","h_mag":"19.9","i_deg":"32.96","moid_au":"0.244","orbit_class":"Amor","period_yr":"4.95","pha":"N","q_au_1":"1.22","q_au_2":"4.59"} -,{"designation":"(2010 AB78)","discovery_date":"2010-01-12T00:00:00.000","h_mag":"18.3","i_deg":"33.26","moid_au":"0.206","orbit_class":"Amor","period_yr":"3.38","pha":"N","q_au_1":"1.02","q_au_2":"3.49"}] +[ + { + "designation": "419880 (2011 AH37)", + "discovery_date": "2011-01-07T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "9.65", + "moid_au": "0.035", + "orbit_class": "Apollo", + "period_yr": "4.06", + "pha": "Y", + "q_au_1": "0.84", + "q_au_2": "4.26" + }, + { + "designation": "419624 (2010 SO16)", + "discovery_date": "2010-09-17T00:00:00.000Z", + "h_mag": "20.5", + "i_deg": "14.52", + "moid_au": "0.028", + "orbit_class": "Apollo", + "period_yr": "1", + "pha": "Y", + "q_au_1": "0.93", + "q_au_2": "1.08" + }, + { + "designation": "414772 (2010 OC103)", + "discovery_date": "2010-07-28T00:00:00.000Z", + "h_mag": "19", + "i_deg": "23.11", + "moid_au": "0.333", + "orbit_class": "Apollo", + "period_yr": "1.31", + "pha": "N", + "q_au_1": "0.39", + "q_au_2": "2" + }, + { + "designation": "414746 (2010 EH20)", + "discovery_date": "2010-03-06T00:00:00.000Z", + "h_mag": "18", + "i_deg": "23.89", + "moid_au": "0.268", + "orbit_class": "Amor", + "period_yr": "4.24", + "pha": "N", + "q_au_1": "1.25", + "q_au_2": "3.99" + }, + { + "designation": "407324 (2010 OB101)", + "discovery_date": "2010-07-18T00:00:00.000Z", + "h_mag": "20.7", + "i_deg": "9.12", + "moid_au": "0.111", + "orbit_class": "Apollo", + "period_yr": "2.06", + "pha": "N", + "q_au_1": "0.77", + "q_au_2": "2.46" + }, + { + "designation": "398188 (2010 LE15)", + "discovery_date": "2010-06-03T00:00:00.000Z", + "h_mag": "19.5", + "i_deg": "13.25", + "moid_au": "0.024", + "orbit_class": "Aten", + "period_yr": "0.8", + "pha": "Y", + "q_au_1": "0.63", + "q_au_2": "1.1" + }, + { + "designation": "395207 (2010 HQ80)", + "discovery_date": "2010-04-25T00:00:00.000Z", + "h_mag": "19.6", + "i_deg": "27.85", + "moid_au": "0.007", + "orbit_class": "Apollo", + "period_yr": "1.96", + "pha": "Y", + "q_au_1": "0.8", + "q_au_2": "2.34" + }, + { + "designation": "386847 (2010 LR33)", + "discovery_date": "2010-06-06T00:00:00.000Z", + "h_mag": "18", + "i_deg": "5.84", + "moid_au": "0.029", + "orbit_class": "Apollo", + "period_yr": "2.2", + "pha": "Y", + "q_au_1": "0.91", + "q_au_2": "2.48" + }, + { + "designation": "381989 (2010 HR80)", + "discovery_date": "2010-04-28T00:00:00.000Z", + "h_mag": "19.9", + "i_deg": "26.71", + "moid_au": "0.104", + "orbit_class": "Apollo", + "period_yr": "1.56", + "pha": "N", + "q_au_1": "0.68", + "q_au_2": "2.02" + }, + { + "designation": "369454 (2010 NZ1)", + "discovery_date": "2010-07-09T00:00:00.000Z", + "h_mag": "19.4", + "i_deg": "32.78", + "moid_au": "0.275", + "orbit_class": "Apollo", + "period_yr": "1.61", + "pha": "N", + "q_au_1": "0.49", + "q_au_2": "2.26" + }, + { + "designation": "365449 (2010 NJ1)", + "discovery_date": "2010-07-03T00:00:00.000Z", + "h_mag": "20.3", + "i_deg": "11.23", + "moid_au": "0.155", + "orbit_class": "Aten", + "period_yr": "0.95", + "pha": "N", + "q_au_1": "0.44", + "q_au_2": "1.49" + }, + { + "designation": "365424 (2010 KX7)", + "discovery_date": "2010-05-16T00:00:00.000Z", + "h_mag": "21.9", + "i_deg": "21.49", + "moid_au": "0.034", + "orbit_class": "Aten", + "period_yr": "0.98", + "pha": "Y", + "q_au_1": "0.82", + "q_au_2": "1.16" + }, + { + "designation": "356394 (2010 QD2)", + "discovery_date": "2010-08-21T00:00:00.000Z", + "h_mag": "17.4", + "i_deg": "10.64", + "moid_au": "0.061", + "orbit_class": "Apollo", + "period_yr": "2.85", + "pha": "N", + "q_au_1": "0.43", + "q_au_2": "3.59" + }, + { + "designation": "(2015 HF11)", + "discovery_date": "2015-04-17T00:00:00.000Z", + "h_mag": "19.2", + "i_deg": "34.89", + "moid_au": "0.225", + "orbit_class": "Amor", + "period_yr": "2.99", + "pha": "N", + "q_au_1": "1.22", + "q_au_2": "2.93" + }, + { + "designation": "(2015 GK50)", + "discovery_date": "2015-04-05T00:00:00.000Z", + "h_mag": "20.5", + "i_deg": "19.07", + "moid_au": "0.237", + "orbit_class": "Amor", + "period_yr": "5.39", + "pha": "N", + "q_au_1": "1.03", + "q_au_2": "5.12" + }, + { + "designation": "(2015 GJ46)", + "discovery_date": "2015-04-11T00:00:00.000Z", + "h_mag": "19.3", + "i_deg": "18.22", + "moid_au": "0.238", + "orbit_class": "Apollo", + "period_yr": "4.85", + "pha": "N", + "q_au_1": "0.67", + "q_au_2": "5.06" + }, + { + "designation": "(2015 FT344)", + "discovery_date": "2015-03-23T00:00:00.000Z", + "h_mag": "20.5", + "i_deg": "12.55", + "moid_au": "0.203", + "orbit_class": "Amor", + "period_yr": "4.07", + "pha": "N", + "q_au_1": "1.09", + "q_au_2": "4.01" + }, + { + "designation": "(2015 FD341)", + "discovery_date": "2015-03-27T00:00:00.000Z", + "h_mag": "18", + "i_deg": "20.55", + "moid_au": "0.124", + "orbit_class": "Aten", + "period_yr": "0.93", + "pha": "N", + "q_au_1": "0.31", + "q_au_2": "1.6" + }, + { + "designation": "(2015 FU332)", + "discovery_date": "2015-03-31T00:00:00.000Z", + "h_mag": "17.3", + "i_deg": "36.11", + "moid_au": "0.269", + "orbit_class": "Apollo", + "period_yr": "4.27", + "pha": "N", + "q_au_1": "0.67", + "q_au_2": "4.59" + }, + { + "designation": "(2015 FE120)", + "discovery_date": "2015-03-23T00:00:00.000Z", + "h_mag": "21.1", + "i_deg": "22.8", + "moid_au": "0.013", + "orbit_class": "Apollo", + "period_yr": "3.38", + "pha": "Y", + "q_au_1": "1.01", + "q_au_2": "3.49" + }, + { + "designation": "(2015 FY117)", + "discovery_date": "2015-03-20T00:00:00.000Z", + "h_mag": "21.2", + "i_deg": "24.33", + "moid_au": "0.15", + "orbit_class": "Amor", + "period_yr": "2.87", + "pha": "N", + "q_au_1": "1.14", + "q_au_2": "2.9" + }, + { + "designation": "(2015 DX198)", + "discovery_date": "2015-02-17T00:00:00.000Z", + "h_mag": "22.1", + "i_deg": "11.05", + "moid_au": "0.074", + "orbit_class": "Amor", + "period_yr": "2.1", + "pha": "N", + "q_au_1": "1.02", + "q_au_2": "2.25" + }, + { + "designation": "(2015 BY516)", + "discovery_date": "2015-01-30T00:00:00.000Z", + "h_mag": "22.3", + "i_deg": "12.71", + "moid_au": "0.139", + "orbit_class": "Apollo", + "period_yr": "3.66", + "pha": "N", + "q_au_1": "0.97", + "q_au_2": "3.77" + }, + { + "designation": "(2015 AK280)", + "discovery_date": "2015-01-15T00:00:00.000Z", + "h_mag": "21.8", + "i_deg": "11.37", + "moid_au": "0.049", + "orbit_class": "Apollo", + "period_yr": "4.33", + "pha": "Y", + "q_au_1": "0.79", + "q_au_2": "4.53" + }, + { + "designation": "(2015 AY245)", + "discovery_date": "2015-01-14T00:00:00.000Z", + "h_mag": "21.2", + "i_deg": "13.59", + "moid_au": "0.019", + "orbit_class": "Apollo", + "period_yr": "1.2", + "pha": "Y", + "q_au_1": "1", + "q_au_2": "1.25" + }, + { + "designation": "(2015 AC17)", + "discovery_date": "2015-01-03T00:00:00.000Z", + "h_mag": "19.9", + "i_deg": "29.25", + "moid_au": "0.238", + "orbit_class": "Amor", + "period_yr": "3.39", + "pha": "N", + "q_au_1": "1.22", + "q_au_2": "3.29" + }, + { + "designation": "(2014 YR43)", + "discovery_date": "2014-12-26T00:00:00.000Z", + "h_mag": "19.5", + "i_deg": "26.46", + "moid_au": "0.303", + "orbit_class": "Apollo", + "period_yr": "3.92", + "pha": "N", + "q_au_1": "0.97", + "q_au_2": "4" + }, + { + "designation": "(2014 YS14)", + "discovery_date": "2014-12-24T00:00:00.000Z", + "h_mag": "21.1", + "i_deg": "18.29", + "moid_au": "0.127", + "orbit_class": "Apollo", + "period_yr": "3.87", + "pha": "N", + "q_au_1": "0.84", + "q_au_2": "4.09" + }, + { + "designation": "(2014 XX31)", + "discovery_date": "2014-12-11T00:00:00.000Z", + "h_mag": "17.5", + "i_deg": "35.78", + "moid_au": "0.475", + "orbit_class": "Apollo", + "period_yr": "4.73", + "pha": "N", + "q_au_1": "0.36", + "q_au_2": "5.28" + }, + { + "designation": "(2014 XX7)", + "discovery_date": "2014-12-10T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "36.71", + "moid_au": "0.183", + "orbit_class": "Amor", + "period_yr": "4.94", + "pha": "N", + "q_au_1": "1.17", + "q_au_2": "4.64" + }, + { + "designation": "(2014 XQ7)", + "discovery_date": "2014-12-06T00:00:00.000Z", + "h_mag": "20.6", + "i_deg": "31.05", + "moid_au": "0.312", + "orbit_class": "Apollo", + "period_yr": "4.32", + "pha": "N", + "q_au_1": "0.66", + "q_au_2": "4.65" + }, + { + "designation": "(2014 VP35)", + "discovery_date": "2014-11-14T00:00:00.000Z", + "h_mag": "23.3", + "i_deg": "9.17", + "moid_au": "0.026", + "orbit_class": "Apollo", + "period_yr": "1.78", + "pha": "N", + "q_au_1": "0.95", + "q_au_2": "1.98" + }, + { + "designation": "(2014 UH210)", + "discovery_date": "2014-10-20T00:00:00.000Z", + "h_mag": "21.1", + "i_deg": "22.06", + "moid_au": "0.099", + "orbit_class": "Apollo", + "period_yr": "4.11", + "pha": "N", + "q_au_1": "0.89", + "q_au_2": "4.25" + }, + { + "designation": "(2014 UF206)", + "discovery_date": "2014-10-31T00:00:00.000Z", + "h_mag": "18.8", + "i_deg": "48.05", + "moid_au": "0.136", + "orbit_class": "Amor", + "period_yr": "3.78", + "pha": "N", + "q_au_1": "1.11", + "q_au_2": "3.74" + }, + { + "designation": "(2014 UG176)", + "discovery_date": "2014-10-25T00:00:00.000Z", + "h_mag": "21.5", + "i_deg": "16.3", + "moid_au": "0.16", + "orbit_class": "Apollo", + "period_yr": "4.44", + "pha": "N", + "q_au_1": "0.78", + "q_au_2": "4.62" + }, + { + "designation": "(2014 TJ64)", + "discovery_date": "2014-10-07T00:00:00.000Z", + "h_mag": "21.2", + "i_deg": "14.91", + "moid_au": "0.154", + "orbit_class": "Amor", + "period_yr": "4.24", + "pha": "N", + "q_au_1": "1.05", + "q_au_2": "4.19" + }, + { + "designation": "(2014 TF64)", + "discovery_date": "2014-10-05T00:00:00.000Z", + "h_mag": "20.1", + "i_deg": "52.66", + "moid_au": "0.131", + "orbit_class": "Apollo", + "period_yr": "2.05", + "pha": "N", + "q_au_1": "0.94", + "q_au_2": "2.29" + }, + { + "designation": "(2014 TW57)", + "discovery_date": "2014-10-10T00:00:00.000Z", + "h_mag": "20.1", + "i_deg": "6.75", + "moid_au": "0.062", + "orbit_class": "Apollo", + "period_yr": "3.21", + "pha": "N", + "q_au_1": "0.57", + "q_au_2": "3.78" + }, + { + "designation": "(2014 SR339)", + "discovery_date": "2014-09-30T00:00:00.000Z", + "h_mag": "18.6", + "i_deg": "29.79", + "moid_au": "0.036", + "orbit_class": "Apollo", + "period_yr": "1.48", + "pha": "Y", + "q_au_1": "0.9", + "q_au_2": "1.69" + }, + { + "designation": "(2014 RH12)", + "discovery_date": "2014-09-03T00:00:00.000Z", + "h_mag": "23.5", + "i_deg": "7.23", + "moid_au": "0.045", + "orbit_class": "Apollo", + "period_yr": "3.22", + "pha": "N", + "q_au_1": "1.01", + "q_au_2": "3.35" + }, + { + "designation": "(2014 QK433)", + "discovery_date": "2014-08-28T00:00:00.000Z", + "h_mag": "18.2", + "i_deg": "39.22", + "moid_au": "0.18", + "orbit_class": "Amor", + "period_yr": "5.16", + "pha": "N", + "q_au_1": "1.19", + "q_au_2": "4.78" + }, + { + "designation": "(2014 PP69)", + "discovery_date": "2014-08-05T00:00:00.000Z", + "h_mag": "20", + "i_deg": "93.63", + "moid_au": "1.617", + "orbit_class": "Amor", + "period_yr": "99.82", + "pha": "N", + "q_au_1": "1.25", + "q_au_2": "41.78" + }, + { + "designation": "(2014 PF68)", + "discovery_date": "2014-08-15T00:00:00.000Z", + "h_mag": "18.2", + "i_deg": "22.75", + "moid_au": "0.17", + "orbit_class": "Amor", + "period_yr": "4.81", + "pha": "N", + "q_au_1": "1.17", + "q_au_2": "4.53" + }, + { + "designation": "(2014 PC68)", + "discovery_date": "2014-08-08T00:00:00.000Z", + "h_mag": "20.4", + "i_deg": "40.68", + "moid_au": "0.104", + "orbit_class": "Amor", + "period_yr": "1.87", + "pha": "N", + "q_au_1": "1.09", + "q_au_2": "1.95" + }, + { + "designation": "(2014 OZ1)", + "discovery_date": "2014-07-20T00:00:00.000Z", + "h_mag": "21", + "i_deg": "18", + "moid_au": "0.231", + "orbit_class": "Amor", + "period_yr": "2.24", + "pha": "N", + "q_au_1": "1.08", + "q_au_2": "2.35" + }, + { + "designation": "(2014 OY1)", + "discovery_date": "2014-07-21T00:00:00.000Z", + "h_mag": "19.1", + "i_deg": "23.01", + "moid_au": "0.042", + "orbit_class": "Apollo", + "period_yr": "4.14", + "pha": "Y", + "q_au_1": "0.97", + "q_au_2": "4.19" + }, + { + "designation": "(2014 NM64)", + "discovery_date": "2014-07-11T00:00:00.000Z", + "h_mag": "22.6", + "i_deg": "28.78", + "moid_au": "0.051", + "orbit_class": "Amor", + "period_yr": "4.79", + "pha": "N", + "q_au_1": "1.06", + "q_au_2": "4.62" + }, + { + "designation": "(2014 NE64)", + "discovery_date": "2014-07-07T00:00:00.000Z", + "h_mag": "18.8", + "i_deg": "41.63", + "moid_au": "0.39", + "orbit_class": "Amor", + "period_yr": "3.06", + "pha": "N", + "q_au_1": "1.2", + "q_au_2": "3.01" + }, + { + "designation": "(2014 NC64)", + "discovery_date": "2014-07-13T00:00:00.000Z", + "h_mag": "20.2", + "i_deg": "22.68", + "moid_au": "0.196", + "orbit_class": "Apollo", + "period_yr": "3.23", + "pha": "N", + "q_au_1": "0.8", + "q_au_2": "3.57" + }, + { + "designation": "(2014 NF3)", + "discovery_date": "2014-07-01T00:00:00.000Z", + "h_mag": "20.8", + "i_deg": "13.53", + "moid_au": "0.215", + "orbit_class": "Apollo", + "period_yr": "1.48", + "pha": "N", + "q_au_1": "0.66", + "q_au_2": "1.94" + }, + { + "designation": "C/2014 N3 (NEOWISE)", + "discovery_date": "2014-07-04T00:00:00.000Z", + "i_deg": "61.63", + "moid_au": "2.888", + "orbit_class": "Comet", + "period_yr": "745640.58", + "pha": "n/a", + "q_au_1": "3.88", + "q_au_2": "16441.51" + }, + { + "designation": "(2014 MQ18)", + "discovery_date": "2014-06-22T00:00:00.000Z", + "h_mag": "15.6", + "i_deg": "35.09", + "moid_au": "0.192", + "orbit_class": "Amor", + "period_yr": "4.93", + "pha": "N", + "q_au_1": "1.16", + "q_au_2": "4.63" + }, + { + "designation": "(2014 LQ25)", + "discovery_date": "2014-06-08T00:00:00.000Z", + "h_mag": "20", + "i_deg": "33.57", + "moid_au": "0.099", + "orbit_class": "Apollo", + "period_yr": "2.88", + "pha": "N", + "q_au_1": "0.65", + "q_au_2": "3.39" + }, + { + "designation": "P/2014 L2 (NEOWISE)", + "discovery_date": "2014-06-07T00:00:00.000Z", + "i_deg": "5.18", + "moid_au": "1.224", + "orbit_class": "Jupiter-family Comet", + "period_yr": "15.91", + "pha": "n/a", + "q_au_1": "2.23", + "q_au_2": "10.42" + }, + { + "designation": "(2014 JN57)", + "discovery_date": "2014-05-11T00:00:00.000Z", + "h_mag": "20.6", + "i_deg": "28.59", + "moid_au": "0.051", + "orbit_class": "Amor", + "period_yr": "1.39", + "pha": "N", + "q_au_1": "1.03", + "q_au_2": "1.45" + }, + { + "designation": "(2014 JH57)", + "discovery_date": "2014-05-10T00:00:00.000Z", + "h_mag": "16.2", + "i_deg": "26.54", + "moid_au": "0.418", + "orbit_class": "Apollo", + "period_yr": "6.13", + "pha": "N", + "q_au_1": "0.43", + "q_au_2": "6.27" + }, + { + "designation": "(2014 JL25)", + "discovery_date": "2014-05-04T00:00:00.000Z", + "h_mag": "23", + "i_deg": "15.75", + "moid_au": "0.012", + "orbit_class": "Apollo", + "period_yr": "4.94", + "pha": "N", + "q_au_1": "1", + "q_au_2": "4.8" + }, + { + "designation": "(2014 HJ129)", + "discovery_date": "2014-04-24T00:00:00.000Z", + "h_mag": "21.1", + "i_deg": "8.44", + "moid_au": "0.212", + "orbit_class": "Amor", + "period_yr": "4.16", + "pha": "N", + "q_au_1": "1.13", + "q_au_2": "4.04" + }, + { + "designation": "(2014 HQ124)", + "discovery_date": "2014-04-23T00:00:00.000Z", + "h_mag": "18.9", + "i_deg": "26.37", + "moid_au": "0.007", + "orbit_class": "Aten", + "period_yr": "0.78", + "pha": "Y", + "q_au_1": "0.63", + "q_au_2": "1.07" + }, + { + "designation": "(2014 EQ49)", + "discovery_date": "2014-03-15T00:00:00.000Z", + "h_mag": "21.8", + "i_deg": "15.18", + "moid_au": "0.026", + "orbit_class": "Apollo", + "period_yr": "1.23", + "pha": "Y", + "q_au_1": "0.91", + "q_au_2": "1.39" + }, + { + "designation": "(2014 EN45)", + "discovery_date": "2014-03-06T00:00:00.000Z", + "h_mag": "21.2", + "i_deg": "14.03", + "moid_au": "0.156", + "orbit_class": "Amor", + "period_yr": "3.82", + "pha": "N", + "q_au_1": "1.06", + "q_au_2": "3.83" + }, + { + "designation": "(2014 ED)", + "discovery_date": "2014-03-01T00:00:00.000Z", + "h_mag": "19.3", + "i_deg": "21.77", + "moid_au": "0.365", + "orbit_class": "Apollo", + "period_yr": "1.92", + "pha": "N", + "q_au_1": "0.56", + "q_au_2": "2.53" + }, + { + "designation": "(2014 CF14)", + "discovery_date": "2014-02-07T00:00:00.000Z", + "h_mag": "18.1", + "i_deg": "29.41", + "moid_au": "0.149", + "orbit_class": "Apollo", + "period_yr": "2.83", + "pha": "N", + "q_au_1": "0.82", + "q_au_2": "3.17" + }, + { + "designation": "(2014 CY4)", + "discovery_date": "2014-02-04T00:00:00.000Z", + "h_mag": "21.1", + "i_deg": "15.02", + "moid_au": "0.042", + "orbit_class": "Apollo", + "period_yr": "4.32", + "pha": "Y", + "q_au_1": "0.48", + "q_au_2": "4.82" + }, + { + "designation": "C/2014 C3 (NEOWISE)", + "discovery_date": "2014-02-14T00:00:00.000Z", + "i_deg": "151.78", + "moid_au": "0.866", + "orbit_class": "Comet", + "period_yr": "1128.89", + "pha": "n/a", + "q_au_1": "1.86", + "q_au_2": "214.97" + }, + { + "designation": "(2014 BE63)", + "discovery_date": "2014-01-23T00:00:00.000Z", + "h_mag": "23.2", + "i_deg": "8.59", + "moid_au": "0.133", + "orbit_class": "Apollo", + "period_yr": "3.08", + "pha": "N", + "q_au_1": "0.75", + "q_au_2": "3.48" + }, + { + "designation": "(2014 BG60)", + "discovery_date": "2014-01-25T00:00:00.000Z", + "h_mag": "20.1", + "i_deg": "8.61", + "moid_au": "0.227", + "orbit_class": "Amor", + "period_yr": "5.27", + "pha": "N", + "q_au_1": "1.17", + "q_au_2": "4.89" + }, + { + "designation": "(2014 AA53)", + "discovery_date": "2014-01-13T00:00:00.000Z", + "h_mag": "19.8", + "i_deg": "12.45", + "moid_au": "0.14", + "orbit_class": "Apollo", + "period_yr": "3.66", + "pha": "N", + "q_au_1": "0.78", + "q_au_2": "3.97" + }, + { + "designation": "(2014 AQ46)", + "discovery_date": "2014-01-02T00:00:00.000Z", + "h_mag": "20.1", + "i_deg": "24.6", + "moid_au": "0.205", + "orbit_class": "Amor", + "period_yr": "3.75", + "pha": "N", + "q_au_1": "1.13", + "q_au_2": "3.7" + }, + { + "designation": "(2013 YP139)", + "discovery_date": "2013-12-29T00:00:00.000Z", + "h_mag": "21.6", + "i_deg": "0.82", + "moid_au": "0.004", + "orbit_class": "Apollo", + "period_yr": "3.73", + "pha": "Y", + "q_au_1": "0.76", + "q_au_2": "4.05" + }, + { + "designation": "(2011 BN59)", + "discovery_date": "2011-01-29T00:00:00.000Z", + "h_mag": "20.4", + "i_deg": "20.32", + "moid_au": "0.326", + "orbit_class": "Amor", + "period_yr": "5.36", + "pha": "N", + "q_au_1": "1.16", + "q_au_2": "4.97" + }, + { + "designation": "(2011 BY24)", + "discovery_date": "2011-01-24T00:00:00.000Z", + "h_mag": "22.6", + "i_deg": "13.95", + "moid_au": "0.017", + "orbit_class": "Apollo", + "period_yr": "2.6", + "pha": "N", + "q_au_1": "0.96", + "q_au_2": "2.83" + }, + { + "designation": "(2010 YD3)", + "discovery_date": "2010-12-26T00:00:00.000Z", + "h_mag": "20", + "i_deg": "24.61", + "moid_au": "0.195", + "orbit_class": "Amor", + "period_yr": "4.14", + "pha": "N", + "q_au_1": "1.11", + "q_au_2": "4.05" + }, + { + "designation": "(2010 YC1)", + "discovery_date": "2010-12-21T00:00:00.000Z", + "h_mag": "21.3", + "i_deg": "17.66", + "moid_au": "0.163", + "orbit_class": "Apollo", + "period_yr": "1.68", + "pha": "N", + "q_au_1": "0.83", + "q_au_2": "2" + }, + { + "designation": "(2010 XY82)", + "discovery_date": "2010-12-14T00:00:00.000Z", + "h_mag": "19.1", + "i_deg": "26.73", + "moid_au": "0.294", + "orbit_class": "Amor", + "period_yr": "3.24", + "pha": "N", + "q_au_1": "1.12", + "q_au_2": "3.26" + }, + { + "designation": "(2010 XP69)", + "discovery_date": "2010-12-08T00:00:00.000Z", + "h_mag": "21.4", + "i_deg": "14.6", + "moid_au": "0.015", + "orbit_class": "Apollo", + "period_yr": "1.88", + "pha": "Y", + "q_au_1": "1", + "q_au_2": "2.05" + }, + { + "designation": "(2010 XZ67)", + "discovery_date": "2010-12-10T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "11.84", + "moid_au": "0.063", + "orbit_class": "Amor", + "period_yr": "2.96", + "pha": "N", + "q_au_1": "1.04", + "q_au_2": "3.08" + }, + { + "designation": "(2010 WE9)", + "discovery_date": "2010-11-23T00:00:00.000Z", + "h_mag": "20", + "i_deg": "42.12", + "moid_au": "0.256", + "orbit_class": "Amor", + "period_yr": "1.94", + "pha": "N", + "q_au_1": "1.17", + "q_au_2": "1.94" + }, + { + "designation": "(2010 UB8)", + "discovery_date": "2010-10-27T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "30.97", + "moid_au": "0.194", + "orbit_class": "Amor", + "period_yr": "5.15", + "pha": "N", + "q_au_1": "1.11", + "q_au_2": "4.85" + }, + { + "designation": "(2010 UY6)", + "discovery_date": "2010-10-23T00:00:00.000Z", + "h_mag": "20.1", + "i_deg": "19.98", + "moid_au": "0.062", + "orbit_class": "Amor", + "period_yr": "4.34", + "pha": "N", + "q_au_1": "1.04", + "q_au_2": "4.28" + }, + { + "designation": "(2010 TK7)", + "discovery_date": "2010-10-01T00:00:00.000Z", + "h_mag": "20.8", + "i_deg": "20.89", + "moid_au": "0.087", + "orbit_class": "Aten", + "period_yr": "1", + "pha": "N", + "q_au_1": "0.81", + "q_au_2": "1.19" + }, + { + "designation": "(2010 QA5)", + "discovery_date": "2010-08-29T00:00:00.000Z", + "h_mag": "22.5", + "i_deg": "33.45", + "moid_au": "0.065", + "orbit_class": "Amor", + "period_yr": "4.97", + "pha": "N", + "q_au_1": "1.07", + "q_au_2": "4.76" + }, + { + "designation": "(2010 QE2)", + "discovery_date": "2010-08-25T00:00:00.000Z", + "h_mag": "17.2", + "i_deg": "64.75", + "moid_au": "0.056", + "orbit_class": "Apollo", + "period_yr": "6.19", + "pha": "N", + "q_au_1": "0.88", + "q_au_2": "5.86" + }, + { + "designation": "(2010 PY75)", + "discovery_date": "2010-08-15T00:00:00.000Z", + "h_mag": "18.7", + "i_deg": "31.29", + "moid_au": "0.243", + "orbit_class": "Apollo", + "period_yr": "4.34", + "pha": "N", + "q_au_1": "0.6", + "q_au_2": "4.72" + }, + { + "designation": "(2010 PU66)", + "discovery_date": "2010-08-03T00:00:00.000Z", + "h_mag": "22.1", + "i_deg": "18.09", + "moid_au": "0.148", + "orbit_class": "Apollo", + "period_yr": "1.81", + "pha": "N", + "q_au_1": "0.91", + "q_au_2": "2.07" + }, + { + "designation": "(2010 PW58)", + "discovery_date": "2010-08-05T00:00:00.000Z", + "h_mag": "21.3", + "i_deg": "14.24", + "moid_au": "0.021", + "orbit_class": "Aten", + "period_yr": "0.84", + "pha": "Y", + "q_au_1": "0.7", + "q_au_2": "1.08" + }, + { + "designation": "(2010 PP58)", + "discovery_date": "2010-08-05T00:00:00.000Z", + "h_mag": "22.1", + "i_deg": "4.55", + "moid_au": "0.014", + "orbit_class": "Apollo", + "period_yr": "2.81", + "pha": "N", + "q_au_1": "0.99", + "q_au_2": "3" + }, + { + "designation": "(2010 PM58)", + "discovery_date": "2010-08-01T00:00:00.000Z", + "h_mag": "20.9", + "i_deg": "13.6", + "moid_au": "0.096", + "orbit_class": "Apollo", + "period_yr": "1.61", + "pha": "N", + "q_au_1": "0.74", + "q_au_2": "2" + }, + { + "designation": "P/2010 P4 (WISE)", + "discovery_date": "2010-08-06T00:00:00.000Z", + "i_deg": "24.1", + "moid_au": "0.854", + "orbit_class": "Jupiter-family Comet", + "period_yr": "7.13", + "pha": "n/a", + "q_au_1": "1.86", + "q_au_2": "5.55" + }, + { + "designation": "(2010 OK126)", + "discovery_date": "2010-07-30T00:00:00.000Z", + "h_mag": "20.7", + "i_deg": "52.56", + "moid_au": "0.149", + "orbit_class": "Amor", + "period_yr": "2.74", + "pha": "N", + "q_au_1": "1.08", + "q_au_2": "2.83" + }, + { + "designation": "(2010 OH126)", + "discovery_date": "2010-07-31T00:00:00.000Z", + "h_mag": "21.4", + "i_deg": "14.38", + "moid_au": "0.068", + "orbit_class": "Apollo", + "period_yr": "2.62", + "pha": "N", + "q_au_1": "0.95", + "q_au_2": "2.85" + }, + { + "designation": "(2010 ON101)", + "discovery_date": "2010-07-30T00:00:00.000Z", + "h_mag": "20.2", + "i_deg": "9.31", + "moid_au": "0.044", + "orbit_class": "Apollo", + "period_yr": "2.08", + "pha": "Y", + "q_au_1": "0.96", + "q_au_2": "2.3" + }, + { + "designation": "(2010 OL101)", + "discovery_date": "2010-07-27T00:00:00.000Z", + "h_mag": "20.4", + "i_deg": "26.11", + "moid_au": "0.298", + "orbit_class": "Amor", + "period_yr": "4.22", + "pha": "N", + "q_au_1": "1.05", + "q_au_2": "4.17" + }, + { + "designation": "(2010 OF101)", + "discovery_date": "2010-07-23T00:00:00.000Z", + "h_mag": "19.6", + "i_deg": "23.37", + "moid_au": "0.062", + "orbit_class": "Aten", + "period_yr": "0.93", + "pha": "N", + "q_au_1": "0.64", + "q_au_2": "1.26" + }, + { + "designation": "(2010 OD101)", + "discovery_date": "2010-07-23T00:00:00.000Z", + "h_mag": "20.7", + "i_deg": "15.39", + "moid_au": "0.19", + "orbit_class": "Amor", + "period_yr": "2.06", + "pha": "N", + "q_au_1": "1.04", + "q_au_2": "2.2" + }, + { + "designation": "(2010 OC101)", + "discovery_date": "2010-07-22T00:00:00.000Z", + "h_mag": "20.7", + "i_deg": "13.6", + "moid_au": "0.092", + "orbit_class": "Apollo", + "period_yr": "1.35", + "pha": "N", + "q_au_1": "0.94", + "q_au_2": "1.5" + }, + { + "designation": "(2010 OL100)", + "discovery_date": "2010-07-28T00:00:00.000Z", + "h_mag": "19.6", + "i_deg": "22.16", + "moid_au": "0.129", + "orbit_class": "Apollo", + "period_yr": "3.4", + "pha": "N", + "q_au_1": "0.78", + "q_au_2": "3.74" + }, + { + "designation": "(2010 OE22)", + "discovery_date": "2010-07-17T00:00:00.000Z", + "h_mag": "21.3", + "i_deg": "14.32", + "moid_au": "0.178", + "orbit_class": "Apollo", + "period_yr": "4.28", + "pha": "N", + "q_au_1": "0.97", + "q_au_2": "4.31" + }, + { + "designation": "(2010 NY65)", + "discovery_date": "2010-07-14T00:00:00.000Z", + "h_mag": "21.4", + "i_deg": "11.74", + "moid_au": "0.017", + "orbit_class": "Aten", + "period_yr": "1", + "pha": "Y", + "q_au_1": "0.63", + "q_au_2": "1.37" + }, + { + "designation": "(2010 NG3)", + "discovery_date": "2010-07-08T00:00:00.000Z", + "h_mag": "17.2", + "i_deg": "26.96", + "moid_au": "0.127", + "orbit_class": "Amor", + "period_yr": "4.2", + "pha": "N", + "q_au_1": "1.13", + "q_au_2": "4.08" + }, + { + "designation": "(2010 NB2)", + "discovery_date": "2010-07-10T00:00:00.000Z", + "h_mag": "20.3", + "i_deg": "28.66", + "moid_au": "0.102", + "orbit_class": "Apollo", + "period_yr": "3.01", + "pha": "N", + "q_au_1": "0.5", + "q_au_2": "3.67" + }, + { + "designation": "(2010 NU1)", + "discovery_date": "2010-07-06T00:00:00.000Z", + "h_mag": "21.2", + "i_deg": "34.58", + "moid_au": "0.336", + "orbit_class": "Apollo", + "period_yr": "3.74", + "pha": "N", + "q_au_1": "0.48", + "q_au_2": "4.33" + }, + { + "designation": "(2010 NT1)", + "discovery_date": "2010-07-04T00:00:00.000Z", + "h_mag": "19.4", + "i_deg": "39.52", + "moid_au": "0.208", + "orbit_class": "Amor", + "period_yr": "1.76", + "pha": "N", + "q_au_1": "1.14", + "q_au_2": "1.78" + }, + { + "designation": "(2010 NG1)", + "discovery_date": "2010-07-02T00:00:00.000Z", + "h_mag": "20.4", + "i_deg": "24.74", + "moid_au": "0.081", + "orbit_class": "Aten", + "period_yr": "0.78", + "pha": "N", + "q_au_1": "0.57", + "q_au_2": "1.13" + }, + { + "designation": "P/2010 N1 (WISE)", + "discovery_date": "2010-07-05T00:00:00.000Z", + "i_deg": "12.88", + "moid_au": "0.491", + "orbit_class": "Jupiter-family Comet", + "period_yr": "5.74", + "pha": "n/a", + "q_au_1": "1.49", + "q_au_2": "4.92" + }, + { + "designation": "(2010 MA113)", + "discovery_date": "2010-06-25T00:00:00.000Z", + "h_mag": "19.2", + "i_deg": "39.85", + "moid_au": "0.081", + "orbit_class": "Apollo", + "period_yr": "3.46", + "pha": "N", + "q_au_1": "0.89", + "q_au_2": "3.68" + }, + { + "designation": "(2010 MZ112)", + "discovery_date": "2010-06-23T00:00:00.000Z", + "h_mag": "19.8", + "i_deg": "30.18", + "moid_au": "0.221", + "orbit_class": "Apollo", + "period_yr": "2.36", + "pha": "N", + "q_au_1": "0.49", + "q_au_2": "3.06" + }, + { + "designation": "(2010 MY112)", + "discovery_date": "2010-06-23T00:00:00.000Z", + "h_mag": "21", + "i_deg": "38.49", + "moid_au": "0.156", + "orbit_class": "Apollo", + "period_yr": "1.1", + "pha": "N", + "q_au_1": "0.8", + "q_au_2": "1.33" + }, + { + "designation": "(2010 MU112)", + "discovery_date": "2010-06-30T00:00:00.000Z", + "h_mag": "20.7", + "i_deg": "48.02", + "moid_au": "0.0002", + "orbit_class": "Apollo", + "period_yr": "2.33", + "pha": "Y", + "q_au_1": "0.81", + "q_au_2": "2.71" + }, + { + "designation": "(2010 MU111)", + "discovery_date": "2010-06-23T00:00:00.000Z", + "h_mag": "18.7", + "i_deg": "41.53", + "moid_au": "0.059", + "orbit_class": "Apollo", + "period_yr": "3.7", + "pha": "N", + "q_au_1": "0.92", + "q_au_2": "3.86" + }, + { + "designation": "(2010 MR87)", + "discovery_date": "2010-06-22T00:00:00.000Z", + "h_mag": "19.5", + "i_deg": "34.98", + "moid_au": "0.15", + "orbit_class": "Amor", + "period_yr": "2.28", + "pha": "N", + "q_au_1": "1.06", + "q_au_2": "2.41" + }, + { + "designation": "(2010 LU134)", + "discovery_date": "2010-06-14T00:00:00.000Z", + "h_mag": "19.5", + "i_deg": "27.39", + "moid_au": "0.146", + "orbit_class": "Apollo", + "period_yr": "2.61", + "pha": "N", + "q_au_1": "0.86", + "q_au_2": "2.93" + }, + { + "designation": "(2010 LV108)", + "discovery_date": "2010-06-14T00:00:00.000Z", + "h_mag": "22.6", + "i_deg": "5.43", + "moid_au": "0.006", + "orbit_class": "Apollo", + "period_yr": "4.64", + "pha": "N", + "q_au_1": "1.01", + "q_au_2": "4.55" + }, + { + "designation": "(2010 LU108)", + "discovery_date": "2010-06-15T00:00:00.000Z", + "h_mag": "20", + "i_deg": "9.51", + "moid_au": "0.126", + "orbit_class": "Apollo", + "period_yr": "3.35", + "pha": "N", + "q_au_1": "0.41", + "q_au_2": "4.08" + }, + { + "designation": "(2010 LT108)", + "discovery_date": "2010-06-13T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "31.87", + "moid_au": "0.138", + "orbit_class": "Apollo", + "period_yr": "1.57", + "pha": "N", + "q_au_1": "0.85", + "q_au_2": "1.85" + }, + { + "designation": "(2010 LO97)", + "discovery_date": "2010-06-13T00:00:00.000Z", + "h_mag": "18.7", + "i_deg": "21.65", + "moid_au": "0.233", + "orbit_class": "Amor", + "period_yr": "4.14", + "pha": "N", + "q_au_1": "1.22", + "q_au_2": "3.94" + }, + { + "designation": "(2010 LF86)", + "discovery_date": "2010-06-11T00:00:00.000Z", + "h_mag": "17.2", + "i_deg": "13.55", + "moid_au": "0.318", + "orbit_class": "Amor", + "period_yr": "3.73", + "pha": "N", + "q_au_1": "1.3", + "q_au_2": "3.51" + }, + { + "designation": "(2010 LR68)", + "discovery_date": "2010-06-08T00:00:00.000Z", + "h_mag": "18.3", + "i_deg": "4.58", + "moid_au": "0.216", + "orbit_class": "Amor", + "period_yr": "5.29", + "pha": "N", + "q_au_1": "1.19", + "q_au_2": "4.88" + }, + { + "designation": "(2010 LL68)", + "discovery_date": "2010-06-12T00:00:00.000Z", + "h_mag": "22.9", + "i_deg": "10.48", + "moid_au": "0.139", + "orbit_class": "Apollo", + "period_yr": "2.99", + "pha": "N", + "q_au_1": "0.98", + "q_au_2": "3.16" + }, + { + "designation": "(2010 LK68)", + "discovery_date": "2010-06-12T00:00:00.000Z", + "h_mag": "22.5", + "i_deg": "22.08", + "moid_au": "0.025", + "orbit_class": "Apollo", + "period_yr": "1.27", + "pha": "N", + "q_au_1": "0.61", + "q_au_2": "1.73" + }, + { + "designation": "(2010 LJ68)", + "discovery_date": "2010-06-11T00:00:00.000Z", + "h_mag": "22.7", + "i_deg": "17.01", + "moid_au": "0.031", + "orbit_class": "Apollo", + "period_yr": "2.32", + "pha": "N", + "q_au_1": "0.97", + "q_au_2": "2.54" + }, + { + "designation": "(2010 LG64)", + "discovery_date": "2010-06-05T00:00:00.000Z", + "h_mag": "20.2", + "i_deg": "42.28", + "moid_au": "0.043", + "orbit_class": "Amor", + "period_yr": "4.36", + "pha": "Y", + "q_au_1": "1.04", + "q_au_2": "4.3" + }, + { + "designation": "(2010 LF64)", + "discovery_date": "2010-06-03T00:00:00.000Z", + "h_mag": "21.6", + "i_deg": "18.54", + "moid_au": "0.192", + "orbit_class": "Amor", + "period_yr": "1.59", + "pha": "N", + "q_au_1": "1.13", + "q_au_2": "1.59" + }, + { + "designation": "(2010 LJ61)", + "discovery_date": "2010-06-08T00:00:00.000Z", + "h_mag": "20.9", + "i_deg": "10.24", + "moid_au": "0.054", + "orbit_class": "Apollo", + "period_yr": "1.12", + "pha": "N", + "q_au_1": "0.57", + "q_au_2": "1.59" + }, + { + "designation": "(2010 LQ33)", + "discovery_date": "2010-06-04T00:00:00.000Z", + "h_mag": "19.3", + "i_deg": "24.63", + "moid_au": "0.228", + "orbit_class": "Amor", + "period_yr": "3.42", + "pha": "N", + "q_au_1": "1.23", + "q_au_2": "3.31" + }, + { + "designation": "(2010 LM14)", + "discovery_date": "2010-06-02T00:00:00.000Z", + "h_mag": "21.5", + "i_deg": "25.92", + "moid_au": "0.312", + "orbit_class": "Apollo", + "period_yr": "1.17", + "pha": "N", + "q_au_1": "0.69", + "q_au_2": "1.53" + }, + { + "designation": "(2010 LH14)", + "discovery_date": "2010-06-02T00:00:00.000Z", + "h_mag": "22", + "i_deg": "4.66", + "moid_au": "0.054", + "orbit_class": "Apollo", + "period_yr": "3.26", + "pha": "N", + "q_au_1": "0.93", + "q_au_2": "3.46" + }, + { + "designation": "C/2010 L5 (WISE)", + "discovery_date": "2010-06-14T00:00:00.000Z", + "i_deg": "147.05", + "moid_au": "0.114", + "orbit_class": "Halley-type Comet*", + "period_yr": "23.56", + "pha": "n/a", + "q_au_1": "0.79", + "q_au_2": "15.64" + }, + { + "designation": "C/2010 L4 (WISE)", + "discovery_date": "2010-06-15T00:00:00.000Z", + "i_deg": "102.82", + "moid_au": "2.53", + "orbit_class": "Comet", + "period_yr": "716.78", + "pha": "n/a", + "q_au_1": "2.83", + "q_au_2": "157.36" + }, + { + "designation": "245P/WISE", + "discovery_date": "2010-06-02T00:00:00.000Z", + "i_deg": "21.09", + "moid_au": "1.172", + "orbit_class": "Jupiter-family Comet", + "period_yr": "8.04", + "pha": "n/a", + "q_au_1": "2.14", + "q_au_2": "5.88" + }, + { + "designation": "(2010 KY127)", + "discovery_date": "2010-05-31T00:00:00.000Z", + "h_mag": "17", + "i_deg": "60.29", + "moid_au": "0.703", + "orbit_class": "Apollo", + "period_yr": "3.95", + "pha": "N", + "q_au_1": "0.3", + "q_au_2": "4.7" + }, + { + "designation": "(2010 KK127)", + "discovery_date": "2010-05-21T00:00:00.000Z", + "h_mag": "20.7", + "i_deg": "6.94", + "moid_au": "0.282", + "orbit_class": "Amor", + "period_yr": "3.33", + "pha": "N", + "q_au_1": "1.28", + "q_au_2": "3.18" + }, + { + "designation": "(2010 KZ117)", + "discovery_date": "2010-05-18T00:00:00.000Z", + "h_mag": "19.2", + "i_deg": "33.17", + "moid_au": "0.166", + "orbit_class": "Amor", + "period_yr": "3.42", + "pha": "N", + "q_au_1": "1.1", + "q_au_2": "3.43" + }, + { + "designation": "(2010 KB61)", + "discovery_date": "2010-05-26T00:00:00.000Z", + "h_mag": "20.5", + "i_deg": "44.6", + "moid_au": "0.051", + "orbit_class": "Apollo", + "period_yr": "1.44", + "pha": "N", + "q_au_1": "0.98", + "q_au_2": "1.57" + }, + { + "designation": "(2010 KY39)", + "discovery_date": "2010-05-18T00:00:00.000Z", + "h_mag": "20.1", + "i_deg": "25.51", + "moid_au": "0.303", + "orbit_class": "Amor", + "period_yr": "2.3", + "pha": "N", + "q_au_1": "1.05", + "q_au_2": "2.43" + }, + { + "designation": "C/2010 KW7 (WISE)", + "discovery_date": "2010-05-16T00:00:00.000Z", + "i_deg": "147.06", + "moid_au": "1.625", + "orbit_class": "Comet", + "period_yr": "997.65", + "pha": "n/a", + "q_au_1": "2.57", + "q_au_2": "197.11" + }, + { + "designation": "317P/WISE", + "discovery_date": "2010-05-27T00:00:00.000Z", + "i_deg": "10.65", + "moid_au": "0.204", + "orbit_class": "Jupiter-family Comet", + "period_yr": "5.01", + "pha": "n/a", + "q_au_1": "1.2", + "q_au_2": "4.65" + }, + { + "designation": "(2010 KH)", + "discovery_date": "2010-05-16T00:00:00.000Z", + "h_mag": "19.4", + "i_deg": "14.57", + "moid_au": "0.367", + "orbit_class": "Amor", + "period_yr": "4.59", + "pha": "N", + "q_au_1": "1.24", + "q_au_2": "4.28" + }, + { + "designation": "(2010 JM151)", + "discovery_date": "2010-05-14T00:00:00.000Z", + "h_mag": "19.6", + "i_deg": "16.65", + "moid_au": "0.111", + "orbit_class": "Apollo", + "period_yr": "2.21", + "pha": "N", + "q_au_1": "0.88", + "q_au_2": "2.52" + }, + { + "designation": "(2010 JH87)", + "discovery_date": "2010-05-11T00:00:00.000Z", + "h_mag": "19.6", + "i_deg": "43.78", + "moid_au": "0.221", + "orbit_class": "Apollo", + "period_yr": "1.91", + "pha": "N", + "q_au_1": "0.71", + "q_au_2": "2.37" + }, + { + "designation": "(2010 JG87)", + "discovery_date": "2010-05-11T00:00:00.000Z", + "h_mag": "19.1", + "i_deg": "16.91", + "moid_au": "0.209", + "orbit_class": "Apollo", + "period_yr": "4.59", + "pha": "N", + "q_au_1": "0.14", + "q_au_2": "5.38" + }, + { + "designation": "(2010 JF87)", + "discovery_date": "2010-05-11T00:00:00.000Z", + "h_mag": "19.2", + "i_deg": "24.93", + "moid_au": "0.053", + "orbit_class": "Apollo", + "period_yr": "3.8", + "pha": "N", + "q_au_1": "0.92", + "q_au_2": "3.95" + }, + { + "designation": "(2010 JE87)", + "discovery_date": "2010-05-10T00:00:00.000Z", + "h_mag": "20.8", + "i_deg": "16.92", + "moid_au": "0.035", + "orbit_class": "Aten", + "period_yr": "0.86", + "pha": "Y", + "q_au_1": "0.51", + "q_au_2": "1.3" + }, + { + "designation": "(2010 JD87)", + "discovery_date": "2010-05-07T00:00:00.000Z", + "h_mag": "19.2", + "i_deg": "24.6", + "moid_au": "0.283", + "orbit_class": "Apollo", + "period_yr": "1.71", + "pha": "N", + "q_au_1": "0.51", + "q_au_2": "2.34" + }, + { + "designation": "P/2010 JC81 (WISE)", + "discovery_date": "2010-05-10T00:00:00.000Z", + "i_deg": "38.69", + "moid_au": "0.828", + "orbit_class": "Halley-type Comet*", + "period_yr": "23.19", + "pha": "n/a", + "q_au_1": "1.81", + "q_au_2": "14.46" + }, + { + "designation": "(2010 JA43)", + "discovery_date": "2010-05-04T00:00:00.000Z", + "h_mag": "20.9", + "i_deg": "36.46", + "moid_au": "0.186", + "orbit_class": "Amor", + "period_yr": "2.23", + "pha": "N", + "q_au_1": "1.03", + "q_au_2": "2.38" + }, + { + "designation": "(2010 JN33)", + "discovery_date": "2010-05-03T00:00:00.000Z", + "h_mag": "20.4", + "i_deg": "53.15", + "moid_au": "0.257", + "orbit_class": "Amor", + "period_yr": "1.94", + "pha": "N", + "q_au_1": "1.11", + "q_au_2": "2" + }, + { + "designation": "C/2010 J4 (WISE)", + "discovery_date": "2010-05-12T00:00:00.000Z", + "i_deg": "162.3", + "moid_au": "0.307", + "orbit_class": "Parabolic Comet", + "pha": "n/a", + "q_au_1": "1.09" + }, + { + "designation": "(2010 HZ108)", + "discovery_date": "2010-04-25T00:00:00.000Z", + "h_mag": "20.9", + "i_deg": "22.88", + "moid_au": "0.108", + "orbit_class": "Apollo", + "period_yr": "1.39", + "pha": "N", + "q_au_1": "0.99", + "q_au_2": "1.51" + }, + { + "designation": "(2010 HX107)", + "discovery_date": "2010-04-20T00:00:00.000Z", + "h_mag": "23.6", + "i_deg": "3.36", + "moid_au": "0.014", + "orbit_class": "Aten", + "period_yr": "0.72", + "pha": "N", + "q_au_1": "0.56", + "q_au_2": "1.04" + }, + { + "designation": "(2010 HZ104)", + "discovery_date": "2010-04-23T00:00:00.000Z", + "h_mag": "22.5", + "i_deg": "20.24", + "moid_au": "0.029", + "orbit_class": "Apollo", + "period_yr": "3.37", + "pha": "N", + "q_au_1": "0.97", + "q_au_2": "3.52" + }, + { + "designation": "(2010 HW81)", + "discovery_date": "2010-04-25T00:00:00.000Z", + "h_mag": "21.4", + "i_deg": "12.77", + "moid_au": "0.117", + "orbit_class": "Apollo", + "period_yr": "1.33", + "pha": "N", + "q_au_1": "0.33", + "q_au_2": "2.1" + }, + { + "designation": "(2010 HD33)", + "discovery_date": "2010-04-20T00:00:00.000Z", + "h_mag": "18.3", + "i_deg": "24.43", + "moid_au": "0.372", + "orbit_class": "Amor", + "period_yr": "4.24", + "pha": "N", + "q_au_1": "1.27", + "q_au_2": "3.97" + }, + { + "designation": "(2010 GV147)", + "discovery_date": "2010-04-14T00:00:00.000Z", + "h_mag": "18.5", + "i_deg": "44.05", + "moid_au": "0.316", + "orbit_class": "Aten", + "period_yr": "0.94", + "pha": "N", + "q_au_1": "0.33", + "q_au_2": "1.59" + }, + { + "designation": "(2010 GR75)", + "discovery_date": "2010-04-13T00:00:00.000Z", + "h_mag": "19.6", + "i_deg": "17.78", + "moid_au": "0.299", + "orbit_class": "Apollo", + "period_yr": "2.27", + "pha": "N", + "q_au_1": "0.63", + "q_au_2": "2.82" + }, + { + "designation": "(2010 GQ75)", + "discovery_date": "2010-04-12T00:00:00.000Z", + "h_mag": "20.2", + "i_deg": "43.23", + "moid_au": "0.598", + "orbit_class": "Apollo", + "period_yr": "3.79", + "pha": "N", + "q_au_1": "0.33", + "q_au_2": "4.53" + }, + { + "designation": "(2010 GP67)", + "discovery_date": "2010-04-11T00:00:00.000Z", + "h_mag": "22.3", + "i_deg": "13.27", + "moid_au": "0.018", + "orbit_class": "Apollo", + "period_yr": "1.18", + "pha": "N", + "q_au_1": "0.99", + "q_au_2": "1.23" + }, + { + "designation": "(2010 GH65)", + "discovery_date": "2010-04-10T00:00:00.000Z", + "h_mag": "18.8", + "i_deg": "21.04", + "moid_au": "0.15", + "orbit_class": "Amor", + "period_yr": "4.45", + "pha": "N", + "q_au_1": "1.05", + "q_au_2": "4.36" + }, + { + "designation": "(2010 GX62)", + "discovery_date": "2010-04-10T00:00:00.000Z", + "h_mag": "20", + "i_deg": "21.66", + "moid_au": "0.013", + "orbit_class": "Apollo", + "period_yr": "5.07", + "pha": "Y", + "q_au_1": "0.87", + "q_au_2": "5.03" + }, + { + "designation": "(2010 GW62)", + "discovery_date": "2010-04-09T00:00:00.000Z", + "h_mag": "19.4", + "i_deg": "32.43", + "moid_au": "0.44", + "orbit_class": "Apollo", + "period_yr": "1.43", + "pha": "N", + "q_au_1": "0.54", + "q_au_2": "2" + }, + { + "designation": "(2010 GF25)", + "discovery_date": "2010-04-02T00:00:00.000Z", + "h_mag": "19.1", + "i_deg": "38.49", + "moid_au": "0.399", + "orbit_class": "Apollo", + "period_yr": "1.7", + "pha": "N", + "q_au_1": "0.37", + "q_au_2": "2.47" + }, + { + "designation": "(2010 GE25)", + "discovery_date": "2010-04-01T00:00:00.000Z", + "h_mag": "20", + "i_deg": "21.66", + "moid_au": "0.22", + "orbit_class": "Amor", + "period_yr": "2.97", + "pha": "N", + "q_au_1": "1.1", + "q_au_2": "3.03" + }, + { + "designation": "(2010 GK23)", + "discovery_date": "2010-04-05T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "34.77", + "moid_au": "0.097", + "orbit_class": "Apollo", + "period_yr": "4.32", + "pha": "N", + "q_au_1": "0.87", + "q_au_2": "4.43" + }, + { + "designation": "C/2010 G3 (WISE)", + "discovery_date": "2010-04-14T00:00:00.000Z", + "i_deg": "108.27", + "moid_au": "4.492", + "orbit_class": "Comet", + "period_yr": "135070.2", + "pha": "n/a", + "q_au_1": "4.91", + "q_au_2": "5260.08" + }, + { + "designation": "C/2010 FB87 (WISE-Garradd)", + "discovery_date": "2010-03-28T00:00:00.000Z", + "i_deg": "107.63", + "moid_au": "2.538", + "orbit_class": "Comet", + "period_yr": "5176.82", + "pha": "n/a", + "q_au_1": "2.84", + "q_au_2": "595.66" + }, + { + "designation": "(2010 FJ81)", + "discovery_date": "2010-03-31T00:00:00.000Z", + "h_mag": "20.8", + "i_deg": "42.54", + "moid_au": "0.128", + "orbit_class": "Amor", + "period_yr": "6.82", + "pha": "N", + "q_au_1": "1.14", + "q_au_2": "6.06" + }, + { + "designation": "(2010 FH81)", + "discovery_date": "2010-03-31T00:00:00.000Z", + "h_mag": "21.6", + "i_deg": "16.79", + "moid_au": "0.034", + "orbit_class": "Apollo", + "period_yr": "1.36", + "pha": "Y", + "q_au_1": "0.97", + "q_au_2": "1.48" + }, + { + "designation": "(2010 FG81)", + "discovery_date": "2010-03-26T00:00:00.000Z", + "h_mag": "23.3", + "i_deg": "7.97", + "moid_au": "0.019", + "orbit_class": "Apollo", + "period_yr": "2.14", + "pha": "N", + "q_au_1": "1.01", + "q_au_2": "2.31" + }, + { + "designation": "(2010 FC81)", + "discovery_date": "2010-03-30T00:00:00.000Z", + "h_mag": "21.8", + "i_deg": "1.68", + "moid_au": "0.027", + "orbit_class": "Apollo", + "period_yr": "4.38", + "pha": "Y", + "q_au_1": "1.01", + "q_au_2": "4.35" + }, + { + "designation": "(2010 FB81)", + "discovery_date": "2010-03-30T00:00:00.000Z", + "h_mag": "21.4", + "i_deg": "9.48", + "moid_au": "0.096", + "orbit_class": "Amor", + "period_yr": "4.14", + "pha": "N", + "q_au_1": "1.02", + "q_au_2": "4.14" + }, + { + "designation": "(2010 FA81)", + "discovery_date": "2010-03-29T00:00:00.000Z", + "h_mag": "22.3", + "i_deg": "15.48", + "moid_au": "0.035", + "orbit_class": "Apollo", + "period_yr": "1.31", + "pha": "N", + "q_au_1": "1.01", + "q_au_2": "1.38" + }, + { + "designation": "(2010 FZ80)", + "discovery_date": "2010-03-28T00:00:00.000Z", + "h_mag": "20.3", + "i_deg": "27.34", + "moid_au": "0.297", + "orbit_class": "Apollo", + "period_yr": "4.56", + "pha": "N", + "q_au_1": "0.7", + "q_au_2": "4.8" + }, + { + "designation": "(2010 FY80)", + "discovery_date": "2010-03-28T00:00:00.000Z", + "h_mag": "19.7", + "i_deg": "18.81", + "moid_au": "0.14", + "orbit_class": "Amor", + "period_yr": "4.42", + "pha": "N", + "q_au_1": "1.05", + "q_au_2": "4.35" + }, + { + "designation": "(2010 FX80)", + "discovery_date": "2010-03-27T00:00:00.000Z", + "h_mag": "20.6", + "i_deg": "36.96", + "moid_au": "0.535", + "orbit_class": "Amor", + "period_yr": "3.19", + "pha": "N", + "q_au_1": "1.18", + "q_au_2": "3.15" + }, + { + "designation": "(2010 EX119)", + "discovery_date": "2010-03-13T00:00:00.000Z", + "h_mag": "19.4", + "i_deg": "15.57", + "moid_au": "0.159", + "orbit_class": "Apollo", + "period_yr": "2.63", + "pha": "N", + "q_au_1": "0.77", + "q_au_2": "3.04" + }, + { + "designation": "(2010 EN44)", + "discovery_date": "2010-03-12T00:00:00.000Z", + "h_mag": "24.3", + "i_deg": "10.18", + "moid_au": "0.023", + "orbit_class": "Apollo", + "period_yr": "1.22", + "pha": "N", + "q_au_1": "0.96", + "q_au_2": "1.33" + }, + { + "designation": "(2010 EX11)", + "discovery_date": "2010-03-03T00:00:00.000Z", + "h_mag": "24.1", + "i_deg": "9.75", + "moid_au": "0.029", + "orbit_class": "Aten", + "period_yr": "0.93", + "pha": "N", + "q_au_1": "0.85", + "q_au_2": "1.06" + }, + { + "designation": "C/2010 E3 (WISE)", + "discovery_date": "2010-03-05T00:00:00.000Z", + "i_deg": "96.48", + "moid_au": "1.546", + "orbit_class": "Parabolic Comet", + "pha": "n/a", + "q_au_1": "2.27" + }, + { + "designation": "(2010 DJ77)", + "discovery_date": "2010-02-20T00:00:00.000Z", + "h_mag": "21.6", + "i_deg": "24.98", + "moid_au": "0.05", + "orbit_class": "Aten", + "period_yr": "0.93", + "pha": "Y", + "q_au_1": "0.75", + "q_au_2": "1.16" + }, + { + "designation": "(2010 DH77)", + "discovery_date": "2010-02-19T00:00:00.000Z", + "h_mag": "21.8", + "i_deg": "34.38", + "moid_au": "0.146", + "orbit_class": "Apollo", + "period_yr": "5.9", + "pha": "N", + "q_au_1": "0.95", + "q_au_2": "5.58" + }, + { + "designation": "(2010 DG77)", + "discovery_date": "2010-02-19T00:00:00.000Z", + "h_mag": "21.4", + "i_deg": "14.81", + "moid_au": "0.009", + "orbit_class": "Apollo", + "period_yr": "3.02", + "pha": "Y", + "q_au_1": "0.96", + "q_au_2": "3.22" + }, + { + "designation": "(2010 DM56)", + "discovery_date": "2010-02-19T00:00:00.000Z", + "h_mag": "19.9", + "i_deg": "25.61", + "moid_au": "0.006", + "orbit_class": "Apollo", + "period_yr": "1.49", + "pha": "Y", + "q_au_1": "0.92", + "q_au_2": "1.69" + }, + { + "designation": "(2010 DJ56)", + "discovery_date": "2010-02-23T00:00:00.000Z", + "h_mag": "19.3", + "i_deg": "34.84", + "moid_au": "0.028", + "orbit_class": "Apollo", + "period_yr": "1.4", + "pha": "Y", + "q_au_1": "0.94", + "q_au_2": "1.56" + }, + { + "designation": "(2010 DH56)", + "discovery_date": "2010-02-20T00:00:00.000Z", + "h_mag": "20.3", + "i_deg": "33.67", + "moid_au": "0.333", + "orbit_class": "Apollo", + "period_yr": "3.35", + "pha": "N", + "q_au_1": "0.97", + "q_au_2": "3.51" + }, + { + "designation": "C/2010 DG56 (WISE)", + "discovery_date": "2010-02-18T00:00:00.000Z", + "i_deg": "160.42", + "moid_au": "0.65", + "orbit_class": "Comet", + "period_yr": "555.03", + "pha": "n/a", + "q_au_1": "1.59", + "q_au_2": "133.48" + }, + { + "designation": "(2010 DK34)", + "discovery_date": "2010-02-20T00:00:00.000Z", + "h_mag": "20.4", + "i_deg": "27.34", + "moid_au": "0.333", + "orbit_class": "Apollo", + "period_yr": "4.54", + "pha": "N", + "q_au_1": "0.65", + "q_au_2": "4.83" + }, + { + "designation": "(2010 DM21)", + "discovery_date": "2010-02-16T00:00:00.000Z", + "h_mag": "20.2", + "i_deg": "21.15", + "moid_au": "0.26", + "orbit_class": "Apollo", + "period_yr": "4.85", + "pha": "N", + "q_au_1": "0.98", + "q_au_2": "4.74" + }, + { + "designation": "C/2010 D4 (WISE)", + "discovery_date": "2010-02-28T00:00:00.000Z", + "i_deg": "105.66", + "moid_au": "6.373", + "orbit_class": "Comet", + "period_yr": "520.06", + "pha": "n/a", + "q_au_1": "7.15", + "q_au_2": "122.19" + }, + { + "designation": "C/2010 D3 (WISE)", + "discovery_date": "2010-02-26T00:00:00.000Z", + "i_deg": "76.39", + "moid_au": "3.586", + "orbit_class": "Comet", + "period_yr": "1254179.62", + "pha": "n/a", + "q_au_1": "4.25", + "q_au_2": "23255.11" + }, + { + "designation": "P/2010 D2 (WISE)", + "discovery_date": "2010-02-25T00:00:00.000Z", + "i_deg": "57.18", + "moid_au": "2.945", + "orbit_class": "Jupiter-family Comet*", + "period_yr": "17.3", + "pha": "n/a", + "q_au_1": "3.66", + "q_au_2": "9.72" + }, + { + "designation": "P/2010 D1 (WISE)", + "discovery_date": "2010-02-17T00:00:00.000Z", + "i_deg": "9.65", + "moid_au": "1.683", + "orbit_class": "Jupiter-family Comet", + "period_yr": "8.45", + "pha": "n/a", + "q_au_1": "2.67", + "q_au_2": "5.63" + }, + { + "designation": "(2010 CN141)", + "discovery_date": "2010-02-14T00:00:00.000Z", + "h_mag": "22.4", + "i_deg": "23.8", + "moid_au": "0.06", + "orbit_class": "Apollo", + "period_yr": "1.87", + "pha": "N", + "q_au_1": "0.91", + "q_au_2": "2.12" + }, + { + "designation": "(2010 CP140)", + "discovery_date": "2010-02-13T00:00:00.000Z", + "h_mag": "19.5", + "i_deg": "14.47", + "moid_au": "0.097", + "orbit_class": "Apollo", + "period_yr": "2.62", + "pha": "N", + "q_au_1": "0.88", + "q_au_2": "2.92" + }, + { + "designation": "(2010 CC55)", + "discovery_date": "2010-02-11T00:00:00.000Z", + "h_mag": "22.5", + "i_deg": "6.78", + "moid_au": "0.079", + "orbit_class": "Apollo", + "period_yr": "1.92", + "pha": "N", + "q_au_1": "0.82", + "q_au_2": "2.27" + }, + { + "designation": "(2010 CA55)", + "discovery_date": "2010-02-05T00:00:00.000Z", + "h_mag": "21.3", + "i_deg": "58.85", + "moid_au": "0.151", + "orbit_class": "Apollo", + "period_yr": "12.13", + "pha": "N", + "q_au_1": "0.67", + "q_au_2": "9.89" + }, + { + "designation": "(2010 CH18)", + "discovery_date": "2010-02-09T00:00:00.000Z", + "h_mag": "19", + "i_deg": "27.15", + "moid_au": "0.333", + "orbit_class": "Amor", + "period_yr": "4.21", + "pha": "N", + "q_au_1": "1.12", + "q_au_2": "4.09" + }, + { + "designation": "(2010 CG18)", + "discovery_date": "2010-02-06T00:00:00.000Z", + "h_mag": "20.8", + "i_deg": "10.15", + "moid_au": "0.13", + "orbit_class": "Amor", + "period_yr": "1.73", + "pha": "N", + "q_au_1": "1.11", + "q_au_2": "1.76" + }, + { + "designation": "(2010 CO1)", + "discovery_date": "2010-02-01T00:00:00.000Z", + "h_mag": "21.5", + "i_deg": "24.03", + "moid_au": "0.023", + "orbit_class": "Apollo", + "period_yr": "1.02", + "pha": "Y", + "q_au_1": "0.79", + "q_au_2": "1.23" + }, + { + "designation": "P/2010 B2 (WISE)", + "discovery_date": "2010-01-22T00:00:00.000Z", + "i_deg": "8.93", + "moid_au": "0.63", + "orbit_class": "Encke-type Comet", + "period_yr": "5.49", + "pha": "n/a", + "q_au_1": "1.62", + "q_au_2": "4.6" + }, + { + "designation": "(2010 AU118)", + "discovery_date": "2010-01-13T00:00:00.000Z", + "h_mag": "17.7", + "i_deg": "43.73", + "moid_au": "0.147", + "orbit_class": "Amor", + "period_yr": "2.06", + "pha": "N", + "q_au_1": "1.13", + "q_au_2": "2.12" + }, + { + "designation": "(2010 AG79)", + "discovery_date": "2010-01-13T00:00:00.000Z", + "h_mag": "19.9", + "i_deg": "32.96", + "moid_au": "0.244", + "orbit_class": "Amor", + "period_yr": "4.95", + "pha": "N", + "q_au_1": "1.22", + "q_au_2": "4.59" + }, + { + "designation": "(2010 AB78)", + "discovery_date": "2010-01-12T00:00:00.000Z", + "h_mag": "18.3", + "i_deg": "33.26", + "moid_au": "0.206", + "orbit_class": "Amor", + "period_yr": "3.38", + "pha": "N", + "q_au_1": "1.02", + "q_au_2": "3.49" + } +] diff --git a/test/inputs/json/misc/80aff.json b/test/inputs/json/misc/80aff.json index e4d7219fe..b7a284651 100644 --- a/test/inputs/json/misc/80aff.json +++ b/test/inputs/json/misc/80aff.json @@ -1 +1,235 @@ -{"count": 25, "facets": {}, "results": [{"name": "Other public or mixed entities, created by law whose purpose is to act in the public interest", "parent": 6, "items": 264, "created_at": "2015-06-20T23:47:50.629565", "updated_at": "2015-06-20T23:47:50.629571", "uri": "http://api.lobbyfacts.eu/api/1/category/66", "id": 66}, {"name": "Transnational associations and networks of public regional or other sub-national authorities", "parent": 6, "items": 86, "created_at": "2015-06-20T23:52:01.435197", "updated_at": "2015-06-20T23:52:01.435209", "uri": "http://api.lobbyfacts.eu/api/1/category/65", "id": 65}, {"name": "Other sub-national public authorities", "parent": 6, "items": 131, "created_at": "2015-06-20T23:45:21.341529", "updated_at": "2015-06-20T23:45:21.341540", "uri": "http://api.lobbyfacts.eu/api/1/category/64", "id": 64}, {"name": "Regional structures", "parent": 6, "items": 139, "created_at": "2015-06-20T23:46:06.687738", "updated_at": "2015-06-20T23:46:06.687750", "uri": "http://api.lobbyfacts.eu/api/1/category/63", "id": 63}, {"name": "Other public or mixed entities, etc.", "parent": 6, "items": 1, "created_at": "2015-04-24T01:48:38.622659", "updated_at": "2015-06-08T21:59:49.003576", "uri": "http://api.lobbyfacts.eu/api/1/category/62", "id": 62}, {"name": "Local, regional and municipal authorities (at sub-national level)", "parent": 6, "items": 2, "created_at": "2015-04-24T01:46:58.298572", "updated_at": "2015-06-08T21:48:45.111744", "uri": "http://api.lobbyfacts.eu/api/1/category/61", "id": 61}, {"name": "Organisations representing churches and religious communities", "parent": 5, "items": 62, "created_at": "2015-04-24T01:53:24.257993", "updated_at": "2015-04-24T01:53:24.258004", "uri": "http://api.lobbyfacts.eu/api/1/category/51", "id": 51}, {"name": "Academic institutions", "parent": 4, "items": 315, "created_at": "2015-04-24T01:49:12.530337", "updated_at": "2015-04-24T01:49:12.530348", "uri": "http://api.lobbyfacts.eu/api/1/category/42", "id": 42}, {"name": "Think tanks and research institutions", "parent": 4, "items": 606, "created_at": "2015-04-24T01:47:16.228011", "updated_at": "2015-04-24T01:47:16.228017", "uri": "http://api.lobbyfacts.eu/api/1/category/41", "id": 41}, {"name": "Non-governmental organisations, platforms and networks and similar", "parent": 3, "items": 3120, "created_at": "2015-04-24T01:46:51.539328", "updated_at": "2015-04-24T01:46:51.539333", "uri": "http://api.lobbyfacts.eu/api/1/category/31", "id": 31}, {"name": "Other in house lobbyists", "parent": 2, "items": 368, "created_at": "2015-06-20T23:45:13.999259", "updated_at": "2015-06-20T23:45:13.999266", "uri": "http://api.lobbyfacts.eu/api/1/category/27", "id": 27}, {"name": "Trade unions and professional associations", "parent": 2, "items": 783, "created_at": "2015-06-20T23:45:15.961411", "updated_at": "2015-06-20T23:45:15.961422", "uri": "http://api.lobbyfacts.eu/api/1/category/26", "id": 26}, {"name": "Trade and business organisations", "parent": 2, "items": 2477, "created_at": "2015-06-20T23:45:10.255417", "updated_at": "2015-06-20T23:45:10.255424", "uri": "http://api.lobbyfacts.eu/api/1/category/25", "id": 25}, {"name": "Other similar organisations", "parent": 2, "items": 2, "created_at": "2015-04-24T01:46:54.547344", "updated_at": "2015-06-08T21:59:29.739023", "uri": "http://api.lobbyfacts.eu/api/1/category/24", "id": 24}, {"name": "Trade, business & professional associations", "parent": 2, "items": 2, "created_at": "2015-04-24T01:46:52.124504", "updated_at": "2015-06-08T22:00:51.075491", "uri": "http://api.lobbyfacts.eu/api/1/category/22", "id": 22}, {"name": "Companies & groups", "parent": 2, "items": 2166, "created_at": "2015-04-24T01:46:51.879074", "updated_at": "2015-04-24T01:46:51.879079", "uri": "http://api.lobbyfacts.eu/api/1/category/21", "id": 21}, {"name": "Self-employed consultants", "parent": 1, "items": 483, "created_at": "2015-04-24T01:46:56.610098", "updated_at": "2015-04-24T01:46:56.610103", "uri": "http://api.lobbyfacts.eu/api/1/category/13", "id": 13}, {"name": "Law firms", "parent": 1, "items": 163, "created_at": "2015-04-24T01:47:16.905163", "updated_at": "2015-04-24T01:47:16.905173", "uri": "http://api.lobbyfacts.eu/api/1/category/12", "id": 12}, {"name": "Professional consultancies", "parent": 1, "items": 852, "created_at": "2015-04-24T01:46:54.278376", "updated_at": "2015-04-24T01:46:54.278380", "uri": "http://api.lobbyfacts.eu/api/1/category/11", "id": 11}, {"name": "VI - Organisations representing local, regional and municipal authorities, other public or mixed entities, etc.", "parent": null, "items": 623, "created_at": "2015-04-24T01:46:58.289906", "updated_at": "2015-04-24T01:46:58.289912", "uri": "http://api.lobbyfacts.eu/api/1/category/6", "id": 6}, {"name": "V - Organisations representing churches and religious communities", "parent": null, "items": 62, "created_at": "2015-04-24T01:53:24.174057", "updated_at": "2015-04-24T01:53:24.174068", "uri": "http://api.lobbyfacts.eu/api/1/category/5", "id": 5}, {"name": "IV - Think tanks, research and academic institutions", "parent": null, "items": 921, "created_at": "2015-04-24T01:47:16.221072", "updated_at": "2015-04-24T01:47:16.221083", "uri": "http://api.lobbyfacts.eu/api/1/category/4", "id": 4}, {"name": "III - Non-governmental organisations", "parent": null, "items": 3120, "created_at": "2015-04-24T01:46:51.534790", "updated_at": "2015-04-24T01:46:51.534797", "uri": "http://api.lobbyfacts.eu/api/1/category/3", "id": 3}, {"name": "II - In-house lobbyists and trade/professional associations", "parent": null, "items": 5799, "created_at": "2015-04-24T01:46:51.875300", "updated_at": "2015-06-08T22:00:51.062663", "uri": "http://api.lobbyfacts.eu/api/1/category/2", "id": 2}, {"name": "I - Professional consultancies/law firms/self-employed consultants", "parent": null, "items": 1498, "created_at": "2015-04-24T01:46:54.274270", "updated_at": "2015-04-24T01:46:54.274275", "uri": "http://api.lobbyfacts.eu/api/1/category/1", "id": 1}], "next": false, "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 25, + "facets": {}, + "results": [ + { + "name": "Other public or mixed entities, created by law whose purpose is to act in the public interest", + "parent": 6, + "items": 264, + "created_at": "2015-06-20T23:47:50.629565Z", + "updated_at": "2015-06-20T23:47:50.629571Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/66", + "id": 66 + }, + { + "name": "Transnational associations and networks of public regional or other sub-national authorities", + "parent": 6, + "items": 86, + "created_at": "2015-06-20T23:52:01.435197Z", + "updated_at": "2015-06-20T23:52:01.435209Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/65", + "id": 65 + }, + { + "name": "Other sub-national public authorities", + "parent": 6, + "items": 131, + "created_at": "2015-06-20T23:45:21.341529Z", + "updated_at": "2015-06-20T23:45:21.341540Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/64", + "id": 64 + }, + { + "name": "Regional structures", + "parent": 6, + "items": 139, + "created_at": "2015-06-20T23:46:06.687738Z", + "updated_at": "2015-06-20T23:46:06.687750Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/63", + "id": 63 + }, + { + "name": "Other public or mixed entities, etc.", + "parent": 6, + "items": 1, + "created_at": "2015-04-24T01:48:38.622659Z", + "updated_at": "2015-06-08T21:59:49.003576Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/62", + "id": 62 + }, + { + "name": "Local, regional and municipal authorities (at sub-national level)", + "parent": 6, + "items": 2, + "created_at": "2015-04-24T01:46:58.298572Z", + "updated_at": "2015-06-08T21:48:45.111744Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/61", + "id": 61 + }, + { + "name": "Organisations representing churches and religious communities", + "parent": 5, + "items": 62, + "created_at": "2015-04-24T01:53:24.257993Z", + "updated_at": "2015-04-24T01:53:24.258004Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/51", + "id": 51 + }, + { + "name": "Academic institutions", + "parent": 4, + "items": 315, + "created_at": "2015-04-24T01:49:12.530337Z", + "updated_at": "2015-04-24T01:49:12.530348Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/42", + "id": 42 + }, + { + "name": "Think tanks and research institutions", + "parent": 4, + "items": 606, + "created_at": "2015-04-24T01:47:16.228011Z", + "updated_at": "2015-04-24T01:47:16.228017Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/41", + "id": 41 + }, + { + "name": "Non-governmental organisations, platforms and networks and similar", + "parent": 3, + "items": 3120, + "created_at": "2015-04-24T01:46:51.539328Z", + "updated_at": "2015-04-24T01:46:51.539333Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/31", + "id": 31 + }, + { + "name": "Other in house lobbyists", + "parent": 2, + "items": 368, + "created_at": "2015-06-20T23:45:13.999259Z", + "updated_at": "2015-06-20T23:45:13.999266Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/27", + "id": 27 + }, + { + "name": "Trade unions and professional associations", + "parent": 2, + "items": 783, + "created_at": "2015-06-20T23:45:15.961411Z", + "updated_at": "2015-06-20T23:45:15.961422Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/26", + "id": 26 + }, + { + "name": "Trade and business organisations", + "parent": 2, + "items": 2477, + "created_at": "2015-06-20T23:45:10.255417Z", + "updated_at": "2015-06-20T23:45:10.255424Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/25", + "id": 25 + }, + { + "name": "Other similar organisations", + "parent": 2, + "items": 2, + "created_at": "2015-04-24T01:46:54.547344Z", + "updated_at": "2015-06-08T21:59:29.739023Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/24", + "id": 24 + }, + { + "name": "Trade, business & professional associations", + "parent": 2, + "items": 2, + "created_at": "2015-04-24T01:46:52.124504Z", + "updated_at": "2015-06-08T22:00:51.075491Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/22", + "id": 22 + }, + { + "name": "Companies & groups", + "parent": 2, + "items": 2166, + "created_at": "2015-04-24T01:46:51.879074Z", + "updated_at": "2015-04-24T01:46:51.879079Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/21", + "id": 21 + }, + { + "name": "Self-employed consultants", + "parent": 1, + "items": 483, + "created_at": "2015-04-24T01:46:56.610098Z", + "updated_at": "2015-04-24T01:46:56.610103Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/13", + "id": 13 + }, + { + "name": "Law firms", + "parent": 1, + "items": 163, + "created_at": "2015-04-24T01:47:16.905163Z", + "updated_at": "2015-04-24T01:47:16.905173Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/12", + "id": 12 + }, + { + "name": "Professional consultancies", + "parent": 1, + "items": 852, + "created_at": "2015-04-24T01:46:54.278376Z", + "updated_at": "2015-04-24T01:46:54.278380Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/11", + "id": 11 + }, + { + "name": "VI - Organisations representing local, regional and municipal authorities, other public or mixed entities, etc.", + "parent": null, + "items": 623, + "created_at": "2015-04-24T01:46:58.289906Z", + "updated_at": "2015-04-24T01:46:58.289912Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/6", + "id": 6 + }, + { + "name": "V - Organisations representing churches and religious communities", + "parent": null, + "items": 62, + "created_at": "2015-04-24T01:53:24.174057Z", + "updated_at": "2015-04-24T01:53:24.174068Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/5", + "id": 5 + }, + { + "name": "IV - Think tanks, research and academic institutions", + "parent": null, + "items": 921, + "created_at": "2015-04-24T01:47:16.221072Z", + "updated_at": "2015-04-24T01:47:16.221083Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/4", + "id": 4 + }, + { + "name": "III - Non-governmental organisations", + "parent": null, + "items": 3120, + "created_at": "2015-04-24T01:46:51.534790Z", + "updated_at": "2015-04-24T01:46:51.534797Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/3", + "id": 3 + }, + { + "name": "II - In-house lobbyists and trade/professional associations", + "parent": null, + "items": 5799, + "created_at": "2015-04-24T01:46:51.875300Z", + "updated_at": "2015-06-08T22:00:51.062663Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/2", + "id": 2 + }, + { + "name": "I - Professional consultancies/law firms/self-employed consultants", + "parent": null, + "items": 1498, + "created_at": "2015-04-24T01:46:54.274270Z", + "updated_at": "2015-04-24T01:46:54.274275Z", + "uri": "http://api.lobbyfacts.eu/api/1/category/1", + "id": 1 + } + ], + "next": false, + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/misc/9ac3b.json b/test/inputs/json/misc/9ac3b.json index b135e8d2b..edb224684 100644 --- a/test/inputs/json/misc/9ac3b.json +++ b/test/inputs/json/misc/9ac3b.json @@ -1 +1,660 @@ -{"count": 36713, "facets": {}, "results": [{"status": "inactive", "first_name": "Lasse Hamilton", "last_name": "Heidemann", "name": "Lasse Hamilton Heidemann", "title": null, "created_at": "2015-12-05T00:52:13.534368", "uri": "http://api.lobbyfacts.eu/api/1/person/ffff1e3de5aa4db8ace7dcb080a4c2e0", "updated_at": "2016-02-04T01:11:29.396185", "entity": "ba0821d8786b4764b4e83d48a62f155e", "position": null, "id": "ffff1e3de5aa4db8ace7dcb080a4c2e0"}, {"status": "inactive", "first_name": "Peter H.P.", "last_name": "Sierat", "name": "Mr Peter H.P. Sierat", "title": "Mr", "created_at": "2015-04-24T01:49:19.714706", "uri": "http://api.lobbyfacts.eu/api/1/person/fffdcd840ce74712ab96125b3c8a29f2", "updated_at": "2016-04-02T00:00:39.433543", "entity": "cb57ae8983dc4ceaba72e7befd59b255", "position": "Algemeen directeur", "id": "fffdcd840ce74712ab96125b3c8a29f2"}, {"status": "inactive", "first_name": "Aleksandra", "last_name": "Kluczka", "name": "Ms Aleksandra Kluczka", "title": "Ms", "created_at": "2015-04-24T02:13:06.918194", "uri": "http://api.lobbyfacts.eu/api/1/person/fffd214acfab4df39770a3cb1cd2a16e", "updated_at": "2015-08-04T23:02:51.578546", "entity": "edc26b7e632146039f0cb3c673d9e5b5", "position": null, "id": "fffd214acfab4df39770a3cb1cd2a16e"}, {"status": "active", "first_name": "Nicholas", "last_name": "Cook", "name": "Mr Nicholas Cook", "title": "Mr", "created_at": "2016-04-28T01:46:54.088777", "uri": "http://api.lobbyfacts.eu/api/1/person/fffba075e7244af5beaf4cb4df492d0c", "updated_at": "2016-04-28T01:46:54.086259", "entity": "2bd41f5a042a4584afe2e2faf7f99d9b", "position": null, "id": "fffba075e7244af5beaf4cb4df492d0c"}, {"status": "active", "first_name": "LORIS", "last_name": "BORGHI", "name": " LORIS BORGHI", "title": null, "created_at": "2016-04-24T01:46:22.432444", "uri": "http://api.lobbyfacts.eu/api/1/person/fff6a7c563db4260833e4a0a5132e06d", "updated_at": "2016-04-24T01:46:22.430054", "entity": "9b890aa4ae8c41c2993408018216ffea", "position": "RETTORE", "id": "fff6a7c563db4260833e4a0a5132e06d"}, {"status": "active", "first_name": "Mary", "last_name": "Booth", "name": "Ms Mary Booth", "title": "Ms", "created_at": "2016-05-06T01:50:28.394132", "uri": "http://api.lobbyfacts.eu/api/1/person/fff42bf8b9bf4553a22a2e54dc060e7b", "updated_at": "2016-05-06T01:50:28.390872", "entity": "4a58ff1f55804c45961de16e03caf8f2", "position": "President", "id": "fff42bf8b9bf4553a22a2e54dc060e7b"}, {"status": "active", "first_name": "Zolt\u00e1n", "last_name": "Dub\u00e9czi ", "name": " Zolt\u00e1n Dub\u00e9czi ", "title": null, "created_at": "2015-04-24T02:33:55.473918", "uri": "http://api.lobbyfacts.eu/api/1/person/fff1ba1aeb93455a9d58d4e8d30106ef", "updated_at": "2015-06-09T00:33:29.597458", "entity": "1604b87b837849e494c502955d9890a6", "position": "f\u0151ttitk\u00e1r", "id": "fff1ba1aeb93455a9d58d4e8d30106ef"}, {"status": "active", "first_name": "Andreas", "last_name": "von Bonin", "name": "Mr Andreas von Bonin", "title": "Mr", "created_at": "2015-10-29T01:59:20.041336", "uri": "http://api.lobbyfacts.eu/api/1/person/fff0688a62b147ce8d4d9e41a8bdf88b", "updated_at": "2015-10-29T01:59:20.040060", "entity": "a944c83d1fe84cabaeff9b672d0d1234", "position": "Partner", "id": "fff0688a62b147ce8d4d9e41a8bdf88b"}, {"status": "active", "first_name": "Jeff", "last_name": "RUPP", "name": "Mr Jeff RUPP", "title": "Mr", "created_at": "2015-04-24T01:55:31.635859", "uri": "http://api.lobbyfacts.eu/api/1/person/ffeb9e9a626945be9b3b24430559d1c9", "updated_at": "2016-08-24T00:25:06.902891", "entity": "4135e9a4a93142eda69d7e9a5cd37c7a", "position": null, "id": "ffeb9e9a626945be9b3b24430559d1c9"}, {"status": "inactive", "first_name": "Marisa", "last_name": "PLOWDEN", "name": "Ms Marisa PLOWDEN", "title": "Ms", "created_at": "2015-08-04T23:38:47.343642", "uri": "http://api.lobbyfacts.eu/api/1/person/ffeb6dc0543a4bdd9c8a785878604da4", "updated_at": "2016-07-29T01:21:54.336544", "entity": "109aaeca90e641b5b0aa218489390222", "position": null, "id": "ffeb6dc0543a4bdd9c8a785878604da4"}, {"status": "active", "first_name": "GOKHAN", "last_name": "BACIK", "name": "Mr GOKHAN BACIK", "title": "Mr", "created_at": "2016-05-29T01:44:59.830189", "uri": "http://api.lobbyfacts.eu/api/1/person/ffe7118837644097bf3c7cf9b9a752c2", "updated_at": "2016-05-29T01:44:59.827812", "entity": "80bbcad3abbc4694a9e35ecc2a8c2179", "position": null, "id": "ffe7118837644097bf3c7cf9b9a752c2"}, {"status": "inactive", "first_name": "Felix", "last_name": "N\u00d6LLER", "name": "Mr Felix N\u00d6LLER", "title": "Mr", "created_at": "2015-08-04T23:30:24.961182", "uri": "http://api.lobbyfacts.eu/api/1/person/ffe39da57ca34c1392974adf5e54cafa", "updated_at": "2015-10-10T00:36:18.906681", "entity": "a38ef74b754a48dcbbfc299e7133472d", "position": null, "id": "ffe39da57ca34c1392974adf5e54cafa"}, {"status": "active", "first_name": "Eric", "last_name": "D\u00e9robert", "name": "Mr Eric D\u00e9robert", "title": "Mr", "created_at": "2016-08-17T01:39:23.665156", "uri": "http://api.lobbyfacts.eu/api/1/person/ffe0b90193684df1a476bfa5e66bc749", "updated_at": "2016-08-17T01:39:23.662897", "entity": "c4e869c531244404abc24f29940de02b", "position": "Pr\u00e9sident", "id": "ffe0b90193684df1a476bfa5e66bc749"}, {"status": "inactive", "first_name": "Xavier", "last_name": "OUSMANE", "name": "Mr Xavier OUSMANE", "title": "Mr", "created_at": "2015-08-04T23:08:26.512050", "uri": "http://api.lobbyfacts.eu/api/1/person/ffdfdf683bac461db2ce125578ef7bf7", "updated_at": "2015-08-30T00:39:28.994682", "entity": "7d9169adde8549ab8a1f0264324d2f1f", "position": null, "id": "ffdfdf683bac461db2ce125578ef7bf7"}, {"status": "active", "first_name": "Tuomo", "last_name": "Kantola", "name": " Tuomo Kantola", "title": null, "created_at": "2016-05-05T02:03:20.848748", "uri": "http://api.lobbyfacts.eu/api/1/person/ffdbd345128d4b32a39f658bb84396da", "updated_at": "2016-05-05T02:03:20.847098", "entity": "47101ad36df340569b9b528b70c5110c", "position": "Toimitusjohtaja", "id": "ffdbd345128d4b32a39f658bb84396da"}, {"status": "active", "first_name": "Anette", "last_name": "HAUFF", "name": "Ms Anette HAUFF", "title": "Ms", "created_at": "2015-08-04T23:29:07.346512", "uri": "http://api.lobbyfacts.eu/api/1/person/ffda7773348f48c2bcb77860a077a231", "updated_at": "2015-08-04T23:29:07.345174", "entity": "2d0354d4776f47c7a5a7453ddbdf2931", "position": null, "id": "ffda7773348f48c2bcb77860a077a231"}, {"status": "inactive", "first_name": "Andrew", "last_name": "CURTIS", "name": "Mr Andrew CURTIS", "title": "Mr", "created_at": "2015-08-04T22:37:37.630107", "uri": "http://api.lobbyfacts.eu/api/1/person/ffd97d5fa9ce411eb8e7f2c16fa032b3", "updated_at": "2015-10-07T23:42:05.080487", "entity": "d15936f25d7449998b977b318738077d", "position": null, "id": "ffd97d5fa9ce411eb8e7f2c16fa032b3"}, {"status": "active", "first_name": "Dr. Alexander", "last_name": "Dix", "name": "Mr Dr. Alexander Dix", "title": "Mr", "created_at": "2016-07-26T02:14:12.400224", "uri": "http://api.lobbyfacts.eu/api/1/person/ffd84a5aadd54a4c9bfa4b054a0a1e5f", "updated_at": "2016-07-26T02:14:12.397991", "entity": "1b4df2f9ead14d7cb0f7216aa2b60dcd", "position": "Stellv. Vorsitzender des Vorstandes", "id": "ffd84a5aadd54a4c9bfa4b054a0a1e5f"}, {"status": "inactive", "first_name": "Arba", "last_name": "Berdica", "name": "Ms Arba Berdica", "title": "Ms", "created_at": "2015-04-24T01:58:46.630945", "uri": "http://api.lobbyfacts.eu/api/1/person/ffd7a7fa1a784d379eb85fd3afb4d117", "updated_at": "2015-07-18T00:05:04.548621", "entity": "c4788736ce5e43f1bc9c8a6a172de9e8", "position": null, "id": "ffd7a7fa1a784d379eb85fd3afb4d117"}, {"status": "active", "first_name": "Robin", "last_name": "Russel", "name": "Mr Robin Russel", "title": "Mr", "created_at": "2015-08-19T00:33:16.773778", "uri": "http://api.lobbyfacts.eu/api/1/person/ffd3e53acfc748a7a1077438ff717151", "updated_at": "2015-08-19T00:33:16.771268", "entity": "51a591f54fb042de953747c255043166", "position": "Operations Director", "id": "ffd3e53acfc748a7a1077438ff717151"}, {"status": "active", "first_name": "Johan", "last_name": "Cloet", "name": "Mr Johan Cloet", "title": "Mr", "created_at": "2015-05-07T21:39:13.187263", "uri": "http://api.lobbyfacts.eu/api/1/person/ffd36cd3a12645179da466ac331153be", "updated_at": "2015-06-09T00:45:34.466401", "entity": "6337b4c5b7124a8ea66536039f7da31d", "position": "Secretary General", "id": "ffd36cd3a12645179da466ac331153be"}, {"status": "active", "first_name": "Lluis", "last_name": "Prat", "name": " Lluis Prat", "title": null, "created_at": "2015-04-24T01:55:37.402043", "uri": "http://api.lobbyfacts.eu/api/1/person/ffcdeb423b28446abcef873c69df242a", "updated_at": "2015-04-28T00:19:34.269864", "entity": "22b145c522cd45b7b9738c1811979c8b", "position": "Secretario", "id": "ffcdeb423b28446abcef873c69df242a"}, {"status": "inactive", "first_name": "STEFAN", "last_name": "KESSLER", "name": "Mr STEFAN KESSLER", "title": "Mr", "created_at": "2015-04-24T02:04:46.096101", "uri": "http://api.lobbyfacts.eu/api/1/person/ffcd441aac3943af8df364f808fccca7", "updated_at": "2015-06-11T00:02:44.145074", "entity": "2567eb47f2144d2885553aaddba6f6e7", "position": null, "id": "ffcd441aac3943af8df364f808fccca7"}, {"status": "active", "first_name": "SANJA", "last_name": "UDOVI\u0106", "name": "Ms SANJA UDOVI\u0106", "title": "Ms", "created_at": "2015-05-24T21:47:17.221327", "uri": "http://api.lobbyfacts.eu/api/1/person/ffccdacbcda64e88b0e08b3950dab345", "updated_at": "2015-06-09T00:52:28.305503", "entity": "60cab7ab53074f8083d6f98c35519495", "position": "OP\u0106INSKA NA\u010cELNICA", "id": "ffccdacbcda64e88b0e08b3950dab345"}, {"status": "active", "first_name": "Lara", "last_name": "LIBRA", "name": "Ms Lara LIBRA", "title": "Ms", "created_at": "2016-02-04T02:54:18.561397", "uri": "http://api.lobbyfacts.eu/api/1/person/ffc74311698745138f9c2b774719c350", "updated_at": "2016-02-04T02:54:18.558910", "entity": "a999107a28d947978d93516c807ec438", "position": null, "id": "ffc74311698745138f9c2b774719c350"}, {"status": "active", "first_name": "Elena", "last_name": "Botanina", "name": "Ms Elena Botanina", "title": "Ms", "created_at": "2016-06-22T01:07:40.350135", "uri": "http://api.lobbyfacts.eu/api/1/person/ffc662accdcd4b07816707d9fb04eb2a", "updated_at": "2016-06-22T01:07:40.347819", "entity": "9bc4005ee22f4667ad2290c70764b805", "position": null, "id": "ffc662accdcd4b07816707d9fb04eb2a"}, {"status": "active", "first_name": "Aneta", "last_name": "JERSKA", "name": "Ms Aneta JERSKA", "title": "Ms", "created_at": "2015-10-22T23:59:47.627842", "uri": "http://api.lobbyfacts.eu/api/1/person/ffc5d0ef59e84ce2b0f2ae2e1ccea313", "updated_at": "2015-10-22T23:59:47.624821", "entity": "09f054eea8cf4dc782ee327dd3f0d8dc", "position": null, "id": "ffc5d0ef59e84ce2b0f2ae2e1ccea313"}, {"status": "inactive", "first_name": "Pol", "last_name": "MINGUET", "name": "Mr Pol MINGUET", "title": "Mr", "created_at": "2015-08-04T22:57:53.507633", "uri": "http://api.lobbyfacts.eu/api/1/person/ffc52b9ad3e5421aa9767f79dd81f16b", "updated_at": "2015-09-22T23:54:42.438604", "entity": "535990e5a5734e7eb21ef8e9a9f2817b", "position": null, "id": "ffc52b9ad3e5421aa9767f79dd81f16b"}, {"status": "active", "first_name": "Delphine", "last_name": "BERNET", "name": "Ms Delphine BERNET", "title": "Ms", "created_at": "2015-04-24T02:14:49.294913", "uri": "http://api.lobbyfacts.eu/api/1/person/ffc449a814a34ff6b24a3ef0286ae408", "updated_at": "2015-06-24T00:11:55.106709", "entity": "5860724e63a14155a970f77cc06bf635", "position": null, "id": "ffc449a814a34ff6b24a3ef0286ae408"}, {"status": "inactive", "first_name": "Lopo", "last_name": "Carvalho", "name": "Lopo Carvalho", "title": null, "created_at": "2016-04-02T00:58:30.912493", "uri": "http://api.lobbyfacts.eu/api/1/person/ffc39c72b4234b7f8de7eb9bb5eca7f1", "updated_at": "2016-08-24T01:14:30.276826", "entity": "5906d5fed679487e99e3e2cf01899772", "position": null, "id": "ffc39c72b4234b7f8de7eb9bb5eca7f1"}, {"status": "active", "first_name": "Akiko", "last_name": "HART", "name": "Ms Akiko HART", "title": "Ms", "created_at": "2016-01-17T01:45:27.658433", "uri": "http://api.lobbyfacts.eu/api/1/person/ffbf098231044d94b413a5f72639689a", "updated_at": "2016-01-17T01:45:27.655462", "entity": "ee4202812abf464c95f71e1f373cca8d", "position": null, "id": "ffbf098231044d94b413a5f72639689a"}, {"status": "inactive", "first_name": "Ramboux", "last_name": "Sandrine", "name": "Ms Ramboux Sandrine", "title": "Ms", "created_at": "2015-04-24T02:23:17.433266", "uri": "http://api.lobbyfacts.eu/api/1/person/ffbe6a6aeacd4698af31cc64e168ce39", "updated_at": "2016-04-07T00:40:36.117992", "entity": "c1ef9815d5c140288fb45a0e93dff6db", "position": "CEO", "id": "ffbe6a6aeacd4698af31cc64e168ce39"}, {"status": "inactive", "first_name": "John", "last_name": "PHELAN", "name": "Mr John PHELAN", "title": "Mr", "created_at": "2015-08-04T23:29:45.048949", "uri": "http://api.lobbyfacts.eu/api/1/person/ffbd37a0eaa6403180260e1a3cb017f5", "updated_at": "2015-11-07T01:32:01.840063", "entity": "41d618e2f1444e4883db0fbef5846066", "position": null, "id": "ffbd37a0eaa6403180260e1a3cb017f5"}, {"status": "active", "first_name": "Jaume", "last_name": "LOFFREDO", "name": "Mr Jaume LOFFREDO", "title": "Mr", "created_at": "2015-08-04T22:40:07.789281", "uri": "http://api.lobbyfacts.eu/api/1/person/ffbbb2ca525947e4ac31b64d7d8be7a0", "updated_at": "2015-10-22T23:42:31.973853", "entity": "6c31c3a458c64e93b1638bf1e35fd848", "position": null, "id": "ffbbb2ca525947e4ac31b64d7d8be7a0"}, {"status": "active", "first_name": "Lewis", "last_name": "Shand Smith", "name": "Mr Lewis Shand Smith", "title": "Mr", "created_at": "2015-04-24T02:32:11.561600", "uri": "http://api.lobbyfacts.eu/api/1/person/ffb8eea4552c4cd6abb9cf8a9f573a71", "updated_at": "2015-06-09T00:30:54.799976", "entity": "102412cbe67d41cf84ed88e86f10d815", "position": "Chair", "id": "ffb8eea4552c4cd6abb9cf8a9f573a71"}, {"status": "active", "first_name": "Tim", "last_name": "Bennett", "name": "Mr Tim Bennett", "title": "Mr", "created_at": "2015-04-24T01:54:36.629902", "uri": "http://api.lobbyfacts.eu/api/1/person/ffb7a6d39627443d95ed632d9f0dc0c0", "updated_at": "2015-04-28T00:18:46.384414", "entity": "c7c13947af6b4de29768f7fa7d599ed6", "position": "Director-General", "id": "ffb7a6d39627443d95ed632d9f0dc0c0"}, {"status": "active", "first_name": "Sebastiaan", "last_name": "BATELAAN", "name": "Mr Sebastiaan BATELAAN", "title": "Mr", "created_at": "2015-08-04T23:37:05.175116", "uri": "http://api.lobbyfacts.eu/api/1/person/ffb61a20a245419bb6c4c0a4a03775d1", "updated_at": "2015-11-28T02:04:31.505728", "entity": "2f0a65caf3624120a9bb30d266efba9d", "position": null, "id": "ffb61a20a245419bb6c4c0a4a03775d1"}, {"status": "inactive", "first_name": "Alasdair", "last_name": "MacEwen", "name": "Mr Alasdair MacEwen", "title": "Mr", "created_at": "2015-04-24T02:16:04.683196", "uri": "http://api.lobbyfacts.eu/api/1/person/ffb5c78b29814171b88746f29ef74ff9", "updated_at": "2016-04-06T00:31:20.357145", "entity": "5c956df07e39444a964d932c195082cf", "position": "Director", "id": "ffb5c78b29814171b88746f29ef74ff9"}, {"status": "inactive", "first_name": "Kent", "last_name": "Petersen", "name": " Kent Petersen", "title": null, "created_at": "2015-04-24T02:09:00.428688", "uri": "http://api.lobbyfacts.eu/api/1/person/ffb4d698762e434a969973ea69db8fa6", "updated_at": "2016-03-17T01:44:57.433271", "entity": "4164877ce9e94921a3f8a3d64c88fe17", "position": "President", "id": "ffb4d698762e434a969973ea69db8fa6"}, {"status": "inactive", "first_name": "Els", "last_name": "HOUTMAN", "name": "Ms Els HOUTMAN", "title": "Ms", "created_at": "2015-08-04T22:47:56.385202", "uri": "http://api.lobbyfacts.eu/api/1/person/ffb4b038bb69483281545844d6924cbd", "updated_at": "2015-08-18T23:34:05.187214", "entity": "b44a02c444464af38a1526a62ff8a9ef", "position": null, "id": "ffb4b038bb69483281545844d6924cbd"}, {"status": "inactive", "first_name": "Pavel", "last_name": "GLUKHOV", "name": "Mr Pavel GLUKHOV", "title": "Mr", "created_at": "2015-08-04T23:31:04.785752", "uri": "http://api.lobbyfacts.eu/api/1/person/ffae269019c44f4d87395fd35362d17a", "updated_at": "2016-05-13T01:07:55.713761", "entity": "ca09b6a0a36841cba747d57a76d8639a", "position": null, "id": "ffae269019c44f4d87395fd35362d17a"}, {"status": "active", "first_name": "Catherine ", "last_name": "Easton", "name": "Ms Catherine Easton", "title": "Ms", "created_at": "2015-09-03T01:23:20.605354", "uri": "http://api.lobbyfacts.eu/api/1/person/ffabd37094c24626a6901a03799c35d2", "updated_at": "2016-09-18T20:05:20.747376", "entity": "bed56c6310c6497b8c456b9244c2a427", "position": "Chair, BILETA ", "id": "ffabd37094c24626a6901a03799c35d2"}, {"status": "active", "first_name": "Dirk", "last_name": "VAEL", "name": "Mr Dirk VAEL", "title": "Mr", "created_at": "2015-05-07T21:26:27.027951", "uri": "http://api.lobbyfacts.eu/api/1/person/ffa976414f1e4ec49f7b5be55c70ee54", "updated_at": "2016-05-10T01:08:32.817372", "entity": "769c08a682054fb5a978b8f4b617e19d", "position": "Secretary General", "id": "ffa976414f1e4ec49f7b5be55c70ee54"}, {"status": "inactive", "first_name": "Blandine", "last_name": "Maindiaux", "name": "Ms Blandine Maindiaux", "title": "Ms", "created_at": "2016-01-09T01:03:07.270560", "uri": "http://api.lobbyfacts.eu/api/1/person/ffa7f3e3c3aa46dba03705a3ba329196", "updated_at": "2016-02-04T01:18:06.006069", "entity": "9a0fc49278be43d4bbc8219f618ac471", "position": null, "id": "ffa7f3e3c3aa46dba03705a3ba329196"}, {"status": "inactive", "first_name": "Cristian", "last_name": "Samoilovich", "name": "Mr Cristian Samoilovich", "title": "Mr", "created_at": "2015-11-21T01:53:32.203734", "uri": "http://api.lobbyfacts.eu/api/1/person/ffa4ce554ea2479ab755fc785c2e74ae", "updated_at": "2016-02-04T02:11:19.989290", "entity": "2ed1f68fe47d455f8822ceeee1359e54", "position": null, "id": "ffa4ce554ea2479ab755fc785c2e74ae"}, {"status": "active", "first_name": "Marta", "last_name": "Marin Sanchez", "name": " Marta Marin Sanchez", "title": null, "created_at": "2015-04-24T02:24:37.850717", "uri": "http://api.lobbyfacts.eu/api/1/person/ffa348b217f546f7b3caba28e01648ea", "updated_at": "2016-04-21T00:57:11.406963", "entity": "4234e7e3ecc94a4687f373e26b19d29a", "position": "Delegada de Euskadi para la Union europea", "id": "ffa348b217f546f7b3caba28e01648ea"}, {"status": "inactive", "first_name": "adele", "last_name": "CORNAGLIA", "name": "Ms adele CORNAGLIA", "title": "Ms", "created_at": "2016-02-04T02:32:43.740368", "uri": "http://api.lobbyfacts.eu/api/1/person/ff9fc768c14c4a09a5e1a0c226293852", "updated_at": "2016-07-21T01:26:12.330350", "entity": "1274bd478d274c2e9d4accdea9f2384c", "position": null, "id": "ff9fc768c14c4a09a5e1a0c226293852"}, {"status": "active", "first_name": "Koen", "last_name": "COPPENHOLLE", "name": "Mr Koen COPPENHOLLE", "title": "Mr", "created_at": "2015-08-04T23:35:27.018355", "uri": "http://api.lobbyfacts.eu/api/1/person/ff9e50bc9719467584315d72376151eb", "updated_at": "2015-11-15T01:39:20.818298", "entity": "f790c12d66904722ae8d98fc124cc4cd", "position": null, "id": "ff9e50bc9719467584315d72376151eb"}, {"status": "active", "first_name": "Adrian", "last_name": "Burder", "name": "Mr Adrian Burder", "title": "Mr", "created_at": "2015-04-24T02:32:15.189726", "uri": "http://api.lobbyfacts.eu/api/1/person/ff9df9f32dba442caa42a4dddad0e1a8", "updated_at": "2015-06-09T00:31:01.344949", "entity": "01dcda1360ff43198ce5ca4696bf46eb", "position": "CEO of founding member Dogs Trust", "id": "ff9df9f32dba442caa42a4dddad0e1a8"}, {"status": "active", "first_name": "Michael", "last_name": "Tscherny", "name": "Mr Michael Tscherny", "title": "Mr", "created_at": "2015-05-07T21:14:09.536326", "uri": "http://api.lobbyfacts.eu/api/1/person/ff9a9f2982b44af6b22c345e217fa277", "updated_at": "2015-05-07T21:14:09.535088", "entity": "fc4ff63acd4b4342b962f55b9c680827", "position": "Partner", "id": "ff9a9f2982b44af6b22c345e217fa277"}], "next": "http://api.lobbyfacts.eu/api/1/person?limit=50&offset=50", "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 36713, + "facets": {}, + "results": [ + { + "status": "inactive", + "first_name": "Lasse Hamilton", + "last_name": "Heidemann", + "name": "Lasse Hamilton Heidemann", + "title": null, + "created_at": "2015-12-05T00:52:13.534368Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffff1e3de5aa4db8ace7dcb080a4c2e0", + "updated_at": "2016-02-04T01:11:29.396185Z", + "entity": "ba0821d8786b4764b4e83d48a62f155e", + "position": null, + "id": "ffff1e3de5aa4db8ace7dcb080a4c2e0" + }, + { + "status": "inactive", + "first_name": "Peter H.P.", + "last_name": "Sierat", + "name": "Mr Peter H.P. Sierat", + "title": "Mr", + "created_at": "2015-04-24T01:49:19.714706Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fffdcd840ce74712ab96125b3c8a29f2", + "updated_at": "2016-04-02T00:00:39.433543Z", + "entity": "cb57ae8983dc4ceaba72e7befd59b255", + "position": "Algemeen directeur", + "id": "fffdcd840ce74712ab96125b3c8a29f2" + }, + { + "status": "inactive", + "first_name": "Aleksandra", + "last_name": "Kluczka", + "name": "Ms Aleksandra Kluczka", + "title": "Ms", + "created_at": "2015-04-24T02:13:06.918194Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fffd214acfab4df39770a3cb1cd2a16e", + "updated_at": "2015-08-04T23:02:51.578546Z", + "entity": "edc26b7e632146039f0cb3c673d9e5b5", + "position": null, + "id": "fffd214acfab4df39770a3cb1cd2a16e" + }, + { + "status": "active", + "first_name": "Nicholas", + "last_name": "Cook", + "name": "Mr Nicholas Cook", + "title": "Mr", + "created_at": "2016-04-28T01:46:54.088777Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fffba075e7244af5beaf4cb4df492d0c", + "updated_at": "2016-04-28T01:46:54.086259Z", + "entity": "2bd41f5a042a4584afe2e2faf7f99d9b", + "position": null, + "id": "fffba075e7244af5beaf4cb4df492d0c" + }, + { + "status": "active", + "first_name": "LORIS", + "last_name": "BORGHI", + "name": " LORIS BORGHI", + "title": null, + "created_at": "2016-04-24T01:46:22.432444Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fff6a7c563db4260833e4a0a5132e06d", + "updated_at": "2016-04-24T01:46:22.430054Z", + "entity": "9b890aa4ae8c41c2993408018216ffea", + "position": "RETTORE", + "id": "fff6a7c563db4260833e4a0a5132e06d" + }, + { + "status": "active", + "first_name": "Mary", + "last_name": "Booth", + "name": "Ms Mary Booth", + "title": "Ms", + "created_at": "2016-05-06T01:50:28.394132Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fff42bf8b9bf4553a22a2e54dc060e7b", + "updated_at": "2016-05-06T01:50:28.390872Z", + "entity": "4a58ff1f55804c45961de16e03caf8f2", + "position": "President", + "id": "fff42bf8b9bf4553a22a2e54dc060e7b" + }, + { + "status": "active", + "first_name": "Zolt\u00e1n", + "last_name": "Dub\u00e9czi ", + "name": " Zolt\u00e1n Dub\u00e9czi ", + "title": null, + "created_at": "2015-04-24T02:33:55.473918Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fff1ba1aeb93455a9d58d4e8d30106ef", + "updated_at": "2015-06-09T00:33:29.597458Z", + "entity": "1604b87b837849e494c502955d9890a6", + "position": "f\u0151ttitk\u00e1r", + "id": "fff1ba1aeb93455a9d58d4e8d30106ef" + }, + { + "status": "active", + "first_name": "Andreas", + "last_name": "von Bonin", + "name": "Mr Andreas von Bonin", + "title": "Mr", + "created_at": "2015-10-29T01:59:20.041336Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/fff0688a62b147ce8d4d9e41a8bdf88b", + "updated_at": "2015-10-29T01:59:20.040060Z", + "entity": "a944c83d1fe84cabaeff9b672d0d1234", + "position": "Partner", + "id": "fff0688a62b147ce8d4d9e41a8bdf88b" + }, + { + "status": "active", + "first_name": "Jeff", + "last_name": "RUPP", + "name": "Mr Jeff RUPP", + "title": "Mr", + "created_at": "2015-04-24T01:55:31.635859Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffeb9e9a626945be9b3b24430559d1c9", + "updated_at": "2016-08-24T00:25:06.902891Z", + "entity": "4135e9a4a93142eda69d7e9a5cd37c7a", + "position": null, + "id": "ffeb9e9a626945be9b3b24430559d1c9" + }, + { + "status": "inactive", + "first_name": "Marisa", + "last_name": "PLOWDEN", + "name": "Ms Marisa PLOWDEN", + "title": "Ms", + "created_at": "2015-08-04T23:38:47.343642Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffeb6dc0543a4bdd9c8a785878604da4", + "updated_at": "2016-07-29T01:21:54.336544Z", + "entity": "109aaeca90e641b5b0aa218489390222", + "position": null, + "id": "ffeb6dc0543a4bdd9c8a785878604da4" + }, + { + "status": "active", + "first_name": "GOKHAN", + "last_name": "BACIK", + "name": "Mr GOKHAN BACIK", + "title": "Mr", + "created_at": "2016-05-29T01:44:59.830189Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffe7118837644097bf3c7cf9b9a752c2", + "updated_at": "2016-05-29T01:44:59.827812Z", + "entity": "80bbcad3abbc4694a9e35ecc2a8c2179", + "position": null, + "id": "ffe7118837644097bf3c7cf9b9a752c2" + }, + { + "status": "inactive", + "first_name": "Felix", + "last_name": "N\u00d6LLER", + "name": "Mr Felix N\u00d6LLER", + "title": "Mr", + "created_at": "2015-08-04T23:30:24.961182Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffe39da57ca34c1392974adf5e54cafa", + "updated_at": "2015-10-10T00:36:18.906681Z", + "entity": "a38ef74b754a48dcbbfc299e7133472d", + "position": null, + "id": "ffe39da57ca34c1392974adf5e54cafa" + }, + { + "status": "active", + "first_name": "Eric", + "last_name": "D\u00e9robert", + "name": "Mr Eric D\u00e9robert", + "title": "Mr", + "created_at": "2016-08-17T01:39:23.665156Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffe0b90193684df1a476bfa5e66bc749", + "updated_at": "2016-08-17T01:39:23.662897Z", + "entity": "c4e869c531244404abc24f29940de02b", + "position": "Pr\u00e9sident", + "id": "ffe0b90193684df1a476bfa5e66bc749" + }, + { + "status": "inactive", + "first_name": "Xavier", + "last_name": "OUSMANE", + "name": "Mr Xavier OUSMANE", + "title": "Mr", + "created_at": "2015-08-04T23:08:26.512050Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffdfdf683bac461db2ce125578ef7bf7", + "updated_at": "2015-08-30T00:39:28.994682Z", + "entity": "7d9169adde8549ab8a1f0264324d2f1f", + "position": null, + "id": "ffdfdf683bac461db2ce125578ef7bf7" + }, + { + "status": "active", + "first_name": "Tuomo", + "last_name": "Kantola", + "name": " Tuomo Kantola", + "title": null, + "created_at": "2016-05-05T02:03:20.848748Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffdbd345128d4b32a39f658bb84396da", + "updated_at": "2016-05-05T02:03:20.847098Z", + "entity": "47101ad36df340569b9b528b70c5110c", + "position": "Toimitusjohtaja", + "id": "ffdbd345128d4b32a39f658bb84396da" + }, + { + "status": "active", + "first_name": "Anette", + "last_name": "HAUFF", + "name": "Ms Anette HAUFF", + "title": "Ms", + "created_at": "2015-08-04T23:29:07.346512Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffda7773348f48c2bcb77860a077a231", + "updated_at": "2015-08-04T23:29:07.345174Z", + "entity": "2d0354d4776f47c7a5a7453ddbdf2931", + "position": null, + "id": "ffda7773348f48c2bcb77860a077a231" + }, + { + "status": "inactive", + "first_name": "Andrew", + "last_name": "CURTIS", + "name": "Mr Andrew CURTIS", + "title": "Mr", + "created_at": "2015-08-04T22:37:37.630107Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffd97d5fa9ce411eb8e7f2c16fa032b3", + "updated_at": "2015-10-07T23:42:05.080487Z", + "entity": "d15936f25d7449998b977b318738077d", + "position": null, + "id": "ffd97d5fa9ce411eb8e7f2c16fa032b3" + }, + { + "status": "active", + "first_name": "Dr. Alexander", + "last_name": "Dix", + "name": "Mr Dr. Alexander Dix", + "title": "Mr", + "created_at": "2016-07-26T02:14:12.400224Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffd84a5aadd54a4c9bfa4b054a0a1e5f", + "updated_at": "2016-07-26T02:14:12.397991Z", + "entity": "1b4df2f9ead14d7cb0f7216aa2b60dcd", + "position": "Stellv. Vorsitzender des Vorstandes", + "id": "ffd84a5aadd54a4c9bfa4b054a0a1e5f" + }, + { + "status": "inactive", + "first_name": "Arba", + "last_name": "Berdica", + "name": "Ms Arba Berdica", + "title": "Ms", + "created_at": "2015-04-24T01:58:46.630945Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffd7a7fa1a784d379eb85fd3afb4d117", + "updated_at": "2015-07-18T00:05:04.548621Z", + "entity": "c4788736ce5e43f1bc9c8a6a172de9e8", + "position": null, + "id": "ffd7a7fa1a784d379eb85fd3afb4d117" + }, + { + "status": "active", + "first_name": "Robin", + "last_name": "Russel", + "name": "Mr Robin Russel", + "title": "Mr", + "created_at": "2015-08-19T00:33:16.773778Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffd3e53acfc748a7a1077438ff717151", + "updated_at": "2015-08-19T00:33:16.771268Z", + "entity": "51a591f54fb042de953747c255043166", + "position": "Operations Director", + "id": "ffd3e53acfc748a7a1077438ff717151" + }, + { + "status": "active", + "first_name": "Johan", + "last_name": "Cloet", + "name": "Mr Johan Cloet", + "title": "Mr", + "created_at": "2015-05-07T21:39:13.187263Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffd36cd3a12645179da466ac331153be", + "updated_at": "2015-06-09T00:45:34.466401Z", + "entity": "6337b4c5b7124a8ea66536039f7da31d", + "position": "Secretary General", + "id": "ffd36cd3a12645179da466ac331153be" + }, + { + "status": "active", + "first_name": "Lluis", + "last_name": "Prat", + "name": " Lluis Prat", + "title": null, + "created_at": "2015-04-24T01:55:37.402043Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffcdeb423b28446abcef873c69df242a", + "updated_at": "2015-04-28T00:19:34.269864Z", + "entity": "22b145c522cd45b7b9738c1811979c8b", + "position": "Secretario", + "id": "ffcdeb423b28446abcef873c69df242a" + }, + { + "status": "inactive", + "first_name": "STEFAN", + "last_name": "KESSLER", + "name": "Mr STEFAN KESSLER", + "title": "Mr", + "created_at": "2015-04-24T02:04:46.096101Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffcd441aac3943af8df364f808fccca7", + "updated_at": "2015-06-11T00:02:44.145074Z", + "entity": "2567eb47f2144d2885553aaddba6f6e7", + "position": null, + "id": "ffcd441aac3943af8df364f808fccca7" + }, + { + "status": "active", + "first_name": "SANJA", + "last_name": "UDOVI\u0106", + "name": "Ms SANJA UDOVI\u0106", + "title": "Ms", + "created_at": "2015-05-24T21:47:17.221327Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffccdacbcda64e88b0e08b3950dab345", + "updated_at": "2015-06-09T00:52:28.305503Z", + "entity": "60cab7ab53074f8083d6f98c35519495", + "position": "OP\u0106INSKA NA\u010cELNICA", + "id": "ffccdacbcda64e88b0e08b3950dab345" + }, + { + "status": "active", + "first_name": "Lara", + "last_name": "LIBRA", + "name": "Ms Lara LIBRA", + "title": "Ms", + "created_at": "2016-02-04T02:54:18.561397Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffc74311698745138f9c2b774719c350", + "updated_at": "2016-02-04T02:54:18.558910Z", + "entity": "a999107a28d947978d93516c807ec438", + "position": null, + "id": "ffc74311698745138f9c2b774719c350" + }, + { + "status": "active", + "first_name": "Elena", + "last_name": "Botanina", + "name": "Ms Elena Botanina", + "title": "Ms", + "created_at": "2016-06-22T01:07:40.350135Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffc662accdcd4b07816707d9fb04eb2a", + "updated_at": "2016-06-22T01:07:40.347819Z", + "entity": "9bc4005ee22f4667ad2290c70764b805", + "position": null, + "id": "ffc662accdcd4b07816707d9fb04eb2a" + }, + { + "status": "active", + "first_name": "Aneta", + "last_name": "JERSKA", + "name": "Ms Aneta JERSKA", + "title": "Ms", + "created_at": "2015-10-22T23:59:47.627842Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffc5d0ef59e84ce2b0f2ae2e1ccea313", + "updated_at": "2015-10-22T23:59:47.624821Z", + "entity": "09f054eea8cf4dc782ee327dd3f0d8dc", + "position": null, + "id": "ffc5d0ef59e84ce2b0f2ae2e1ccea313" + }, + { + "status": "inactive", + "first_name": "Pol", + "last_name": "MINGUET", + "name": "Mr Pol MINGUET", + "title": "Mr", + "created_at": "2015-08-04T22:57:53.507633Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffc52b9ad3e5421aa9767f79dd81f16b", + "updated_at": "2015-09-22T23:54:42.438604Z", + "entity": "535990e5a5734e7eb21ef8e9a9f2817b", + "position": null, + "id": "ffc52b9ad3e5421aa9767f79dd81f16b" + }, + { + "status": "active", + "first_name": "Delphine", + "last_name": "BERNET", + "name": "Ms Delphine BERNET", + "title": "Ms", + "created_at": "2015-04-24T02:14:49.294913Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffc449a814a34ff6b24a3ef0286ae408", + "updated_at": "2015-06-24T00:11:55.106709Z", + "entity": "5860724e63a14155a970f77cc06bf635", + "position": null, + "id": "ffc449a814a34ff6b24a3ef0286ae408" + }, + { + "status": "inactive", + "first_name": "Lopo", + "last_name": "Carvalho", + "name": "Lopo Carvalho", + "title": null, + "created_at": "2016-04-02T00:58:30.912493Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffc39c72b4234b7f8de7eb9bb5eca7f1", + "updated_at": "2016-08-24T01:14:30.276826Z", + "entity": "5906d5fed679487e99e3e2cf01899772", + "position": null, + "id": "ffc39c72b4234b7f8de7eb9bb5eca7f1" + }, + { + "status": "active", + "first_name": "Akiko", + "last_name": "HART", + "name": "Ms Akiko HART", + "title": "Ms", + "created_at": "2016-01-17T01:45:27.658433Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffbf098231044d94b413a5f72639689a", + "updated_at": "2016-01-17T01:45:27.655462Z", + "entity": "ee4202812abf464c95f71e1f373cca8d", + "position": null, + "id": "ffbf098231044d94b413a5f72639689a" + }, + { + "status": "inactive", + "first_name": "Ramboux", + "last_name": "Sandrine", + "name": "Ms Ramboux Sandrine", + "title": "Ms", + "created_at": "2015-04-24T02:23:17.433266Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffbe6a6aeacd4698af31cc64e168ce39", + "updated_at": "2016-04-07T00:40:36.117992Z", + "entity": "c1ef9815d5c140288fb45a0e93dff6db", + "position": "CEO", + "id": "ffbe6a6aeacd4698af31cc64e168ce39" + }, + { + "status": "inactive", + "first_name": "John", + "last_name": "PHELAN", + "name": "Mr John PHELAN", + "title": "Mr", + "created_at": "2015-08-04T23:29:45.048949Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffbd37a0eaa6403180260e1a3cb017f5", + "updated_at": "2015-11-07T01:32:01.840063Z", + "entity": "41d618e2f1444e4883db0fbef5846066", + "position": null, + "id": "ffbd37a0eaa6403180260e1a3cb017f5" + }, + { + "status": "active", + "first_name": "Jaume", + "last_name": "LOFFREDO", + "name": "Mr Jaume LOFFREDO", + "title": "Mr", + "created_at": "2015-08-04T22:40:07.789281Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffbbb2ca525947e4ac31b64d7d8be7a0", + "updated_at": "2015-10-22T23:42:31.973853Z", + "entity": "6c31c3a458c64e93b1638bf1e35fd848", + "position": null, + "id": "ffbbb2ca525947e4ac31b64d7d8be7a0" + }, + { + "status": "active", + "first_name": "Lewis", + "last_name": "Shand Smith", + "name": "Mr Lewis Shand Smith", + "title": "Mr", + "created_at": "2015-04-24T02:32:11.561600Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffb8eea4552c4cd6abb9cf8a9f573a71", + "updated_at": "2015-06-09T00:30:54.799976Z", + "entity": "102412cbe67d41cf84ed88e86f10d815", + "position": "Chair", + "id": "ffb8eea4552c4cd6abb9cf8a9f573a71" + }, + { + "status": "active", + "first_name": "Tim", + "last_name": "Bennett", + "name": "Mr Tim Bennett", + "title": "Mr", + "created_at": "2015-04-24T01:54:36.629902Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffb7a6d39627443d95ed632d9f0dc0c0", + "updated_at": "2015-04-28T00:18:46.384414Z", + "entity": "c7c13947af6b4de29768f7fa7d599ed6", + "position": "Director-General", + "id": "ffb7a6d39627443d95ed632d9f0dc0c0" + }, + { + "status": "active", + "first_name": "Sebastiaan", + "last_name": "BATELAAN", + "name": "Mr Sebastiaan BATELAAN", + "title": "Mr", + "created_at": "2015-08-04T23:37:05.175116Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffb61a20a245419bb6c4c0a4a03775d1", + "updated_at": "2015-11-28T02:04:31.505728Z", + "entity": "2f0a65caf3624120a9bb30d266efba9d", + "position": null, + "id": "ffb61a20a245419bb6c4c0a4a03775d1" + }, + { + "status": "inactive", + "first_name": "Alasdair", + "last_name": "MacEwen", + "name": "Mr Alasdair MacEwen", + "title": "Mr", + "created_at": "2015-04-24T02:16:04.683196Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffb5c78b29814171b88746f29ef74ff9", + "updated_at": "2016-04-06T00:31:20.357145Z", + "entity": "5c956df07e39444a964d932c195082cf", + "position": "Director", + "id": "ffb5c78b29814171b88746f29ef74ff9" + }, + { + "status": "inactive", + "first_name": "Kent", + "last_name": "Petersen", + "name": " Kent Petersen", + "title": null, + "created_at": "2015-04-24T02:09:00.428688Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffb4d698762e434a969973ea69db8fa6", + "updated_at": "2016-03-17T01:44:57.433271Z", + "entity": "4164877ce9e94921a3f8a3d64c88fe17", + "position": "President", + "id": "ffb4d698762e434a969973ea69db8fa6" + }, + { + "status": "inactive", + "first_name": "Els", + "last_name": "HOUTMAN", + "name": "Ms Els HOUTMAN", + "title": "Ms", + "created_at": "2015-08-04T22:47:56.385202Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffb4b038bb69483281545844d6924cbd", + "updated_at": "2015-08-18T23:34:05.187214Z", + "entity": "b44a02c444464af38a1526a62ff8a9ef", + "position": null, + "id": "ffb4b038bb69483281545844d6924cbd" + }, + { + "status": "inactive", + "first_name": "Pavel", + "last_name": "GLUKHOV", + "name": "Mr Pavel GLUKHOV", + "title": "Mr", + "created_at": "2015-08-04T23:31:04.785752Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffae269019c44f4d87395fd35362d17a", + "updated_at": "2016-05-13T01:07:55.713761Z", + "entity": "ca09b6a0a36841cba747d57a76d8639a", + "position": null, + "id": "ffae269019c44f4d87395fd35362d17a" + }, + { + "status": "active", + "first_name": "Catherine ", + "last_name": "Easton", + "name": "Ms Catherine Easton", + "title": "Ms", + "created_at": "2015-09-03T01:23:20.605354Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffabd37094c24626a6901a03799c35d2", + "updated_at": "2016-09-18T20:05:20.747376Z", + "entity": "bed56c6310c6497b8c456b9244c2a427", + "position": "Chair, BILETA ", + "id": "ffabd37094c24626a6901a03799c35d2" + }, + { + "status": "active", + "first_name": "Dirk", + "last_name": "VAEL", + "name": "Mr Dirk VAEL", + "title": "Mr", + "created_at": "2015-05-07T21:26:27.027951Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffa976414f1e4ec49f7b5be55c70ee54", + "updated_at": "2016-05-10T01:08:32.817372Z", + "entity": "769c08a682054fb5a978b8f4b617e19d", + "position": "Secretary General", + "id": "ffa976414f1e4ec49f7b5be55c70ee54" + }, + { + "status": "inactive", + "first_name": "Blandine", + "last_name": "Maindiaux", + "name": "Ms Blandine Maindiaux", + "title": "Ms", + "created_at": "2016-01-09T01:03:07.270560Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffa7f3e3c3aa46dba03705a3ba329196", + "updated_at": "2016-02-04T01:18:06.006069Z", + "entity": "9a0fc49278be43d4bbc8219f618ac471", + "position": null, + "id": "ffa7f3e3c3aa46dba03705a3ba329196" + }, + { + "status": "inactive", + "first_name": "Cristian", + "last_name": "Samoilovich", + "name": "Mr Cristian Samoilovich", + "title": "Mr", + "created_at": "2015-11-21T01:53:32.203734Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffa4ce554ea2479ab755fc785c2e74ae", + "updated_at": "2016-02-04T02:11:19.989290Z", + "entity": "2ed1f68fe47d455f8822ceeee1359e54", + "position": null, + "id": "ffa4ce554ea2479ab755fc785c2e74ae" + }, + { + "status": "active", + "first_name": "Marta", + "last_name": "Marin Sanchez", + "name": " Marta Marin Sanchez", + "title": null, + "created_at": "2015-04-24T02:24:37.850717Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ffa348b217f546f7b3caba28e01648ea", + "updated_at": "2016-04-21T00:57:11.406963Z", + "entity": "4234e7e3ecc94a4687f373e26b19d29a", + "position": "Delegada de Euskadi para la Union europea", + "id": "ffa348b217f546f7b3caba28e01648ea" + }, + { + "status": "inactive", + "first_name": "adele", + "last_name": "CORNAGLIA", + "name": "Ms adele CORNAGLIA", + "title": "Ms", + "created_at": "2016-02-04T02:32:43.740368Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ff9fc768c14c4a09a5e1a0c226293852", + "updated_at": "2016-07-21T01:26:12.330350Z", + "entity": "1274bd478d274c2e9d4accdea9f2384c", + "position": null, + "id": "ff9fc768c14c4a09a5e1a0c226293852" + }, + { + "status": "active", + "first_name": "Koen", + "last_name": "COPPENHOLLE", + "name": "Mr Koen COPPENHOLLE", + "title": "Mr", + "created_at": "2015-08-04T23:35:27.018355Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ff9e50bc9719467584315d72376151eb", + "updated_at": "2015-11-15T01:39:20.818298Z", + "entity": "f790c12d66904722ae8d98fc124cc4cd", + "position": null, + "id": "ff9e50bc9719467584315d72376151eb" + }, + { + "status": "active", + "first_name": "Adrian", + "last_name": "Burder", + "name": "Mr Adrian Burder", + "title": "Mr", + "created_at": "2015-04-24T02:32:15.189726Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ff9df9f32dba442caa42a4dddad0e1a8", + "updated_at": "2015-06-09T00:31:01.344949Z", + "entity": "01dcda1360ff43198ce5ca4696bf46eb", + "position": "CEO of founding member Dogs Trust", + "id": "ff9df9f32dba442caa42a4dddad0e1a8" + }, + { + "status": "active", + "first_name": "Michael", + "last_name": "Tscherny", + "name": "Mr Michael Tscherny", + "title": "Mr", + "created_at": "2015-05-07T21:14:09.536326Z", + "uri": "http://api.lobbyfacts.eu/api/1/person/ff9a9f2982b44af6b22c345e217fa277", + "updated_at": "2015-05-07T21:14:09.535088Z", + "entity": "fc4ff63acd4b4342b962f55b9c680827", + "position": "Partner", + "id": "ff9a9f2982b44af6b22c345e217fa277" + } + ], + "next": "http://api.lobbyfacts.eu/api/1/person?limit=50&offset=50", + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/misc/b4865.json b/test/inputs/json/misc/b4865.json index 053f3f4af..ff33b5f57 100644 --- a/test/inputs/json/misc/b4865.json +++ b/test/inputs/json/misc/b4865.json @@ -1,1000 +1,12204 @@ -[{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.08333,50.775]},"id":"1","mass":"21","name":"Aachen","nametype":"Valid","recclass":"L5","reclat":"50.775000","reclong":"6.083330","year":"1880-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.23333,56.18333]},"id":"2","mass":"720","name":"Aarhus","nametype":"Valid","recclass":"H6","reclat":"56.183330","reclong":"10.233330","year":"1951-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-113,54.21667]},"id":"6","mass":"107000","name":"Abee","nametype":"Valid","recclass":"EH4","reclat":"54.216670","reclong":"-113.000000","year":"1952-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.9,16.88333]},"id":"10","mass":"1914","name":"Acapulco","nametype":"Valid","recclass":"Acapulcoite","reclat":"16.883330","reclong":"-99.900000","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-64.95,-33.16667]},"id":"370","mass":"780","name":"Achiras","nametype":"Valid","recclass":"L6","reclat":"-33.166670","reclong":"-64.950000","year":"1902-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[71.8,32.1]},"id":"379","mass":"4239","name":"Adhi Kot","nametype":"Valid","recclass":"EH4","reclat":"32.100000","reclong":"71.800000","year":"1919-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[95.16667,44.83333]},"id":"390","mass":"910","name":"Adzhi-Bogdo (stone)","nametype":"Valid","recclass":"LL3-6","reclat":"44.833330","reclong":"95.166670","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.61667,44.21667]},"id":"392","mass":"30000","name":"Agen","nametype":"Valid","recclass":"H5","reclat":"44.216670","reclong":"0.616670","year":"1814-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-65.23333,-31.6]},"id":"398","mass":"1620","name":"Aguada","nametype":"Valid","recclass":"L6","reclat":"-31.600000","reclong":"-65.233330","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-64.55,-30.86667]},"id":"417","mass":"1440","name":"Aguila Blanca","nametype":"Valid","recclass":"L","reclat":"-30.866670","reclong":"-64.550000","year":"1920-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-9.57028,16.39806]},"id":"423","mass":"1000","name":"Aioun el Atrouss","nametype":"Valid","recclass":"Diogenite-pm","reclat":"16.398060","reclong":"-9.570280","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.38333,19.08333]},"id":"424","mass":"24000","name":"AΓ―r","nametype":"Valid","recclass":"L6","reclat":"19.083330","reclong":"8.383330","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[2.33333,50.66667]},"id":"425","name":"Aire-sur-la-Lys","nametype":"Valid","recclass":"Unknown","reclat":"50.666670","reclong":"2.333330","year":"1769-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.05,29.51667]},"id":"426","mass":"779","name":"Akaba","nametype":"Valid","recclass":"L6","reclat":"29.516670","reclong":"35.050000","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.95,29.71667]},"id":"427","mass":"1800","name":"Akbarpur","nametype":"Valid","recclass":"H4","reclat":"29.716670","reclong":"77.950000","year":"1838-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.43333,8.91667]},"id":"432","mass":"3000","name":"Akwanga","nametype":"Valid","recclass":"H","reclat":"8.916670","reclong":"8.433330","year":"1959-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[42.81667,39.91667]},"id":"433","mass":"50000","name":"Akyumak","nametype":"Valid","recclass":"Iron, IVA","reclat":"39.916670","reclong":"42.816670","year":"1981-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[39.51667,24.41667]},"id":"446","mass":"160","name":"Al Rais","nametype":"Valid","recclass":"CR2-an","reclat":"24.416670","reclong":"39.516670","year":"1957-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28.96,13.66033]},"id":"447","mass":"700","name":"Al Zarnkh","nametype":"Valid","recclass":"LL5","reclat":"13.660330","reclong":"28.960000","year":"2001-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4.08333,44.11667]},"id":"448","mass":"6000","name":"Alais","nametype":"Valid","recclass":"CI1","reclat":"44.116670","reclong":"4.083330","year":"1806-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.01667,44.65]},"id":"453","mass":"2000","name":"Albareto","nametype":"Valid","recclass":"L/LL4","reclat":"44.650000","reclong":"11.016670","year":"1766-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.66667,2]},"id":"454","mass":"625","name":"Alberta","nametype":"Valid","recclass":"L","reclat":"2.000000","reclong":"22.666670","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.01533,45.82133]},"id":"458","mass":"252","name":"Alby sur ChΓ©ran","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"45.821330","reclong":"6.015330","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.78333,51.78333]},"id":"461","mass":"700","name":"Aldsworth","nametype":"Valid","recclass":"LL5","reclat":"51.783330","reclong":"-1.783330","year":"1835-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.13333,36.23333]},"id":"462","mass":"3200","name":"Aleppo","nametype":"Valid","recclass":"L6","reclat":"36.233330","reclong":"37.133330","year":"1873-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.75,44.88333]},"id":"463","mass":"908","name":"Alessandria","nametype":"Valid","recclass":"H5","reclat":"44.883330","reclong":"8.750000","year":"1860-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.81667,50.95]},"id":"465","mass":"9251","name":"Alexandrovsky","nametype":"Valid","recclass":"H4","reclat":"50.950000","reclong":"31.816670","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.15,45.26667]},"id":"466","mass":"228000","name":"Alfianello","nametype":"Valid","recclass":"L6","reclat":"45.266670","reclong":"10.150000","year":"1883-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"50",":@computed_region_nnqa_25f4":"429","fall":"Fell","geolocation":{"type":"Point","coordinates":[-85.88333,42.53333]},"id":"2276","mass":"32000","name":"Allegan","nametype":"Valid","recclass":"H5","reclat":"42.533330","reclong":"-85.883330","year":"1899-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-105.31667,26.96667]},"id":"2278","mass":"2000000","name":"Allende","nametype":"Valid","recclass":"CV3","reclat":"26.966670","reclong":"-105.316670","year":"1969-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[32.41275,20.74575]},"id":"48915","mass":"3950","name":"Almahata Sitta","nametype":"Valid","recclass":"Ureilite-an","reclat":"20.745750","reclong":"32.412750","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[44.21556,35.27333]},"id":"2284","mass":"6000","name":"Alta'ameem","nametype":"Valid","recclass":"LL5","reclat":"35.273330","reclong":"44.215560","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.25,27.66667]},"id":"2290","mass":"6400","name":"Ambapur Nagla","nametype":"Valid","recclass":"H5","reclat":"27.666670","reclong":"78.250000","year":"1895-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[85.56667,26.58333]},"id":"2294","mass":"2700","name":"Andhara","nametype":"Valid","recclass":"Stone-uncl","reclat":"26.583330","reclong":"85.566670","year":"1880-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"49",":@computed_region_nnqa_25f4":"1723","fall":"Fell","geolocation":{"type":"Point","coordinates":[-70.75,44.61667]},"id":"2295","mass":"3200","name":"Andover","nametype":"Valid","recclass":"L6","reclat":"44.616670","reclong":"-70.750000","year":"1898-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.5,48.7]},"id":"2296","mass":"600","name":"Andreevka","nametype":"Valid","recclass":"L3","reclat":"48.700000","reclong":"37.500000","year":"1969-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.86667,20.88333]},"id":"2298","mass":"17900","name":"Andura","nametype":"Valid","recclass":"H6","reclat":"20.883330","reclong":"76.866670","year":"1939-01-01T00:00:00.000"} -,{"fall":"Found","geolocation":{"type":"Point","coordinates":[0,0]},"id":"50693","mass":"256.8","name":"Northwest Africa 5815","nametype":"Valid","recclass":"L5","reclat":"0.000000","reclong":"0.000000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.55,47.46667]},"id":"2301","name":"Angers","nametype":"Valid","recclass":"L6","reclat":"47.466670","reclong":"-0.550000","year":"1822-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-44.31667,-22.96667]},"id":"2302","mass":"1500","name":"Angra dos Reis (stone)","nametype":"Valid","recclass":"Angrite","reclat":"-22.966670","reclong":"-44.316670","year":"1869-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[39.71667,9.53333]},"id":"2304","mass":"6500","name":"Ankober","nametype":"Valid","recclass":"H4","reclat":"9.533330","reclong":"39.716670","year":"1942-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[105.18333,25.15]},"id":"2305","mass":"2500","name":"Anlong","nametype":"Valid","recclass":"H5","reclat":"25.150000","reclong":"105.183330","year":"1971-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[140.78556,40.81056]},"id":"2313","mass":"320","name":"Aomori","nametype":"Valid","recclass":"L6","reclat":"40.810560","reclong":"140.785560","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-2.71667,53.58333]},"id":"2318","mass":"15000","name":"Appley Bridge","nametype":"Valid","recclass":"LL6","reclat":"53.583330","reclong":"-2.716670","year":"1914-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.38333,43.86667]},"id":"2320","mass":"3200","name":"Apt","nametype":"Valid","recclass":"L6","reclat":"43.866670","reclong":"5.383330","year":"1803-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-66,-33]},"id":"2325","mass":"810","name":"Arbol Solo","nametype":"Valid","recclass":"H5","reclat":"-33.000000","reclong":"-66.000000","year":"1954-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"2697","fall":"Fell","geolocation":{"type":"Point","coordinates":[-94.3,38.5]},"id":"2329","mass":"5070","name":"Archie","nametype":"Valid","recclass":"H6","reclat":"38.500000","reclong":"-94.300000","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-60.66667,-31.41667]},"id":"2340","mass":"7450","name":"Arroyo Aguiar","nametype":"Valid","recclass":"H5","reclat":"-31.416670","reclong":"-60.666670","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.03333,42.45]},"id":"2345","mass":"41","name":"Asco","nametype":"Valid","recclass":"H6","reclat":"42.450000","reclong":"9.033330","year":"1805-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"774","fall":"Fell","geolocation":{"type":"Point","coordinates":[-97.01,31.805]},"id":"48954","mass":"9500","name":"Ash Creek","nametype":"Valid","recclass":"L6","reclat":"31.805000","reclong":"-97.010000","year":"2009-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.3,52.05]},"id":"2346","mass":"1300","name":"Ashdon","nametype":"Valid","recclass":"L6","reclat":"52.050000","reclong":"0.300000","year":"1923-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.55,43.03333]},"id":"2353","mass":"2000","name":"Assisi","nametype":"Valid","recclass":"H5","reclat":"43.033330","reclong":"12.550000","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[80.625,25.25417]},"id":"4883","mass":"1280","name":"Atarra","nametype":"Valid","recclass":"L4","reclat":"25.254170","reclong":"80.625000","year":"1920-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.66667,20.06667]},"id":"4884","mass":"94.2","name":"Atemajac","nametype":"Valid","recclass":"L6","reclat":"20.066670","reclong":"-103.666670","year":"1896-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"29",":@computed_region_nnqa_25f4":"3134","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87,34.75]},"id":"4885","mass":"265","name":"Athens","nametype":"Valid","recclass":"LL6","reclat":"34.750000","reclong":"-87.000000","year":"1933-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"20",":@computed_region_nnqa_25f4":"602","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96.15,34.31667]},"id":"4888","mass":"1384.2","name":"Atoka","nametype":"Valid","recclass":"L6","reclat":"34.316670","reclong":"-96.150000","year":"1945-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.16667,44.38333]},"id":"4893","mass":"800","name":"Aubres","nametype":"Valid","recclass":"Aubrite","reclat":"44.383330","reclong":"5.166670","year":"1836-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.66667,36.16667]},"id":"4899","mass":"50000","name":"Aumale","nametype":"Valid","recclass":"L6","reclat":"36.166670","reclong":"3.666670","year":"1865-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.23333,44.33333]},"id":"4900","mass":"2000","name":"Aumieres","nametype":"Valid","recclass":"L6","reclat":"44.333330","reclong":"3.233330","year":"1842-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.58333,43.08333]},"id":"4903","mass":"50000","name":"Ausson","nametype":"Valid","recclass":"L5","reclat":"43.083330","reclong":"0.583330","year":"1858-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-49.95083,-21.46028]},"id":"4905","mass":"9330","name":"Avanhandava","nametype":"Valid","recclass":"H4","reclat":"-21.460280","reclong":"-49.950830","year":"1952-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.5,46]},"id":"4906","mass":"1230","name":"Avce","nametype":"Valid","recclass":"Iron, IIAB","reclat":"46.000000","reclong":"13.500000","year":"1908-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.5,25]},"id":"4907","mass":"146","name":"Avilez","nametype":"Valid","recclass":"H","reclat":"25.000000","reclong":"-103.500000","year":"1855-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[32.83333,2.71667]},"id":"4910","mass":"134","name":"Awere","nametype":"Valid","recclass":"L4","reclat":"2.716670","reclong":"32.833330","year":"1968-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"11",":@computed_region_nnqa_25f4":"1989","fall":"Fell","geolocation":{"type":"Point","coordinates":[-108,36.8]},"id":"4913","mass":"2830","name":"Aztec","nametype":"Valid","recclass":"L6","reclat":"36.800000","reclong":"-108.000000","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[38,48.6]},"id":"4917","mass":"18000","name":"Bachmut","nametype":"Valid","recclass":"L6","reclat":"48.600000","reclong":"38.000000","year":"1814-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.5,28.48333]},"id":"4922","mass":"10322","name":"Bahjoi","nametype":"Valid","recclass":"Iron, IAB-sLL","reclat":"28.483330","reclong":"78.500000","year":"1934-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"2373","fall":"Fell","geolocation":{"type":"Point","coordinates":[-82.48333,35.96667]},"id":"4925","mass":"3700","name":"Bald Mountain","nametype":"Valid","recclass":"L4","reclat":"35.966670","reclong":"-82.483330","year":"1929-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"32",":@computed_region_nnqa_25f4":"495","fall":"Fell","geolocation":{"type":"Point","coordinates":[-88.66667,34.5]},"id":"4926","mass":"345","name":"Baldwyn","nametype":"Valid","recclass":"L6","reclat":"34.500000","reclong":"-88.666670","year":"1922-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.38333,5.38333]},"id":"4928","mass":"1000","name":"Bali","nametype":"Valid","recclass":"CV3","reclat":"5.383330","reclong":"16.383330","year":"1907-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[101.18333,16.66667]},"id":"4934","mass":"16700","name":"Ban Rong Du","nametype":"Valid","recclass":"Iron, ungrouped","reclat":"16.666670","reclong":"101.183330","year":"1993-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[107.6,-6.91667]},"id":"4935","mass":"11500","name":"Bandong","nametype":"Valid","recclass":"LL6","reclat":"-6.916670","reclong":"107.600000","year":"1871-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.33333,27.7]},"id":"4936","mass":"15000","name":"Bansur","nametype":"Valid","recclass":"L6","reclat":"27.700000","reclong":"76.333330","year":"1892-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.2,30.4]},"id":"4937","mass":"14","name":"Banswal","nametype":"Valid","recclass":"L5","reclat":"30.400000","reclong":"78.200000","year":"1913-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[106,-6.33333]},"id":"4938","mass":"629","name":"Banten","nametype":"Valid","recclass":"CM2","reclat":"-6.333330","reclong":"106.000000","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.05,43.95]},"id":"4942","mass":"6400","name":"Barbotan","nametype":"Valid","recclass":"H5","reclat":"43.950000","reclong":"-0.050000","year":"1790-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[2.16667,41.36667]},"id":"4944","name":"Barcelona (stone)","nametype":"Valid","recclass":"OC","reclat":"41.366670","reclong":"2.166670","year":"1704-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-2.5,42.38333]},"id":"4946","mass":"3200","name":"Barea","nametype":"Valid","recclass":"Mesosiderite-A1","reclat":"42.383330","reclong":"-2.500000","year":"1842-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.08333,52.73333]},"id":"4947","mass":"23.2","name":"Barnaul","nametype":"Valid","recclass":"H5","reclat":"52.733330","reclong":"84.083330","year":"1904-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.1,52]},"id":"4948","mass":"17","name":"Barntrup","nametype":"Valid","recclass":"LL4","reclat":"52.000000","reclong":"9.100000","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.8,31.61667]},"id":"4949","mass":"4500","name":"Baroti","nametype":"Valid","recclass":"L6","reclat":"31.616670","reclong":"76.800000","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.33972,52.56528]},"id":"4954","mass":"44000","name":"Barwell","nametype":"Valid","recclass":"L5","reclat":"52.565280","reclong":"-1.339720","year":"1965-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-5.9,15.78333]},"id":"44876","mass":"29560","name":"Bassikounou","nametype":"Valid","recclass":"H5","reclat":"15.783330","reclong":"-5.900000","year":"2006-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[20.93583,52.03333]},"id":"4957","mass":"15500","name":"BaszkΓ³wka","nametype":"Valid","recclass":"L5","reclat":"52.033330","reclong":"20.935830","year":"1994-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"21",":@computed_region_nnqa_25f4":"662","fall":"Fell","geolocation":{"type":"Point","coordinates":[-98.31667,45.41667]},"id":"4974","mass":"21000","name":"Bath","nametype":"Valid","recclass":"H4","reclat":"45.416670","reclong":"-98.316670","year":"1892-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"36",":@computed_region_nnqa_25f4":"1921","fall":"Fell","geolocation":{"type":"Point","coordinates":[-83.75,38.25]},"id":"4975","mass":"86000","name":"Bath Furnace","nametype":"Valid","recclass":"L6","reclat":"38.250000","reclong":"-83.750000","year":"1902-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"10",":@computed_region_nnqa_25f4":"2397","fall":"Fell","geolocation":{"type":"Point","coordinates":[-117.18913,40.66813]},"id":"56133","mass":"2900","name":"Battle Mountain","nametype":"Valid","recclass":"L6","reclat":"40.668130","reclong":"-117.189130","year":"2012-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.18333,11.08333]},"id":"4976","mass":"1557","name":"Bawku","nametype":"Valid","recclass":"LL5","reclat":"11.083330","reclong":"-0.183330","year":"1989-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"2216","fall":"Fell","geolocation":{"type":"Point","coordinates":[-93.5,36.75]},"id":"4977","mass":"611","name":"Baxter","nametype":"Valid","recclass":"L6","reclat":"36.750000","reclong":"-93.500000","year":"1916-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1285","fall":"Fell","geolocation":{"type":"Point","coordinates":[-101.2,39.8]},"id":"4984","mass":"16000","name":"Beardsley","nametype":"Valid","recclass":"H5","reclat":"39.800000","reclong":"-101.200000","year":"1929-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-117.33333,51.16667]},"id":"4986","mass":"14000","name":"Beaver Creek","nametype":"Valid","recclass":"H5","reclat":"51.166670","reclong":"-117.333330","year":"1893-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-4.1,53.01667]},"id":"4993","mass":"794","name":"Beddgelert","nametype":"Valid","recclass":"H5","reclat":"53.016670","reclong":"-4.100000","year":"1949-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"1978","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96.46667,33.6]},"id":"5005","mass":"375","name":"Bells","nametype":"Valid","recclass":"C2-ung","reclat":"33.600000","reclong":"-96.466670","year":"1961-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-64.86667,-32.33333]},"id":"5009","name":"Belville","nametype":"Valid","recclass":"OC","reclat":"-32.333330","reclong":"-64.866670","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.91667,25.36667]},"id":"5011","mass":"3700","name":"Benares (a)","nametype":"Valid","recclass":"LL4","reclat":"25.366670","reclong":"82.916670","year":"1798-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8.15,32.25]},"id":"30443","mass":"25000","name":"Benguerir","nametype":"Valid","recclass":"LL6","reclat":"32.250000","reclong":"-8.150000","year":"2004-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.8,32.86667]},"id":"5018","mass":"19000","name":"Beni M'hira","nametype":"Valid","recclass":"L6","reclat":"32.866670","reclong":"10.800000","year":"2001-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"34",":@computed_region_nnqa_25f4":"1869","fall":"Fell","geolocation":{"type":"Point","coordinates":[-89.15,39.08333]},"id":"5021","mass":"1770.5","name":"Benld","nametype":"Valid","recclass":"H6","reclat":"39.083330","reclong":"-89.150000","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28.41667,-26.16667]},"id":"5023","mass":"3880","name":"Benoni","nametype":"Valid","recclass":"H6","reclat":"-26.166670","reclong":"28.416670","year":"1943-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7,30]},"id":"5024","mass":"45000","name":"Bensour","nametype":"Valid","recclass":"LL6","reclat":"30.000000","reclong":"-7.000000","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-67.55,45.95]},"id":"5026","mass":"2840","name":"Benton","nametype":"Valid","recclass":"LL6","reclat":"45.950000","reclong":"-67.550000","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-58.32833,-31.91]},"id":"48975","mass":"270","name":"Berduc","nametype":"Valid","recclass":"L6","reclat":"-31.910000","reclong":"-58.328330","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.65,11.65]},"id":"5028","mass":"18000","name":"BΓ©rΓ©ba","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"11.650000","reclong":"-3.650000","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.8,41.68333]},"id":"5029","mass":"1440","name":"Berlanguillas","nametype":"Valid","recclass":"L6","reclat":"41.683330","reclong":"-3.800000","year":"1811-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"9",":@computed_region_nnqa_25f4":"1072","fall":"Fell","geolocation":{"type":"Point","coordinates":[-105.02325,40.30583]},"id":"47355","mass":"960","name":"Berthoud","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"40.305830","reclong":"-105.023250","year":"2004-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"47",":@computed_region_nnqa_25f4":"2030","fall":"Fell","geolocation":{"type":"Point","coordinates":[-73.83333,42.53333]},"id":"5032","mass":"13.9","name":"Bethlehem","nametype":"Valid","recclass":"H","reclat":"42.533330","reclong":"-73.833330","year":"1859-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.23333,43.21667]},"id":"5034","mass":"2000","name":"Beuste","nametype":"Valid","recclass":"L5","reclat":"43.216670","reclong":"-0.233330","year":"1859-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.5,33.88333]},"id":"5035","mass":"1100","name":"Beyrout","nametype":"Valid","recclass":"LL3.8","reclat":"33.883330","reclong":"35.500000","year":"1921-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[74.83333,20.88333]},"id":"5037","mass":"18","name":"Bhagur","nametype":"Valid","recclass":"L6","reclat":"20.883330","reclong":"74.833330","year":"1877-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[73.11528,26.50833]},"id":"36591","mass":"678","name":"Bhawad","nametype":"Valid","recclass":"LL6","reclat":"26.508330","reclong":"73.115280","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[71.46667,20.83333]},"id":"5039","mass":"100","name":"Bherai","nametype":"Valid","recclass":"L6","reclat":"20.833330","reclong":"71.466670","year":"1893-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[90.65,22.68333]},"id":"5040","mass":"1047","name":"Bhola","nametype":"Valid","recclass":"LL3-6","reclat":"22.683330","reclong":"90.650000","year":"1940-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[86.9,22.08333]},"id":"5041","mass":"2500","name":"Bholghati","nametype":"Valid","recclass":"Howardite","reclat":"22.083330","reclong":"86.900000","year":"1905-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23.2,53.1]},"id":"5042","mass":"4000","name":"Bialystok","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"53.100000","reclong":"23.200000","year":"1827-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.16667,50.13333]},"id":"5043","mass":"1900","name":"Bielokrynitschie","nametype":"Valid","recclass":"H4","reclat":"50.133330","reclong":"27.166670","year":"1887-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.08333,12.45]},"id":"5045","mass":"25000","name":"Bilanga","nametype":"Valid","recclass":"Diogenite","reclat":"12.450000","reclong":"-0.083330","year":"1999-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.67639,-33.15639]},"id":"5051","mass":"488.1","name":"Binningup","nametype":"Valid","recclass":"H5","reclat":"-33.156390","reclong":"115.676390","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.3,13.76667]},"id":"5056","mass":"560","name":"Birni N'konni","nametype":"Valid","recclass":"H4","reclat":"13.766670","reclong":"5.300000","year":"1923-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"33",":@computed_region_nnqa_25f4":"657","fall":"Fell","geolocation":{"type":"Point","coordinates":[-80.28333,34.16667]},"id":"5059","mass":"6000","name":"Bishopville","nametype":"Valid","recclass":"Aubrite","reclat":"34.166670","reclong":"-80.283330","year":"1843-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.6,25.38333]},"id":"5060","mass":"1039","name":"Bishunpur","nametype":"Valid","recclass":"LL3.15","reclat":"25.383330","reclong":"82.600000","year":"1895-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.16667,49.78333]},"id":"5063","mass":"1850","name":"Bjelaja Zerkov","nametype":"Valid","recclass":"H6","reclat":"49.783330","reclong":"30.166670","year":"1796-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.8,60.4]},"id":"5064","mass":"330000","name":"BjurbΓΆle","nametype":"Valid","recclass":"L/LL4","reclat":"60.400000","reclong":"25.800000","year":"1899-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"48",":@computed_region_nnqa_25f4":"2495","fall":"Fell","geolocation":{"type":"Point","coordinates":[-78.08333,40.91667]},"id":"5065","mass":"705","name":"Black Moshannan Park","nametype":"Valid","recclass":"L5","reclat":"40.916670","reclong":"-78.083330","year":"1941-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"20",":@computed_region_nnqa_25f4":"2164","fall":"Fell","geolocation":{"type":"Point","coordinates":[-97.33333,36.83333]},"id":"5068","mass":"2381","name":"Blackwell","nametype":"Valid","recclass":"L5","reclat":"36.833330","reclong":"-97.333330","year":"1906-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"3063","fall":"Fell","geolocation":{"type":"Point","coordinates":[-98.83333,31.83333]},"id":"5071","mass":"5100","name":"Blanket","nametype":"Valid","recclass":"L6","reclat":"31.833330","reclong":"-98.833330","year":"1909-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.63333,49.36667]},"id":"5072","mass":"470","name":"Blansko","nametype":"Valid","recclass":"H6","reclat":"49.366670","reclong":"16.633330","year":"1833-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"34",":@computed_region_nnqa_25f4":"1795","fall":"Fell","geolocation":{"type":"Point","coordinates":[-89.00417,40.48]},"id":"5076","mass":"67.8","name":"Bloomington","nametype":"Valid","recclass":"LL6","reclat":"40.480000","reclong":"-89.004170","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.83333,33.83333]},"id":"5090","mass":"7500","name":"Bo Xian","nametype":"Valid","recclass":"LL3.9","reclat":"33.833330","reclong":"115.833330","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-102,23]},"id":"5093","mass":"56","name":"Bocas","nametype":"Valid","recclass":"L6","reclat":"23.000000","reclong":"-102.000000","year":"1804-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.7,12.5]},"id":"5097","mass":"8800","name":"Bogou","nametype":"Valid","recclass":"Iron, IAB-MG","reclat":"12.500000","reclong":"0.700000","year":"1962-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[131.63333,44.55]},"id":"5098","mass":"256000","name":"Boguslavka","nametype":"Valid","recclass":"Iron, IIAB","reclat":"44.550000","reclong":"131.633330","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.05,44.86667]},"id":"5110","mass":"1676","name":"Borgo San Donino","nametype":"Valid","recclass":"LL6","reclat":"44.866670","reclong":"10.050000","year":"1808-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.03333,21.95]},"id":"5111","mass":"8600","name":"Bori","nametype":"Valid","recclass":"L6","reclat":"21.950000","reclong":"78.033330","year":"1894-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[52.48333,54.23333]},"id":"5112","mass":"1342","name":"Boriskino","nametype":"Valid","recclass":"CM2","reclat":"54.233330","reclong":"52.483330","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[24.28333,48.15]},"id":"5113","mass":"7000","name":"Borkut","nametype":"Valid","recclass":"L5","reclat":"48.150000","reclong":"24.283330","year":"1852-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.86667,55.46667]},"id":"5114","mass":"500","name":"Borodino","nametype":"Valid","recclass":"H5","reclat":"55.466670","reclong":"35.866670","year":"1812-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.88333,51.33333]},"id":"5117","mass":"614","name":"Botschetschki","nametype":"Valid","recclass":"L4","reclat":"51.333330","reclong":"33.883330","year":"1823-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-11.3715,17.71067]},"id":"57168","mass":"190","name":"Boumdeid (2003)","nametype":"Valid","recclass":"L6","reclat":"17.710670","reclong":"-11.371500","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-11.34133,17.17493]},"id":"57167","mass":"3599","name":"Boumdeid (2011)","nametype":"Valid","recclass":"L6","reclat":"17.174930","reclong":"-11.341330","year":"2011-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.33333,54.56667]},"id":"5121","mass":"5460","name":"Bovedy","nametype":"Valid","recclass":"L3","reclat":"54.566670","reclong":"-6.333330","year":"1969-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"48",":@computed_region_nnqa_25f4":"2455","fall":"Fell","geolocation":{"type":"Point","coordinates":[-80.08333,40.5]},"id":"5128","mass":"762","name":"Bradford Woods","nametype":"Valid","recclass":"L","reclat":"40.500000","reclong":"-80.083330","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.3,50.6]},"id":"5133","mass":"39000","name":"Braunau","nametype":"Valid","recclass":"Iron, IIAB","reclat":"50.600000","reclong":"16.300000","year":"1847-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.18361,50.66694]},"id":"5134","mass":"1500","name":"Breitscheid","nametype":"Valid","recclass":"H5","reclat":"50.666940","reclong":"8.183610","year":"1956-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.1,53.4]},"id":"5135","mass":"7250","name":"BremervΓΆrde","nametype":"Valid","recclass":"H/L3.9","reclat":"53.400000","reclong":"9.100000","year":"1855-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[59.31667,52.13333]},"id":"5140","mass":"219","name":"Brient","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"52.133330","reclong":"59.316670","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-112.88333,53.9]},"id":"5156","mass":"303000","name":"Bruderheim","nametype":"Valid","recclass":"L6","reclat":"53.900000","reclong":"-112.883330","year":"1960-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[64.60035,39.77978]},"id":"30448","mass":"5300","name":"Bukhara","nametype":"Valid","recclass":"CV3","reclat":"39.779780","reclong":"64.600350","year":"2001-01-01T00:00:00.000"} -,{"fall":"Fell","id":"5163","mass":"2250","name":"Bulls Run","nametype":"Valid","recclass":"Iron?","year":"1964-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[129.19,-31.35]},"id":"48653","mass":"324","name":"Bunburra Rockhole","nametype":"Valid","recclass":"Eucrite","reclat":"-31.350000","reclong":"129.190000","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.58333,10.01667]},"id":"5165","mass":"357","name":"Bununu","nametype":"Valid","recclass":"Howardite","reclat":"10.016670","reclong":"9.583330","year":"1942-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[48,5]},"id":"5169","mass":"120000","name":"Bur-Gheluai","nametype":"Valid","recclass":"H5","reclat":"5.000000","reclong":"48.000000","year":"1919-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"36",":@computed_region_nnqa_25f4":"256","fall":"Fell","geolocation":{"type":"Point","coordinates":[-82.23722,37.62194]},"id":"5175","mass":"1504","name":"Burnwell","nametype":"Valid","recclass":"H4-an","reclat":"37.621940","reclong":"-82.237220","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.23333,40.2]},"id":"5177","mass":"25000","name":"Bursa","nametype":"Valid","recclass":"L6","reclat":"40.200000","reclong":"29.233330","year":"1946-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.78333,46.45]},"id":"5178","mass":"5000","name":"Buschhof","nametype":"Valid","recclass":"L6","reclat":"46.450000","reclong":"25.783330","year":"1863-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.83333,26.78333]},"id":"5181","mass":"1500","name":"Bustee","nametype":"Valid","recclass":"Aubrite","reclat":"26.783330","reclong":"82.833330","year":"1852-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.08333,27.08333]},"id":"5183","mass":"29000","name":"Butsura","nametype":"Valid","recclass":"H6","reclat":"27.083330","reclong":"84.083330","year":"1861-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-109.84817,52.996]},"id":"48654","mass":"41000","name":"Buzzard Coulee","nametype":"Valid","recclass":"H4","reclat":"52.996000","reclong":"-109.848170","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.16667,37.98333]},"id":"5185","mass":"25000","name":"Cabezo de Mayo","nametype":"Valid","recclass":"L/LL6","reclat":"37.983330","reclong":"-1.166670","year":"1870-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"15",":@computed_region_nnqa_25f4":"1029","fall":"Fell","geolocation":{"type":"Point","coordinates":[-93.5,35.5]},"id":"5186","mass":"48500","name":"Cabin Creek","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"35.500000","reclong":"-93.500000","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[20.33333,43.83889]},"id":"5187","mass":"212","name":"Cacak","nametype":"Valid","recclass":"OC","reclat":"43.838890","reclong":"20.333330","year":"1919-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-76.51,3.405]},"id":"45976","mass":"478","name":"Cali","nametype":"Valid","recclass":"H/L4","reclat":"3.405000","reclong":"-76.510000","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[122.33333,11.75]},"id":"5200","mass":"2400","name":"Calivo","nametype":"Valid","recclass":"Stone-uncl","reclat":"11.750000","reclong":"122.333330","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-40.16667,-7.03333]},"id":"5249","mass":"23680","name":"Campos Sales","nametype":"Valid","recclass":"L5","reclat":"-7.033330","reclong":"-40.166670","year":"1991-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.6,39.8]},"id":"5250","mass":"4000","name":"Γ‡anakkale","nametype":"Valid","recclass":"L6","reclat":"39.800000","reclong":"26.600000","year":"1964-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.66667,41.25]},"id":"5251","mass":"945","name":"CaΓ±ellas","nametype":"Valid","recclass":"H4","reclat":"41.250000","reclong":"1.666670","year":"1861-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-5.15,43.38333]},"id":"5252","mass":"34000","name":"Cangas de Onis","nametype":"Valid","recclass":"H5","reclat":"43.383330","reclong":"-5.150000","year":"1866-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"9",":@computed_region_nnqa_25f4":"1448","fall":"Fell","geolocation":{"type":"Point","coordinates":[-105.24139,38.47028]},"id":"5253","mass":"1400","name":"Canon City","nametype":"Valid","recclass":"H6","reclat":"38.470280","reclong":"-105.241390","year":"1973-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"2695","fall":"Fell","geolocation":{"type":"Point","coordinates":[-89.58333,37.26667]},"id":"5260","mass":"2300","name":"Cape Girardeau","nametype":"Valid","recclass":"H6","reclat":"37.266670","reclong":"-89.583330","year":"1846-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-64.55,-30.88333]},"id":"5264","mass":"750","name":"Capilla del Monte","nametype":"Valid","recclass":"H6","reclat":"-30.883330","reclong":"-64.550000","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-69.04389,-16.66444]},"id":"45817","mass":"342","name":"Carancas","nametype":"Valid","recclass":"H4-5","reclat":"-16.664440","reclong":"-69.043890","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27,38.5]},"id":"5265","mass":"8","name":"Caratash","nametype":"Valid","recclass":"LL6","reclat":"38.500000","reclong":"27.000000","year":"1902-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"648","fall":"Fell","geolocation":{"type":"Point","coordinates":[-78.06667,36.08333]},"id":"5291","mass":"7300","name":"Castalia","nametype":"Valid","recclass":"H5","reclat":"36.083330","reclong":"-78.066670","year":"1874-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.5,43.35]},"id":"5292","name":"Castel Berardenga","nametype":"Valid","recclass":"Stone-uncl","reclat":"43.350000","reclong":"11.500000","year":"1791-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"49",":@computed_region_nnqa_25f4":"414","fall":"Fell","geolocation":{"type":"Point","coordinates":[-68.75,44.38333]},"id":"5293","mass":"94","name":"Castine","nametype":"Valid","recclass":"L6","reclat":"44.383330","reclong":"-68.750000","year":"1848-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.2,39.8]},"id":"5295","mass":"15000","name":"Castrovillari","nametype":"Valid","recclass":"Stone-uncl","reclat":"39.800000","reclong":"16.200000","year":"1583-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"637","fall":"Fell","geolocation":{"type":"Point","coordinates":[-79.25,36.5]},"id":"5296","mass":"1360","name":"Caswell County","nametype":"Valid","recclass":"OC","reclat":"36.500000","reclong":"-79.250000","year":"1810-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-105.23333,26.46667]},"id":"5306","mass":"1025","name":"Ceniceros","nametype":"Valid","recclass":"L3.7","reclat":"26.466670","reclong":"-105.233330","year":"1988-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"21",":@computed_region_nnqa_25f4":"2684","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96.91667,43.2]},"id":"5307","mass":"45.6","name":"Centerville","nametype":"Valid","recclass":"H5","reclat":"43.200000","reclong":"-96.916670","year":"1956-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.3,45.08333]},"id":"5308","mass":"6460","name":"Cereseto","nametype":"Valid","recclass":"H5","reclat":"45.083330","reclong":"8.300000","year":"1840-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[109.31667,28.53333]},"id":"5313","mass":"3700","name":"Chadong","nametype":"Valid","recclass":"L6","reclat":"28.533330","reclong":"109.316670","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81.66667,25.36667]},"id":"5314","mass":"0.5","name":"Chail","nametype":"Valid","recclass":"H6","reclat":"25.366670","reclong":"81.666670","year":"1814-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.48333,25.85]},"id":"5315","mass":"8200","name":"Chainpur","nametype":"Valid","recclass":"LL3.4","reclat":"25.850000","reclong":"83.483330","year":"1907-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-58.05,-30.78333]},"id":"5316","mass":"18300","name":"Chajari","nametype":"Valid","recclass":"L5","reclat":"-30.783330","reclong":"-58.050000","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.01667,20.26667]},"id":"5320","mass":"8800","name":"Chandakapur","nametype":"Valid","recclass":"L5","reclat":"20.266670","reclong":"76.016670","year":"1838-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[79.05,27.28333]},"id":"5321","mass":"1100","name":"Chandpur","nametype":"Valid","recclass":"L6","reclat":"27.283330","reclong":"79.050000","year":"1885-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.75,29.08333]},"id":"5322","mass":"1810","name":"Changde","nametype":"Valid","recclass":"H5","reclat":"29.083330","reclong":"111.750000","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.05,46.68333]},"id":"5325","mass":"31500","name":"Chantonnay","nametype":"Valid","recclass":"L6","reclat":"46.683330","reclong":"1.050000","year":"1812-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"39",":@computed_region_nnqa_25f4":"2007","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87.33333,36.16667]},"id":"5328","mass":"4300","name":"Charlotte","nametype":"Valid","recclass":"Iron, IVA","reclat":"36.166670","reclong":"-87.333330","year":"1835-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.56667,47.93333]},"id":"5329","mass":"27000","name":"Charsonville","nametype":"Valid","recclass":"H6","reclat":"47.933330","reclong":"1.566670","year":"1810-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.5,29.48333]},"id":"5330","mass":"12000","name":"Charwallas","nametype":"Valid","recclass":"H6","reclat":"29.483330","reclong":"75.500000","year":"1834-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.36667,47.71667]},"id":"5331","mass":"4000","name":"Chassigny","nametype":"Valid","recclass":"Martian (chassignite)","reclat":"47.716670","reclong":"5.366670","year":"1815-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[2.91667,47.93333]},"id":"5332","mass":"30000","name":"ChΓ’teau-Renard","nametype":"Valid","recclass":"L6","reclat":"47.933330","reclong":"2.916670","year":"1841-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.46667,41.93333]},"id":"5334","mass":"2945","name":"Chaves","nametype":"Valid","recclass":"Howardite","reclat":"41.933330","reclong":"-7.466670","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[32.5,-3.66667]},"id":"5338","mass":"2936","name":"Chela","nametype":"Valid","recclass":"H4","reclat":"-3.666670","reclong":"32.500000","year":"1988-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[61.11667,54.81667]},"id":"57165","mass":"100000","name":"Chelyabinsk","nametype":"Valid","recclass":"LL5","reclat":"54.816670","reclong":"61.116670","year":"2013-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-5.01472,23.69639]},"id":"47347","mass":"100000","name":"Chergach ","nametype":"Valid","recclass":"H5","reclat":"23.696390","reclong":"-5.014720","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.1,53.7]},"id":"5339","mass":"6000","name":"Chernyi Bor","nametype":"Valid","recclass":"H4","reclat":"53.700000","reclong":"30.100000","year":"1964-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"33",":@computed_region_nnqa_25f4":"2582","fall":"Fell","geolocation":{"type":"Point","coordinates":[-81.88333,35.03333]},"id":"5340","mass":"8400","name":"Cherokee Springs","nametype":"Valid","recclass":"LL6","reclat":"35.033330","reclong":"-81.883330","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.81667,46.55]},"id":"5341","mass":"705","name":"Chervettaz","nametype":"Valid","recclass":"L5","reclat":"46.550000","reclong":"6.816670","year":"1901-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[34,50.83333]},"id":"5342","mass":"1700","name":"Chervony Kut","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"50.833330","reclong":"34.000000","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.5,14.5]},"id":"5344","mass":"72","name":"Chetrinahatti","nametype":"Valid","recclass":"Stone-uncl","reclat":"14.500000","reclong":"76.500000","year":"1880-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[101.63333,17.9]},"id":"5345","mass":"367","name":"Chiang Khan","nametype":"Valid","recclass":"H6","reclat":"17.900000","reclong":"101.633330","year":"1981-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"48",":@computed_region_nnqa_25f4":"2459","fall":"Fell","geolocation":{"type":"Point","coordinates":[-79.73333,40.93333]},"id":"5349","mass":"303","name":"Chicora","nametype":"Valid","recclass":"LL6","reclat":"40.933330","reclong":"-79.733330","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.395,-10.05944]},"id":"5355","mass":"3920","name":"Chisenga","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"-10.059440","reclong":"33.395000","year":"1988-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.96667,-17.35]},"id":"5356","name":"Chitado","nametype":"Valid","recclass":"L6","reclat":"-17.350000","reclong":"13.966670","year":"1966-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.97667,47.47083]},"id":"5357","mass":"4000","name":"Chitenay","nametype":"Valid","recclass":"L6","reclat":"47.470830","reclong":"0.976670","year":"1978-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[108.1,-6.95]},"id":"5364","mass":"1600","name":"Cilimus","nametype":"Valid","recclass":"L5","reclat":"-6.950000","reclong":"108.100000","year":"1979-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"31",":@computed_region_nnqa_25f4":"67","fall":"Fell","geolocation":{"type":"Point","coordinates":[-81.87278,32.1025]},"id":"5374","mass":"1455","name":"Claxton","nametype":"Valid","recclass":"L6","reclat":"32.102500","reclong":"-81.872780","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","id":"5383","mass":"48.6","name":"Clohars","nametype":"Valid","recclass":"L4","year":"1822-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"41",":@computed_region_nnqa_25f4":"877","fall":"Fell","geolocation":{"type":"Point","coordinates":[-90.28333,44.9]},"id":"5395","mass":"104000","name":"Colby (Wisconsin)","nametype":"Valid","recclass":"L6","reclat":"44.900000","reclong":"-90.283330","year":"1917-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[19.38333,-33.13333]},"id":"5397","mass":"5200","name":"Cold Bokkeveld","nametype":"Valid","recclass":"CM2","reclat":"-33.133330","reclong":"19.383330","year":"1838-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"50",":@computed_region_nnqa_25f4":"356","fall":"Fell","geolocation":{"type":"Point","coordinates":[-84.50778,43.76111]},"id":"5401","mass":"469","name":"Coleman","nametype":"Valid","recclass":"L6","reclat":"43.761110","reclong":"-84.507780","year":"1994-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.61667,42.53333]},"id":"5403","mass":"5000","name":"Collescipoli","nametype":"Valid","recclass":"H5","reclat":"42.533330","reclong":"12.616670","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-47.55,-19.85]},"id":"5418","mass":"20350","name":"Conquista","nametype":"Valid","recclass":"H4","reclat":"-19.850000","reclong":"-47.550000","year":"1965-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-100.86667,21.16667]},"id":"5451","mass":"1200","name":"Cosina","nametype":"Valid","recclass":"H5","reclat":"21.166670","reclong":"-100.866670","year":"1844-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.26667,10.2]},"id":"5465","mass":"1460","name":"Cranganore","nametype":"Valid","recclass":"L6","reclat":"10.200000","reclong":"76.266670","year":"1917-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"20",":@computed_region_nnqa_25f4":"2201","fall":"Fell","geolocation":{"type":"Point","coordinates":[-97.58333,35.95]},"id":"5470","mass":"78.400000000000006","name":"Crescent","nametype":"Valid","recclass":"CM2","reclat":"35.950000","reclong":"-97.583330","year":"1936-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.3,-27.7]},"id":"5474","mass":"3650","name":"Cronstad","nametype":"Valid","recclass":"H5","reclat":"-27.700000","reclong":"27.300000","year":"1877-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"2332","fall":"Fell","geolocation":{"type":"Point","coordinates":[-78.13333,35.63333]},"id":"5476","mass":"167","name":"Cross Roads","nametype":"Valid","recclass":"H5","reclat":"35.633330","reclong":"-78.133330","year":"1892-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.21667,54.61667]},"id":"5477","mass":"4255","name":"Crumlin","nametype":"Valid","recclass":"L5","reclat":"54.616670","reclong":"-6.216670","year":"1902-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"36",":@computed_region_nnqa_25f4":"1426","fall":"Fell","geolocation":{"type":"Point","coordinates":[-84.35,36.83333]},"id":"5496","mass":"17000","name":"Cumberland Falls","nametype":"Valid","recclass":"Aubrite","reclat":"36.833330","reclong":"-84.350000","year":"1919-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"36",":@computed_region_nnqa_25f4":"244","fall":"Fell","geolocation":{"type":"Point","coordinates":[-84.25,38.4]},"id":"5500","mass":"6000","name":"Cynthiana","nametype":"Valid","recclass":"L/LL4","reclat":"38.400000","reclong":"-84.250000","year":"1877-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.83333,35.61667]},"id":"5504","mass":"18000","name":"Dahmani","nametype":"Valid","recclass":"LL6","reclat":"35.616670","reclong":"8.833330","year":"1981-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.96667,26.91667]},"id":"5511","mass":"5650","name":"Dandapur","nametype":"Valid","recclass":"L6","reclat":"26.916670","reclong":"83.966670","year":"1878-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[24.56667,-28.2]},"id":"5513","mass":"1064","name":"Daniel's Kuil","nametype":"Valid","recclass":"EL6","reclat":"-28.200000","reclong":"24.566670","year":"1868-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"29",":@computed_region_nnqa_25f4":"103","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87.06667,34.4]},"id":"5514","mass":"2000","name":"Danville","nametype":"Valid","recclass":"L6","reclat":"34.400000","reclong":"-87.066670","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.65,49.86667]},"id":"6603","mass":"100","name":"Darmstadt","nametype":"Valid","recclass":"H5","reclat":"49.866670","reclong":"8.650000","year":"1804-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[59.685,41.98444]},"id":"6604","mass":"7000","name":"Dashoguz","nametype":"Valid","recclass":"H5","reclat":"41.984440","reclong":"59.685000","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-79.95756,-1.87089]},"id":"51559","mass":"6580","name":"Daule","nametype":"Valid","recclass":"L5","reclat":"-1.870890","reclong":"-79.957560","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-80,43]},"id":"6621","mass":"340","name":"De Cewsville","nametype":"Valid","recclass":"H6","reclat":"43.000000","reclong":"-80.000000","year":"1887-01-01T00:00:00.000"} -,{":@computed_region_nnqa_25f4":"2491","fall":"Fell","geolocation":{"type":"Point","coordinates":[-74,40.25]},"id":"6634","mass":"28","name":"Deal","nametype":"Valid","recclass":"L6","reclat":"40.250000","reclong":"-74.000000","year":"1829-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.25,28.56667]},"id":"6642","mass":"0.8","name":"Delhi","nametype":"Valid","recclass":"L5","reclat":"28.566670","reclong":"77.250000","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.76667,51.46667]},"id":"6649","mass":"16400","name":"Demina","nametype":"Valid","recclass":"L6","reclat":"51.466670","reclong":"84.766670","year":"1911-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"9",":@computed_region_nnqa_25f4":"1444","fall":"Fell","geolocation":{"type":"Point","coordinates":[-104.93056,39.7825]},"id":"6660","mass":"230","name":"Denver","nametype":"Valid","recclass":"L6","reclat":"39.782500","reclong":"-104.930560","year":"1967-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[93.86667,26.68333]},"id":"6664","mass":"12500","name":"Dergaon","nametype":"Valid","recclass":"H5","reclat":"26.683330","reclong":"93.866670","year":"2001-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[73.61667,25.73333]},"id":"6693","mass":"25400","name":"Desuri","nametype":"Valid","recclass":"H6","reclat":"25.733330","reclong":"73.616670","year":"1962-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81,19]},"id":"6694","mass":"12000","name":"Devgaon","nametype":"Valid","recclass":"H3.8","reclat":"19.000000","reclong":"81.000000","year":"2001-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.525,24.225]},"id":"6696","mass":"1140","name":"Devri-Khera","nametype":"Valid","recclass":"L6","reclat":"24.225000","reclong":"76.525000","year":"1994-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[71.42722,22.37778]},"id":"6698","mass":"45000","name":"Dhajala","nametype":"Valid","recclass":"H3.8","reclat":"22.377780","reclong":"71.427220","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.6,14.88333]},"id":"6699","mass":"1800","name":"Dharwar","nametype":"Valid","recclass":"OC","reclat":"14.883330","reclong":"75.600000","year":"1848-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.46667,32.23333]},"id":"7640","mass":"32000","name":"Dhurmsala","nametype":"Valid","recclass":"LL6","reclat":"32.233330","reclong":"76.466670","year":"1860-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.32997,37.35172]},"id":"47350","mass":"3396","name":"Didim","nametype":"Valid","recclass":"H3-5","reclat":"37.351720","reclong":"27.329970","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[18.56667,-33.75]},"id":"7642","mass":"1000","name":"Diep River","nametype":"Valid","recclass":"L6","reclat":"-33.750000","reclong":"18.566670","year":"1906-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-60.46667,-31.88333]},"id":"7649","mass":"400","name":"Distrito Quebracho","nametype":"Valid","recclass":"H4","reclat":"-31.883330","reclong":"-60.466670","year":"1957-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.5,-7.5]},"id":"7652","mass":"166000","name":"Djati-Pengilon","nametype":"Valid","recclass":"H6","reclat":"-7.500000","reclong":"111.500000","year":"1884-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.05,12.73333]},"id":"7656","mass":"3950","name":"Djermaia","nametype":"Valid","recclass":"H","reclat":"12.733330","reclong":"15.050000","year":"1961-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.55,36.95]},"id":"7657","mass":"10000","name":"Djoumine","nametype":"Valid","recclass":"H5-6","reclat":"36.950000","reclong":"9.550000","year":"1999-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[90.33333,23.5]},"id":"7658","mass":"3840","name":"Dokachi","nametype":"Valid","recclass":"H5","reclat":"23.500000","reclong":"90.333330","year":"1903-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.3,50.75]},"id":"7659","mass":"1600","name":"Dolgovoli","nametype":"Valid","recclass":"L6","reclat":"50.750000","reclong":"25.300000","year":"1864-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29,40]},"id":"7661","mass":"438","name":"Domanitch","nametype":"Valid","recclass":"L5","reclat":"40.000000","reclong":"29.000000","year":"1907-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[119.03333,45.5]},"id":"7706","mass":"128800","name":"Dong Ujimqin Qi","nametype":"Valid","recclass":"Mesosiderite","reclat":"45.500000","reclong":"119.033330","year":"1995-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.45,21.86667]},"id":"7707","mass":"230","name":"Donga Kohrod","nametype":"Valid","recclass":"H6","reclat":"21.866670","reclong":"82.450000","year":"1899-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[120.78333,32.91667]},"id":"7708","mass":"5500","name":"Dongtai","nametype":"Valid","recclass":"LL6","reclat":"32.916670","reclong":"120.783330","year":"1970-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[112.3,51.2]},"id":"7718","mass":"3891","name":"Doroninsk","nametype":"Valid","recclass":"H5-7","reclat":"51.200000","reclong":"112.300000","year":"1805-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.16667,13.05]},"id":"7722","mass":"1250","name":"Dosso","nametype":"Valid","recclass":"L6","reclat":"13.050000","reclong":"3.166670","year":"1962-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.3,32.33333]},"id":"7723","mass":"1161","name":"Douar Mghila","nametype":"Valid","recclass":"LL6","reclat":"32.333330","reclong":"-6.300000","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.91667,-13.66667]},"id":"7725","mass":"642","name":"Dowa","nametype":"Valid","recclass":"Stone-uncl","reclat":"-13.666670","reclong":"33.916670","year":"1976-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"39",":@computed_region_nnqa_25f4":"2115","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.5,36.4]},"id":"7728","mass":"5000","name":"Drake Creek","nametype":"Valid","recclass":"L6","reclat":"36.400000","reclong":"-86.500000","year":"1827-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-82.26,42.52]},"id":"7731","mass":"47700","name":"Dresden (Ontario)","nametype":"Valid","recclass":"H6","reclat":"42.520000","reclong":"-82.260000","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[18.44167,42.45833]},"id":"7736","mass":"1900","name":"Dubrovnik","nametype":"Valid","recclass":"L3-6","reclat":"42.458330","reclong":"18.441670","year":"1951-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[152.83333,-31.66667]},"id":"7743","mass":"30","name":"Dunbogan","nametype":"Valid","recclass":"L6","reclat":"-31.666670","reclong":"152.833330","year":"1999-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8.03333,52.55]},"id":"7745","mass":"2270","name":"Dundrum","nametype":"Valid","recclass":"H5","reclat":"52.550000","reclong":"-8.033330","year":"1865-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[128.25,43.33333]},"id":"7749","name":"Dunhua","nametype":"Valid","recclass":"Stone-uncl","reclat":"43.333330","reclong":"128.250000","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.63333,30.3]},"id":"7750","mass":"13200","name":"Durala","nametype":"Valid","recclass":"L6","reclat":"30.300000","reclong":"76.633330","year":"1815-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[39.5,-4]},"id":"7752","mass":"577","name":"Duruma","nametype":"Valid","recclass":"L6","reclat":"-4.000000","reclong":"39.500000","year":"1853-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[127.26667,33.43333]},"id":"7754","mass":"2117","name":"Duwun","nametype":"Valid","recclass":"L6","reclat":"33.433330","reclong":"127.266670","year":"1943-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.31667,-27.2]},"id":"7755","mass":"3230","name":"Dwaleni","nametype":"Valid","recclass":"H4-6","reclat":"-27.200000","reclong":"31.316670","year":"1970-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82,26.25]},"id":"7757","mass":"300","name":"Dyalpur","nametype":"Valid","recclass":"Ureilite","reclat":"26.250000","reclong":"82.000000","year":"1872-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[151,-3]},"id":"7758","mass":"188","name":"Dyarrl Island","nametype":"Valid","recclass":"Mesosiderite-A1","reclat":"-3.000000","reclong":"151.000000","year":"1933-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"19",":@computed_region_nnqa_25f4":"462","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96.47167,40.78167]},"id":"7760","mass":"10000","name":"Eagle","nametype":"Valid","recclass":"EL6","reclat":"40.781670","reclong":"-96.471670","year":"1947-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.83333,-17.3]},"id":"7774","mass":"2400","name":"Ehole","nametype":"Valid","recclass":"H5","reclat":"-17.300000","reclong":"15.833330","year":"1961-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.21667,48.9]},"id":"7775","mass":"3000","name":"EichstΓ€dt","nametype":"Valid","recclass":"H5","reclat":"48.900000","reclong":"11.216670","year":"1785-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13,56.03333]},"id":"7776","mass":"3336","name":"Ekeby","nametype":"Valid","recclass":"H4","reclat":"56.033330","reclong":"13.000000","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.78333,28.26667]},"id":"7777","mass":"840","name":"Ekh Khera","nametype":"Valid","recclass":"H6","reclat":"28.266670","reclong":"78.783330","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.25,34.41667]},"id":"7807","mass":"10000","name":"El Idrissia","nametype":"Valid","recclass":"L6","reclat":"34.416670","reclong":"3.250000","year":"1989-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-97.37,25.37]},"id":"45977","mass":"17226","name":"El Paso de Aguila","nametype":"Valid","recclass":"H5","reclat":"25.370000","reclong":"-97.370000","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.05167,19.96722]},"id":"7819","mass":"5000","name":"El Tigre","nametype":"Valid","recclass":"L6","reclat":"19.967220","reclong":"-103.051670","year":"1993-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"9",":@computed_region_nnqa_25f4":"88","fall":"Fell","geolocation":{"type":"Point","coordinates":[-104.58817,39.24667]},"id":"7822","mass":"680.5","name":"Elbert","nametype":"Valid","recclass":"LL6","reclat":"39.246670","reclong":"-104.588170","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.73333,50.18333]},"id":"7823","mass":"107000","name":"Elbogen","nametype":"Valid","recclass":"Iron, IID","reclat":"50.183330","reclong":"12.733330","year":"1400-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.66667,47.83333]},"id":"7824","mass":"54640","name":"Elenovka","nametype":"Valid","recclass":"L5","reclat":"47.833330","reclong":"37.666670","year":"1951-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4,51.75]},"id":"10019","mass":"1470","name":"Ellemeet","nametype":"Valid","recclass":"Diogenite","reclat":"51.750000","reclong":"4.000000","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[151.61667,-29.46667]},"id":"10033","mass":"127","name":"Emmaville","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"-29.466670","reclong":"151.616670","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[109.5,30.3]},"id":"10038","mass":"8000","name":"Enshi","nametype":"Valid","recclass":"H5","reclat":"30.300000","reclong":"109.500000","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.35,47.86667]},"id":"10039","mass":"127000","name":"Ensisheim","nametype":"Valid","recclass":"LL6","reclat":"47.866670","reclong":"7.350000","year":"1492-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.46667,48.18333]},"id":"10041","mass":"277","name":"Γ‰pinal","nametype":"Valid","recclass":"H5","reclat":"48.183330","reclong":"6.466670","year":"1822-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81.89167,19.03333]},"id":"10042","mass":"113","name":"Erakot","nametype":"Valid","recclass":"CM2","reclat":"19.033330","reclong":"81.891670","year":"1940-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[44.5,40.3]},"id":"10043","mass":"107.2","name":"Erevan","nametype":"Valid","recclass":"Howardite","reclat":"40.300000","reclong":"44.500000","year":"1911-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[44.16667,1.16667]},"id":"10044","mass":"20000","name":"Ergheo","nametype":"Valid","recclass":"L5","reclat":"1.166670","reclong":"44.166670","year":"1889-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.25,52.21667]},"id":"10049","mass":"2250","name":"Erxleben","nametype":"Valid","recclass":"H6","reclat":"52.216670","reclong":"11.250000","year":"1812-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.1,46.25]},"id":"10051","mass":"1500","name":"Esnandes","nametype":"Valid","recclass":"L6","reclat":"46.250000","reclong":"-1.100000","year":"1837-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.83333,2.88333]},"id":"10055","mass":"500","name":"Essebi","nametype":"Valid","recclass":"C2-ung","reclat":"2.883330","reclong":"30.833330","year":"1957-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"16",":@computed_region_nnqa_25f4":"277","fall":"Fell","geolocation":{"type":"Point","coordinates":[-94.83333,43.41667]},"id":"10059","mass":"320000","name":"Estherville","nametype":"Valid","recclass":"Mesosiderite-A3/4","reclat":"43.416670","reclong":"-94.833330","year":"1879-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1300","fall":"Fell","geolocation":{"type":"Point","coordinates":[-97.03333,39.75]},"id":"10074","mass":"89400","name":"Farmington","nametype":"Valid","recclass":"L5","reclat":"39.750000","reclong":"-97.033330","year":"1890-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"2439","fall":"Fell","geolocation":{"type":"Point","coordinates":[-77.53333,35.55]},"id":"10075","mass":"56000","name":"Farmville","nametype":"Valid","recclass":"H4","reclat":"35.550000","reclong":"-77.533330","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[2.81667,44.38333]},"id":"10078","mass":"1500","name":"Favars","nametype":"Valid","recclass":"H5","reclat":"44.383330","reclong":"2.816670","year":"1844-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"15",":@computed_region_nnqa_25f4":"70","fall":"Fell","geolocation":{"type":"Point","coordinates":[-94.16667,36.05]},"id":"10079","mass":"2360","name":"Fayetteville","nametype":"Valid","recclass":"H4","reclat":"36.050000","reclong":"-94.166670","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.45,36.88333]},"id":"10080","mass":"380","name":"Feid Chair","nametype":"Valid","recclass":"H4","reclat":"36.883330","reclong":"8.450000","year":"1875-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"29",":@computed_region_nnqa_25f4":"1631","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87.16667,32.53333]},"id":"10081","mass":"3200","name":"Felix","nametype":"Valid","recclass":"CO3.3","reclat":"32.533330","reclong":"-87.166670","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[116.75,34.6]},"id":"10086","mass":"82","name":"Fenghsien-Ku","nametype":"Valid","recclass":"H5","reclat":"34.600000","reclong":"116.750000","year":"1924-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"2331","fall":"Fell","geolocation":{"type":"Point","coordinates":[-81.41667,36.1]},"id":"10088","mass":"220","name":"Ferguson","nametype":"Valid","recclass":"OC","reclat":"36.100000","reclong":"-81.416670","year":"1889-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.75333,43.18111]},"id":"10091","mass":"10200","name":"Fermo","nametype":"Valid","recclass":"H3-5","reclat":"43.181110","reclong":"13.753330","year":"1996-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"1",":@computed_region_nnqa_25f4":"385","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96.85,47.81667]},"id":"10107","mass":"17600","name":"Fisher","nametype":"Valid","recclass":"L6","reclat":"47.816670","reclong":"-96.850000","year":"1894-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"807","fall":"Fell","geolocation":{"type":"Point","coordinates":[-97.76667,30.83333]},"id":"10111","mass":"3640","name":"Florence","nametype":"Valid","recclass":"H3","reclat":"30.833330","reclong":"-97.766670","year":"1922-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"16",":@computed_region_nnqa_25f4":"1785","fall":"Fell","geolocation":{"type":"Point","coordinates":[-93.66667,43.25]},"id":"10119","mass":"152000","name":"Forest City","nametype":"Valid","recclass":"H5","reclat":"43.250000","reclong":"-93.666670","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[146.85833,-33.35]},"id":"10120","mass":"26000","name":"Forest Vale","nametype":"Valid","recclass":"H4","reclat":"-33.350000","reclong":"146.858330","year":"1942-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"40",":@computed_region_nnqa_25f4":"2839","fall":"Fell","geolocation":{"type":"Point","coordinates":[-78.08333,36.78333]},"id":"10123","mass":"6067","name":"Forksville","nametype":"Valid","recclass":"L6","reclat":"36.783330","reclong":"-78.083330","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.31667,50.95]},"id":"10163","mass":"240","name":"Forsbach","nametype":"Valid","recclass":"H6","reclat":"50.950000","reclong":"7.316670","year":"1900-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"31",":@computed_region_nnqa_25f4":"1470","fall":"Fell","geolocation":{"type":"Point","coordinates":[-83.96667,33.01667]},"id":"10164","mass":"16300","name":"Forsyth","nametype":"Valid","recclass":"L6","reclat":"33.016670","reclong":"-83.966670","year":"1829-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7,28.25]},"id":"10166","name":"Fort Flatters","nametype":"Valid","recclass":"Stone-uncl","reclat":"28.250000","reclong":"7.000000","year":"1944-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"29",":@computed_region_nnqa_25f4":"99","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87.83333,34.48333]},"id":"10177","mass":"650","name":"Frankfort (stone)","nametype":"Valid","recclass":"Howardite","reclat":"34.483330","reclong":"-87.833330","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[113.56694,31.47556]},"id":"52412","mass":"23000","name":"Fuhe","nametype":"Valid","recclass":"L5","reclat":"31.475560","reclong":"113.566940","year":"1945-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[130.2,33.18333]},"id":"10836","mass":"11620","name":"Fukutomi","nametype":"Valid","recclass":"L5","reclat":"33.183330","reclong":"130.200000","year":"1882-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.33333,55.33333]},"id":"10838","name":"FΓΌnen","nametype":"Valid","recclass":"Stone-uncl","reclat":"55.333330","reclong":"10.333330","year":"1654-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[80.81667,25.95]},"id":"10839","mass":"4000","name":"Futtehpur","nametype":"Valid","recclass":"L6","reclat":"25.950000","reclong":"80.816670","year":"1822-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.9,32.9]},"id":"10840","mass":"2500","name":"Fuyang","nametype":"Valid","recclass":"Stone-uncl","reclat":"32.900000","reclong":"115.900000","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.4,44.3]},"id":"10846","mass":"132.69999999999999","name":"Galapian","nametype":"Valid","recclass":"H6","reclat":"44.300000","reclong":"0.400000","year":"1826-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.43333,7.05]},"id":"10848","mass":"36.1","name":"Galim (a)","nametype":"Valid","recclass":"LL6","reclat":"7.050000","reclong":"12.433330","year":"1952-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.43333,7.05]},"id":"10849","mass":"28","name":"Galim (b)","nametype":"Valid","recclass":"EH3/4-an","reclat":"7.050000","reclong":"12.433330","year":"1952-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.78333,51.68333]},"id":"10850","mass":"5000","name":"Galkiv","nametype":"Valid","recclass":"H4","reclat":"51.683330","reclong":"30.783330","year":"1995-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[68.53333,27.35]},"id":"10851","mass":"6400","name":"Gambat","nametype":"Valid","recclass":"L6","reclat":"27.350000","reclong":"68.533330","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-2.18333,11.65]},"id":"10854","name":"Gao-Guenie","nametype":"Valid","recclass":"H5","reclat":"11.650000","reclong":"-2.183330","year":"1960-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[68.53333,27.88333]},"id":"10860","mass":"380","name":"Garhi Yasin","nametype":"Valid","recclass":"Iron, IIE","reclat":"27.883330","reclong":"68.533330","year":"1917-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"13",":@computed_region_nnqa_25f4":"2985","fall":"Fell","geolocation":{"type":"Point","coordinates":[-112.13333,41.68333]},"id":"10861","mass":"102","name":"Garland","nametype":"Valid","recclass":"Diogenite-pm","reclat":"41.683330","reclong":"-112.133330","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.03333,12.85]},"id":"44882","mass":"4162","name":"Gashua","nametype":"Valid","recclass":"L6","reclat":"12.850000","reclong":"11.033330","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-2.04167,14.15083]},"id":"10866","name":"Gasseltepaoua","nametype":"Valid","recclass":"H5","reclat":"14.150830","reclong":"-2.041670","year":"2000-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.91667,12.91667]},"id":"10870","mass":"725","name":"Geidam","nametype":"Valid","recclass":"H5","reclat":"12.916670","reclong":"11.916670","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.88333,35.53333]},"id":"10914","mass":"14290","name":"Gifu","nametype":"Valid","recclass":"L6","reclat":"35.533330","reclong":"136.883330","year":"1909-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.56667,37.31667]},"id":"10917","mass":"18000","name":"Girgenti","nametype":"Valid","recclass":"L6","reclat":"37.316670","reclong":"13.566670","year":"1853-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.91667,9.6]},"id":"10919","mass":"480","name":"Git-Git","nametype":"Valid","recclass":"L6","reclat":"9.600000","reclong":"9.916670","year":"1947-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.86667,52.2]},"id":"10923","mass":"670","name":"Glanerbrug","nametype":"Valid","recclass":"L/LL5","reclat":"52.200000","reclong":"6.866670","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[107.7,-7.25]},"id":"10924","mass":"1303","name":"Glanggang","nametype":"Valid","recclass":"H5-6","reclat":"-7.250000","reclong":"107.700000","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.61667,57.35]},"id":"10926","mass":"152000","name":"Glasatovo","nametype":"Valid","recclass":"H4","reclat":"57.350000","reclong":"37.616670","year":"1918-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.3,52.45972]},"id":"10930","mass":"767","name":"Glatton","nametype":"Valid","recclass":"L6","reclat":"52.459720","reclong":"-0.300000","year":"1991-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.76667,50.66667]},"id":"10936","mass":"1750","name":"Gnadenfrei","nametype":"Valid","recclass":"H5","reclat":"50.666670","reclong":"16.766670","year":"1879-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[89.05,24.23333]},"id":"10948","mass":"1600","name":"Gopalpur","nametype":"Valid","recclass":"H6","reclat":"24.233330","reclong":"89.050000","year":"1865-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[38.08333,48.28333]},"id":"10949","mass":"3618","name":"Gorlovka","nametype":"Valid","recclass":"H3.7","reclat":"48.283330","reclong":"38.083330","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[2.25,42.9]},"id":"10956","mass":"9000","name":"Granes","nametype":"Valid","recclass":"L6","reclat":"42.900000","reclong":"2.250000","year":"1964-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11,60.66667]},"id":"11196","mass":"45.5","name":"Grefsheim","nametype":"Valid","recclass":"L5","reclat":"60.666670","reclong":"11.000000","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-79.61667,43.2]},"id":"50911","mass":"215","name":"Grimsby","nametype":"Valid","recclass":"H5","reclat":"43.200000","reclong":"-79.616670","year":"2009-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[45.38333,43.66667]},"id":"11206","mass":"3500","name":"Grosnaja","nametype":"Valid","recclass":"CV3","reclat":"43.666670","reclong":"45.383330","year":"1861-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[18.71667,49.26667]},"id":"11207","mass":"10500","name":"Gross-Divina","nametype":"Valid","recclass":"H5","reclat":"49.266670","reclong":"18.716670","year":"1837-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.58333,46.35]},"id":"11208","mass":"8000","name":"Grossliebenthal","nametype":"Valid","recclass":"L6","reclat":"46.350000","reclong":"30.583330","year":"1881-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.5,51.93333]},"id":"11426","mass":"1000","name":"GrΓΌneberg","nametype":"Valid","recclass":"H4","reclat":"51.933330","reclong":"15.500000","year":"1841-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.63333,52.86667]},"id":"11429","mass":"690","name":"Grzempach","nametype":"Valid","recclass":"H5","reclat":"52.866670","reclong":"16.633330","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-58.61667,-33]},"id":"11432","mass":"22000","name":"GualeguaychΓΊ","nametype":"Valid","recclass":"H6","reclat":"-33.000000","reclong":"-58.616670","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[122.76389,39.80417]},"id":"11435","mass":"2910","name":"Guangmingshan","nametype":"Valid","recclass":"H5","reclat":"39.804170","reclong":"122.763890","year":"1996-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[105,24.1]},"id":"11436","name":"Guangnan","nametype":"Valid","recclass":"L6","reclat":"24.100000","reclong":"105.000000","year":"1983-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[118.4,37.1]},"id":"11437","mass":"1900","name":"Guangrao","nametype":"Valid","recclass":"L6","reclat":"37.100000","reclong":"118.400000","year":"1980-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.01667,38.73333]},"id":"11439","mass":"39000","name":"GuareΓ±a","nametype":"Valid","recclass":"H6","reclat":"38.733330","reclong":"-6.016670","year":"1892-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[20.23333,43.76667]},"id":"11440","mass":"1915","name":"GuΓͺa","nametype":"Valid","recclass":"Stone-uncl","reclat":"43.766670","reclong":"20.233330","year":"1891-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.68333,13.5]},"id":"11442","mass":"288","name":"Guibga","nametype":"Valid","recclass":"L5","reclat":"13.500000","reclong":"-0.683330","year":"1972-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.98333,9.91667]},"id":"11443","mass":"968","name":"Guidder","nametype":"Valid","recclass":"LL5","reclat":"9.916670","reclong":"13.983330","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.05,22.98333]},"id":"11448","mass":"2449","name":"Gujargaon","nametype":"Valid","recclass":"H5","reclat":"22.983330","reclong":"76.050000","year":"1982-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.65833,11.49167]},"id":"11449","mass":"100000","name":"Gujba","nametype":"Valid","recclass":"CBa","reclat":"11.491670","reclong":"11.658330","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[24.7,42.9]},"id":"11450","mass":"5700","name":"Gumoschnik","nametype":"Valid","recclass":"H5","reclat":"42.900000","reclong":"24.700000","year":"1904-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.56667,13.78333]},"id":"11464","mass":"28","name":"Gurram Konda","nametype":"Valid","recclass":"L6","reclat":"13.783330","reclong":"78.566670","year":"1814-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[42.41667,9.36667]},"id":"11465","mass":"34650","name":"Gursum","nametype":"Valid","recclass":"H4/5","reclat":"9.366670","reclong":"42.416670","year":"1981-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.38333,51.91667]},"id":"11466","mass":"1000","name":"GΓΌtersloh","nametype":"Valid","recclass":"H3/4","reclat":"51.916670","reclong":"8.383330","year":"1851-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[127.5,35]},"id":"11467","mass":"1320","name":"Gyokukei","nametype":"Valid","recclass":"OC","reclat":"35.000000","reclong":"127.500000","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[139.33333,35.65]},"id":"11468","mass":"0.2","name":"Hachi-oji","nametype":"Valid","recclass":"H?","reclat":"35.650000","reclong":"139.333330","year":"1817-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.73333,50.31667]},"id":"11472","mass":"9000","name":"Hainaut","nametype":"Valid","recclass":"H3-6","reclat":"50.316670","reclong":"3.733330","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.23333,57.81667]},"id":"11479","mass":"1456","name":"Hallingeberg","nametype":"Valid","recclass":"L3.4","reclat":"57.816670","reclong":"16.233330","year":"1944-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"35",":@computed_region_nnqa_25f4":"1205","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.6,41.38333]},"id":"11485","mass":"3710","name":"Hamlet","nametype":"Valid","recclass":"LL4","reclat":"41.383330","reclong":"-86.600000","year":"1959-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.53333,26.8]},"id":"11824","mass":"1000","name":"Haraiya","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"26.800000","reclong":"82.533330","year":"1878-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.78333,28.38333]},"id":"11829","mass":"315","name":"Haripura","nametype":"Valid","recclass":"CM2","reclat":"28.383330","reclong":"75.783330","year":"1921-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"2025","fall":"Fell","geolocation":{"type":"Point","coordinates":[-94.51167,32.675]},"id":"11830","mass":"8360","name":"Harleton","nametype":"Valid","recclass":"L6","reclat":"32.675000","reclong":"-94.511670","year":"1961-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"35",":@computed_region_nnqa_25f4":"1855","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.16667,38.25]},"id":"11842","mass":"680","name":"Harrison County","nametype":"Valid","recclass":"L6","reclat":"38.250000","reclong":"-86.166670","year":"1859-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.70033,35.2945]},"id":"11848","mass":"1110.5999999999999","name":"Hashima","nametype":"Valid","recclass":"H4","reclat":"35.294500","reclong":"136.700330","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.81667,28.95]},"id":"11852","mass":"1250","name":"Hassi-Jekna","nametype":"Valid","recclass":"Iron, IAB-sHL","reclat":"28.950000","reclong":"0.816670","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.51667,51.65]},"id":"11855","mass":"29000","name":"Hatford","nametype":"Valid","recclass":"Stone-uncl","reclat":"51.650000","reclong":"-1.516670","year":"1628-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.06194,60.24556]},"id":"11859","mass":"1544","name":"HaverΓΆ","nametype":"Valid","recclass":"Ureilite","reclat":"60.245560","reclong":"22.061940","year":"1971-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.78333,55.46667]},"id":"11869","mass":"3500","name":"Hedeskoga","nametype":"Valid","recclass":"H5","reclat":"55.466670","reclong":"13.783330","year":"1922-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.66667,27.33333]},"id":"11870","mass":"6100","name":"Hedjaz","nametype":"Valid","recclass":"L3.7-6","reclat":"27.333330","reclong":"35.666670","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-84.1,10]},"id":"11875","mass":"1000","name":"Heredia","nametype":"Valid","recclass":"H5","reclat":"10.000000","reclong":"-84.100000","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[17.66667,59.85]},"id":"11878","mass":"20000","name":"Hessle","nametype":"Valid","recclass":"H5","reclat":"59.850000","reclong":"17.666670","year":"1869-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[130.43333,33.6]},"id":"11883","mass":"750","name":"Higashi-koen","nametype":"Valid","recclass":"H5","reclat":"33.600000","reclong":"130.433330","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-4.23333,55.9]},"id":"11884","mass":"4500","name":"High Possil","nametype":"Valid","recclass":"L6","reclat":"55.900000","reclong":"-4.233330","year":"1804-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[132.38333,34.45]},"id":"11889","mass":"414","name":"Hiroshima","nametype":"Valid","recclass":"H5","reclat":"34.450000","reclong":"132.383330","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.47278,1.345]},"id":"44714","mass":"167.7","name":"Hoima","nametype":"Valid","recclass":"H6","reclat":"1.345000","reclong":"31.472780","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.2,64.43333]},"id":"11893","mass":"305.5","name":"HΓΆkmark","nametype":"Valid","recclass":"L4","reclat":"64.433330","reclong":"21.200000","year":"1954-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"7",":@computed_region_nnqa_25f4":"990","fall":"Fell","geolocation":{"type":"Point","coordinates":[-110.18333,34.9]},"id":"11894","mass":"220000","name":"Holbrook","nametype":"Valid","recclass":"L/LL6","reclat":"34.900000","reclong":"-110.183330","year":"1912-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[38.41667,9.06667]},"id":"11895","mass":"1415","name":"Holetta","nametype":"Valid","recclass":"Stone-uncl","reclat":"9.066670","reclong":"38.416670","year":"1923-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"16",":@computed_region_nnqa_25f4":"284","fall":"Fell","geolocation":{"type":"Point","coordinates":[-91.86667,41.8]},"id":"11901","mass":"230000","name":"Homestead","nametype":"Valid","recclass":"L5","reclat":"41.800000","reclong":"-91.866670","year":"1875-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"4",":@computed_region_nnqa_25f4":"1657","fall":"Fell","geolocation":{"type":"Point","coordinates":[-157.86667,21.3]},"id":"11904","mass":"2420","name":"Honolulu","nametype":"Valid","recclass":"L5","reclat":"21.300000","reclong":"-157.866670","year":"1825-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.5,35.66667]},"id":"11913","mass":"180","name":"Hotse","nametype":"Valid","recclass":"L6","reclat":"35.666670","reclong":"115.500000","year":"1956-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1293","fall":"Fell","geolocation":{"type":"Point","coordinates":[-100.45,39.35]},"id":"11915","mass":"266.10000000000002","name":"Hoxie","nametype":"Valid","recclass":"OC","reclat":"39.350000","reclong":"-100.450000","year":"1963-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.33333,46.1]},"id":"11916","mass":"49000","name":"Hraschina","nametype":"Valid","recclass":"Iron, IID","reclat":"46.100000","reclong":"16.333330","year":"1751-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[106.63241,26.46469]},"id":"54719","mass":"1600","name":"Huaxi","nametype":"Valid","recclass":"H5","reclat":"26.464690","reclong":"106.632410","year":"2010-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.91667,50.3]},"id":"11986","mass":"112","name":"Hungen","nametype":"Valid","recclass":"H6","reclat":"50.300000","reclong":"8.916670","year":"1877-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.68333,61.18333]},"id":"11989","mass":"14000","name":"Hvittis","nametype":"Valid","recclass":"EL6","reclat":"61.183330","reclong":"22.683330","year":"1901-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.7,52.28333]},"id":"11992","mass":"2000","name":"IbbenbΓΌren","nametype":"Valid","recclass":"Diogenite","reclat":"52.283330","reclong":"7.700000","year":"1870-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-45,-20]},"id":"11993","mass":"2500","name":"Ibitira","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"-20.000000","reclong":"-45.000000","year":"1957-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35,38]},"id":"11994","name":"Ibrisim","nametype":"Valid","recclass":"OC","reclat":"38.000000","reclong":"35.000000","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.93333,58.2]},"id":"11995","mass":"3973","name":"Ichkala","nametype":"Valid","recclass":"H6","reclat":"58.200000","reclong":"82.933330","year":"1936-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28.33333,-32.1]},"id":"12000","mass":"3457","name":"Idutywa","nametype":"Valid","recclass":"H5","reclat":"-32.100000","reclong":"28.333330","year":"1956-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-51.83333,-23.2]},"id":"12003","mass":"1200","name":"Iguaracu","nametype":"Valid","recclass":"H5","reclat":"-23.200000","reclong":"-51.833330","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[145.36667,-6.03333]},"id":"12004","mass":"7330","name":"Ijopega","nametype":"Valid","recclass":"H6","reclat":"-6.033330","reclong":"145.366670","year":"1975-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[46.66667,39.75]},"id":"12027","mass":"27000","name":"Indarch","nametype":"Valid","recclass":"EH4","reclat":"39.750000","reclong":"46.666670","year":"1891-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"525","fall":"Fell","geolocation":{"type":"Point","coordinates":[-94.4,39.08333]},"id":"12028","mass":"880","name":"Independence","nametype":"Valid","recclass":"L6","reclat":"39.083330","reclong":"-94.400000","year":"1917-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[112,41]},"id":"12037","mass":"3000","name":"Inner Mongolia","nametype":"Valid","recclass":"L6","reclat":"41.000000","reclong":"112.000000","year":"1963-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-111.3375,53.415]},"id":"12039","mass":"4576","name":"Innisfree","nametype":"Valid","recclass":"L5","reclat":"53.415000","reclong":"-111.337500","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-54.5,-25.5]},"id":"12043","mass":"7000","name":"Ipiranga","nametype":"Valid","recclass":"H6","reclat":"-25.500000","reclong":"-54.500000","year":"1972-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.8,-8.93333]},"id":"12049","mass":"1300","name":"Ishinga","nametype":"Valid","recclass":"H","reclat":"-8.933330","reclong":"33.800000","year":"1954-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-57.95,-31.18333]},"id":"12053","mass":"3050","name":"Isthilart","nametype":"Valid","recclass":"H5","reclat":"-31.183330","reclong":"-57.950000","year":"1928-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-44.33333,-3.4]},"id":"12056","mass":"2024","name":"Itapicuru-Mirim","nametype":"Valid","recclass":"H5","reclat":"-3.400000","reclong":"-44.333330","year":"1879-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-12.95217,26.59083]},"id":"12058","mass":"4720","name":"Itqiy","nametype":"Valid","recclass":"EH7-an","reclat":"26.590830","reclong":"-12.952170","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[32.43333,-8.41667]},"id":"12063","mass":"704.5","name":"Ivuna","nametype":"Valid","recclass":"CI1","reclat":"-8.416670","reclong":"32.433330","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.9,-32.5]},"id":"12065","mass":"48000","name":"Jackalsfontein","nametype":"Valid","recclass":"L6","reclat":"-32.500000","reclong":"21.900000","year":"1903-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[68.41667,26.75]},"id":"12067","mass":"973","name":"Jajh deh Kot Lalu","nametype":"Valid","recclass":"EL6","reclat":"26.750000","reclong":"68.416670","year":"1926-01-01T00:00:00.000"} -,{"fall":"Fell","id":"12068","mass":"700","name":"Jalanash","nametype":"Valid","recclass":"Ureilite","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75,31]},"id":"12069","mass":"1967","name":"Jalandhar","nametype":"Valid","recclass":"Iron","reclat":"31.000000","reclong":"75.000000","year":"1621-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.33333,18.75]},"id":"12072","mass":"22","name":"Jamkheir","nametype":"Valid","recclass":"H6","reclat":"18.750000","reclong":"75.333330","year":"1866-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[105.8,39.7]},"id":"12074","mass":"20500","name":"Jartai","nametype":"Valid","recclass":"L6","reclat":"39.700000","reclong":"105.800000","year":"1979-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[20.44167,43.83333]},"id":"12078","mass":"34000","name":"Jelica","nametype":"Valid","recclass":"LL6","reclat":"43.833330","reclong":"20.441670","year":"1889-01-01T00:00:00.000"} -,{"fall":"Fell","id":"12079","mass":"450","name":"Jemlapur","nametype":"Valid","recclass":"L6","year":"1901-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.05217,46.42137]},"id":"51589","mass":"3667","name":"Jesenice","nametype":"Valid","recclass":"L6","reclat":"46.421370","reclong":"14.052170","year":"2009-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[72.38333,31.3]},"id":"12085","mass":"5900","name":"Jhung","nametype":"Valid","recclass":"L5","reclat":"31.300000","reclong":"72.383330","year":"1873-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[104.91667,31.91667]},"id":"12086","mass":"222","name":"Jiange","nametype":"Valid","recclass":"H5","reclat":"31.916670","reclong":"104.916670","year":"1964-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[109.5,30.80833]},"id":"12087","mass":"600000","name":"Jianshi","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"30.808330","reclong":"109.500000","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[126.16667,44.05]},"id":"12171","mass":"4000000","name":"Jilin","nametype":"Valid","recclass":"H5","reclat":"44.050000","reclong":"126.166670","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[70.31333,22.68]},"id":"47362","mass":"100","name":"Jodiya","nametype":"Valid","recclass":"L5","reclat":"22.680000","reclong":"70.313330","year":"2006-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[24.4,55.7]},"id":"12173","mass":"30","name":"Jodzie","nametype":"Valid","recclass":"Howardite","reclat":"55.700000","reclong":"24.400000","year":"1877-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"9",":@computed_region_nnqa_25f4":"1072","fall":"Fell","geolocation":{"type":"Point","coordinates":[-104.9,40.35]},"id":"12198","mass":"40300","name":"Johnstown","nametype":"Valid","recclass":"Diogenite","reclat":"40.350000","reclong":"-104.900000","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.83333,-11.85]},"id":"12199","mass":"483","name":"Jolomba","nametype":"Valid","recclass":"LL6","reclat":"-11.850000","reclong":"15.833330","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.45,45.43333]},"id":"12202","mass":"5000","name":"Jonzac","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"45.433330","reclong":"-0.450000","year":"1819-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.41667,35.5]},"id":"12203","mass":"100000","name":"Juancheng","nametype":"Valid","recclass":"H5","reclat":"35.500000","reclong":"115.416670","year":"1997-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.8,12.85]},"id":"12207","mass":"680","name":"Judesegeri","nametype":"Valid","recclass":"H6","reclat":"12.850000","reclong":"76.800000","year":"1876-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.2,-7.71667]},"id":"12209","mass":"32490","name":"Jumapalo","nametype":"Valid","recclass":"L6","reclat":"-7.716670","reclong":"111.200000","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[118.8,35.2]},"id":"12210","mass":"950","name":"Junan","nametype":"Valid","recclass":"L6","reclat":"35.200000","reclong":"118.800000","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.27,38.74028]},"id":"12213","mass":"25250","name":"Juromenha","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"38.740280","reclong":"-7.270000","year":"1968-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4.3,44.71667]},"id":"12214","mass":"91000","name":"Juvinas","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"44.716670","reclong":"4.300000","year":"1821-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.3,47.35]},"id":"12218","mass":"3000","name":"Kaba","nametype":"Valid","recclass":"CV3","reclat":"47.350000","reclong":"21.300000","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.21667,11.85]},"id":"12220","mass":"13400","name":"Kabo","nametype":"Valid","recclass":"H4","reclat":"11.850000","reclong":"8.216670","year":"1971-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.33333,27.08333]},"id":"12221","mass":"89","name":"Kadonah","nametype":"Valid","recclass":"H6","reclat":"27.083330","reclong":"78.333330","year":"1822-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[79.96667,27.25]},"id":"12222","mass":"230","name":"Kaee","nametype":"Valid","recclass":"H5","reclat":"27.250000","reclong":"79.966670","year":"1838-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.83333,49.86667]},"id":"12227","mass":"1900","name":"Kagarlyk","nametype":"Valid","recclass":"L6","reclat":"49.866670","reclong":"30.833330","year":"1908-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[48.3,15]},"id":"12228","mass":"2000","name":"Kaidun","nametype":"Valid","recclass":"CR2","reclat":"15.000000","reclong":"48.300000","year":"1980-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[53.25,55.43333]},"id":"12229","mass":"200000","name":"Kainsaz","nametype":"Valid","recclass":"CO3.2","reclat":"55.433330","reclong":"53.250000","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.51667,12.38333]},"id":"12230","mass":"350","name":"Kakangari","nametype":"Valid","recclass":"K3","reclat":"12.383330","reclong":"78.516670","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.66667,45.13333]},"id":"12231","mass":"577","name":"Kakowa","nametype":"Valid","recclass":"L6","reclat":"45.133330","reclong":"21.666670","year":"1858-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.5,-6.83333]},"id":"12232","mass":"950","name":"Kalaba","nametype":"Valid","recclass":"H4","reclat":"-6.833330","reclong":"29.500000","year":"1951-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[73.98333,17.83333]},"id":"12236","mass":"4500","name":"Kalumbi","nametype":"Valid","recclass":"L6","reclat":"17.833330","reclong":"73.983330","year":"1879-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81.46667,26.03333]},"id":"12238","mass":"2770","name":"Kamalpur","nametype":"Valid","recclass":"L6","reclat":"26.033330","reclong":"81.466670","year":"1942-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[139.95667,36.04167]},"id":"12240","mass":"448","name":"Kamiomi","nametype":"Valid","recclass":"H5","reclat":"36.041670","reclong":"139.956670","year":"1913-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.8,14.18333]},"id":"12241","mass":"1293","name":"Kamsagar","nametype":"Valid","recclass":"L6","reclat":"14.183330","reclong":"75.800000","year":"1902-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[65.78333,31.6]},"id":"12243","mass":"299","name":"Kandahar (Afghanistan)","nametype":"Valid","recclass":"L6","reclat":"31.600000","reclong":"65.783330","year":"1959-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.5,-7]},"id":"12245","mass":"1630","name":"Kangean","nametype":"Valid","recclass":"H5","reclat":"-7.000000","reclong":"115.500000","year":"1908-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.3,32.08333]},"id":"12246","mass":"400","name":"Kangra Valley","nametype":"Valid","recclass":"H5","reclat":"32.083330","reclong":"76.300000","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.63333,4.7]},"id":"12251","mass":"11355","name":"Kapoeta","nametype":"Valid","recclass":"Howardite","reclat":"4.700000","reclong":"33.633330","year":"1942-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[73.22329,20.33916]},"id":"47357","mass":"1600","name":"Kaprada","nametype":"Valid","recclass":"L5/6","reclat":"20.339160","reclong":"73.223290","year":"2004-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[73.36667,42.45]},"id":"12253","mass":"3500","name":"Kaptal-Aryk","nametype":"Valid","recclass":"L6","reclat":"42.450000","reclong":"73.366670","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81.01667,47.21667]},"id":"12256","mass":"3000","name":"Karakol","nametype":"Valid","recclass":"LL6","reclat":"47.216670","reclong":"81.016670","year":"1840-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.58333,-3.5]},"id":"12258","mass":"2220","name":"Karatu","nametype":"Valid","recclass":"LL6","reclat":"-3.500000","reclong":"35.583330","year":"1963-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.15,12.9]},"id":"12260","mass":"180","name":"Karewar","nametype":"Valid","recclass":"L6","reclat":"12.900000","reclong":"7.150000","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[67.16667,27.8]},"id":"12262","mass":"22000","name":"Karkh","nametype":"Valid","recclass":"L6","reclat":"27.800000","reclong":"67.166670","year":"1905-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[71.6,31.58333]},"id":"12263","mass":"2950","name":"Karloowala","nametype":"Valid","recclass":"L6","reclat":"31.583330","reclong":"71.600000","year":"1955-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[139.91667,-35.08333]},"id":"12264","mass":"41730","name":"Karoonda","nametype":"Valid","recclass":"CK4","reclat":"-35.083330","reclong":"139.916670","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.76667,35.36667]},"id":"12266","mass":"710","name":"Kasamatsu","nametype":"Valid","recclass":"H","reclat":"35.366670","reclong":"136.766670","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.58333,29.58333]},"id":"30740","mass":"16820","name":"Kasauli","nametype":"Valid","recclass":"H4","reclat":"29.583330","reclong":"77.583330","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.08333,11.33333]},"id":"35465","mass":"1500","name":"Katagum","nametype":"Valid","recclass":"L6","reclat":"11.333330","reclong":"10.083330","year":"1999-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.81333,25.14333]},"id":"47351","mass":"6800","name":"Kavarpura","nametype":"Valid","recclass":"Iron, IIE-an","reclat":"25.143330","reclong":"75.813330","year":"2006-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.78,39.26333]},"id":"12268","mass":"85000","name":"Kayakent","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"39.263330","reclong":"31.780000","year":"1961-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[112.01667,-7.75]},"id":"12270","mass":"3300","name":"Kediri","nametype":"Valid","recclass":"L4","reclat":"-7.750000","reclong":"112.016670","year":"1940-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.41822,36.54194]},"id":"53654","mass":"5760","name":"Kemer","nametype":"Valid","recclass":"L4","reclat":"36.541940","reclong":"29.418220","year":"2008-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"3190","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96,29.45]},"id":"12275","mass":"6937","name":"Kendleton","nametype":"Valid","recclass":"L4","reclat":"29.450000","reclong":"-96.000000","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[86.70278,20.4625]},"id":"12276","mass":"6669.2","name":"Kendrapara","nametype":"Valid","recclass":"H4-5","reclat":"20.462500","reclong":"86.702780","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.3,48.4]},"id":"12282","mass":"5000","name":"Kerilis","nametype":"Valid","recclass":"H5","reclat":"48.400000","reclong":"-3.300000","year":"1874-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.08333,48.11667]},"id":"12284","mass":"80000","name":"Kernouve","nametype":"Valid","recclass":"H6","reclat":"48.116670","reclong":"-3.083330","year":"1869-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[141.61667,38.98333]},"id":"12286","mass":"135000","name":"Kesen","nametype":"Valid","recclass":"H4","reclat":"38.983330","reclong":"141.616670","year":"1850-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[72.3,29.53333]},"id":"12288","mass":"13600","name":"Khairpur","nametype":"Valid","recclass":"EL6","reclat":"29.533330","reclong":"72.300000","year":"1873-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.11667,25.55]},"id":"12289","mass":"3698","name":"Khanpur","nametype":"Valid","recclass":"LL5","reclat":"25.550000","reclong":"83.116670","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.075,50.625]},"id":"12291","mass":"1500","name":"Kharkov","nametype":"Valid","recclass":"L6","reclat":"50.625000","reclong":"35.075000","year":"1787-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.88333,26.95]},"id":"12294","mass":"450","name":"Kheragur","nametype":"Valid","recclass":"L6","reclat":"26.950000","reclong":"77.883330","year":"1860-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.81667,28.01667]},"id":"12296","mass":"100","name":"Khetri","nametype":"Valid","recclass":"H6","reclat":"28.016670","reclong":"75.816670","year":"1867-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.33333,56.75]},"id":"12297","mass":"6109","name":"Khmelevka","nametype":"Valid","recclass":"L5","reclat":"56.750000","reclong":"75.333330","year":"1929-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81.53333,25.1]},"id":"12298","mass":"9700","name":"Khohar","nametype":"Valid","recclass":"L3.6","reclat":"25.100000","reclong":"81.533330","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[36,16]},"id":"12299","mass":"3200","name":"Khor Temiki","nametype":"Valid","recclass":"Aubrite","reclat":"16.000000","reclong":"36.000000","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28,14]},"id":"12300","mass":"100000","name":"Kidairat","nametype":"Valid","recclass":"H6","reclat":"14.000000","reclong":"28.000000","year":"1983-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.15,54.4]},"id":"12301","mass":"737.6","name":"Kiel","nametype":"Valid","recclass":"L6","reclat":"54.400000","reclong":"10.150000","year":"1962-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-11.33333,16.58333]},"id":"12303","mass":"1500","name":"Kiffa","nametype":"Valid","recclass":"H5","reclat":"16.583330","reclong":"-11.333330","year":"1970-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[138.38333,36.85]},"id":"12305","mass":"331","name":"Kijima (1906)","nametype":"Valid","recclass":"Stone-uncl","reclat":"36.850000","reclong":"138.383330","year":"1906-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[34,55]},"id":"12306","mass":"195","name":"Kikino","nametype":"Valid","recclass":"H6","reclat":"55.000000","reclong":"34.000000","year":"1809-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.8,12.76667]},"id":"12307","mass":"19000","name":"Kilabo","nametype":"Valid","recclass":"LL6","reclat":"12.766670","reclong":"9.800000","year":"2002-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"41",":@computed_region_nnqa_25f4":"2971","fall":"Fell","geolocation":{"type":"Point","coordinates":[-89.6,43.58333]},"id":"12308","mass":"772","name":"Kilbourn","nametype":"Valid","recclass":"H5","reclat":"43.583330","reclong":"-89.600000","year":"1911-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.66667,54.66667]},"id":"12309","mass":"140","name":"Killeter","nametype":"Valid","recclass":"H6","reclat":"54.666670","reclong":"-7.666670","year":"1844-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[24.68333,11.63333]},"id":"12316","mass":"67.400000000000006","name":"Kingai","nametype":"Valid","recclass":"H6","reclat":"11.633330","reclong":"24.683330","year":"1967-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"2018","fall":"Fell","geolocation":{"type":"Point","coordinates":[-95.95,30.75]},"id":"12321","mass":"97.7","name":"Kirbyville","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"30.750000","reclong":"-95.950000","year":"1906-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.30833,48.16667]},"id":"12325","mass":"1550","name":"KisvarsΓ‘ny","nametype":"Valid","recclass":"L6","reclat":"48.166670","reclong":"22.308330","year":"1914-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-80.38333,43.38333]},"id":"12326","mass":"202.6","name":"Kitchener","nametype":"Valid","recclass":"L6","reclat":"43.383330","reclong":"-80.383330","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.8,51.6]},"id":"12332","mass":"3250","name":"Klein-Wenden","nametype":"Valid","recclass":"H6","reclat":"51.600000","reclong":"10.800000","year":"1843-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.4,48.9]},"id":"12335","mass":"500000","name":"Knyahinya","nametype":"Valid","recclass":"L/LL5","reclat":"48.900000","reclong":"22.400000","year":"1866-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[135.16667,34.73333]},"id":"12336","mass":"136","name":"Kobe","nametype":"Valid","recclass":"CK4","reclat":"34.733330","reclong":"135.166670","year":"1999-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[133.95,34.3]},"id":"12342","mass":"11510","name":"Kokubunji","nametype":"Valid","recclass":"L6","reclat":"34.300000","reclong":"133.950000","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[139.75,35.73333]},"id":"12343","mass":"238","name":"Komagome","nametype":"Valid","recclass":"Iron","reclat":"35.733330","reclong":"139.750000","year":"1926-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.16667,42.51667]},"id":"12344","mass":"90","name":"Konovo","nametype":"Valid","recclass":"LL5","reclat":"42.516670","reclong":"26.166670","year":"1931-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.17633,48.76367]},"id":"53810","mass":"4300","name":"KoΕ‘ice","nametype":"Valid","recclass":"H5","reclat":"48.763670","reclong":"21.176330","year":"2010-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.46472,49.32694]},"id":"12353","mass":"16500","name":"KrΓ€henberg","nametype":"Valid","recclass":"LL5","reclat":"49.326940","reclong":"7.464720","year":"1869-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[40.9,54.03333]},"id":"12355","mass":"2440","name":"Krasnoi-Ugol","nametype":"Valid","recclass":"L6","reclat":"54.033330","reclong":"40.900000","year":"1829-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[56.08333,54.33333]},"id":"12357","mass":"4000","name":"Krasnyi Klyuch","nametype":"Valid","recclass":"H5","reclat":"54.333330","reclong":"56.083330","year":"1946-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77,56.8]},"id":"12363","mass":"845.2","name":"Krutikha","nametype":"Valid","recclass":"OC","reclat":"56.800000","reclong":"77.000000","year":"1906-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.76667,47.83333]},"id":"12364","mass":"50000","name":"Krymka","nametype":"Valid","recclass":"LL3.2","reclat":"47.833330","reclong":"30.766670","year":"1946-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.7,51.15]},"id":"12368","mass":"2250","name":"Kukschin","nametype":"Valid","recclass":"L6","reclat":"51.150000","reclong":"31.700000","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[66.80222,30.73111]},"id":"12369","mass":"453.6","name":"Kulak","nametype":"Valid","recclass":"L5","reclat":"30.731110","reclong":"66.802220","year":"1961-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.5,50.75]},"id":"12370","mass":"6000","name":"Kuleschovka","nametype":"Valid","recclass":"L6","reclat":"50.750000","reclong":"33.500000","year":"1811-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[45,41.11667]},"id":"12373","mass":"3719","name":"Kulp","nametype":"Valid","recclass":"H6","reclat":"41.116670","reclong":"45.000000","year":"1906-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[61.36667,55.78333]},"id":"12377","mass":"200000","name":"Kunashak","nametype":"Valid","recclass":"L6","reclat":"55.783330","reclong":"61.366670","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[59.2,42.25]},"id":"12379","mass":"1100000","name":"Kunya-Urgench","nametype":"Valid","recclass":"H5","reclat":"42.250000","reclong":"59.200000","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[138.38333,37.05]},"id":"12381","mass":"4460","name":"Kushiike","nametype":"Valid","recclass":"OC","reclat":"37.050000","reclong":"138.383330","year":"1920-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.38333,29.68333]},"id":"12382","mass":"5","name":"Kusiali","nametype":"Valid","recclass":"L6","reclat":"29.683330","reclong":"78.383330","year":"1860-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[39.3,44.51667]},"id":"12383","mass":"23","name":"Kutais","nametype":"Valid","recclass":"H5","reclat":"44.516670","reclong":"39.300000","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.03333,10.83333]},"id":"12384","mass":"45000","name":"Kuttippuram","nametype":"Valid","recclass":"L6","reclat":"10.833330","reclong":"76.033330","year":"1914-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.33333,55.2]},"id":"12385","mass":"4047","name":"Kuznetzovo","nametype":"Valid","recclass":"L6","reclat":"55.200000","reclong":"75.333330","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[130.63333,32.03333]},"id":"12390","mass":"45000","name":"Kyushu","nametype":"Valid","recclass":"L6","reclat":"32.033330","reclong":"130.633330","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.75,47.08333]},"id":"12392","mass":"2800","name":"La BΓ©casse","nametype":"Valid","recclass":"L6","reclat":"47.083330","reclong":"1.750000","year":"1879-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-101.28333,20.66667]},"id":"12394","mass":"399","name":"La Charca","nametype":"Valid","recclass":"OC","reclat":"20.666670","reclong":"-101.283330","year":"1878-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-61.53333,-37.33333]},"id":"12395","mass":"2000","name":"La Colina","nametype":"Valid","recclass":"H5","reclat":"-37.333330","reclong":"-61.533330","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-58.16667,-31.23333]},"id":"12396","mass":"45000","name":"La Criolla","nametype":"Valid","recclass":"L6","reclat":"-31.233330","reclong":"-58.166670","year":"1985-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.58333,44.28333]},"id":"12408","mass":"3833","name":"Laborel","nametype":"Valid","recclass":"H5","reclat":"44.283330","reclong":"5.583330","year":"1871-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.71667,26.78333]},"id":"12433","mass":"900","name":"Lahrauli","nametype":"Valid","recclass":"Ureilite","reclat":"26.783330","reclong":"82.716670","year":"1955-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.63333,48.76667]},"id":"12434","mass":"37000","name":"L'Aigle","nametype":"Valid","recclass":"L6","reclat":"48.766670","reclong":"0.633330","year":"1803-01-01T00:00:00.000"} -,{"fall":"Found","id":"32531","mass":"9.6","name":"Cumulus Hills 04075","nametype":"Valid","recclass":"Pallasite","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.03333,21.86667]},"id":"12435","mass":"212.5","name":"Lakangaon","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"21.866670","reclong":"76.033330","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.56667,24.45]},"id":"12451","mass":"372","name":"Lalitpur","nametype":"Valid","recclass":"L6","reclat":"24.450000","reclong":"78.566670","year":"1887-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.06667,47.7]},"id":"12455","mass":"51700","name":"LancΓ©","nametype":"Valid","recclass":"CO3.5","reclat":"47.700000","reclong":"1.066670","year":"1872-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.11667,43.75]},"id":"12456","mass":"7000","name":"Lancon","nametype":"Valid","recclass":"H6","reclat":"43.750000","reclong":"5.116670","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.73333,58.85]},"id":"12461","mass":"2300","name":"LΓ₯nghalsen","nametype":"Valid","recclass":"L6","reclat":"58.850000","reclong":"16.733330","year":"1947-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[126.19611,46.24167]},"id":"12464","mass":"1282","name":"Lanxi","nametype":"Valid","recclass":"L6","reclat":"46.241670","reclong":"126.196110","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.23333,47.75]},"id":"12465","mass":"7000","name":"Lanzenkirchen","nametype":"Valid","recclass":"L4","reclat":"47.750000","reclong":"16.233330","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.16667,33.13333]},"id":"12466","mass":"14250","name":"Laochenzhen","nametype":"Valid","recclass":"H5","reclat":"33.133330","reclong":"115.166670","year":"1987-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.11667,51.9]},"id":"12740","mass":"1060","name":"Launton","nametype":"Valid","recclass":"L6","reclat":"51.900000","reclong":"-1.116670","year":"1830-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[51.56667,52.45]},"id":"12743","mass":"800","name":"Lavrentievka","nametype":"Valid","recclass":"L6","reclat":"52.450000","reclong":"51.566670","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.43333,47.16667]},"id":"12748","mass":"3000","name":"Le Pressoir","nametype":"Valid","recclass":"H5","reclat":"47.166670","reclong":"0.433330","year":"1845-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.86667,48.53333]},"id":"12749","mass":"780","name":"Le Teilleul","nametype":"Valid","recclass":"Howardite","reclat":"48.533330","reclong":"-0.866670","year":"1845-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"20",":@computed_region_nnqa_25f4":"608","fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.33333,35.88333]},"id":"12755","mass":"51500","name":"Leedey","nametype":"Valid","recclass":"L6","reclat":"35.883330","reclong":"-99.333330","year":"1943-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28.36667,-25.66667]},"id":"12756","mass":"460","name":"Leeuwfontein","nametype":"Valid","recclass":"L6","reclat":"-25.666670","reclong":"28.366670","year":"1912-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.96667,52.66667]},"id":"12759","mass":"271.39999999999998","name":"Leighlinbridge","nametype":"Valid","recclass":"L6","reclat":"52.666670","reclong":"-6.966670","year":"1999-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"29",":@computed_region_nnqa_25f4":"1585","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87.5,34.58333]},"id":"12760","mass":"877","name":"Leighton","nametype":"Valid","recclass":"H5","reclat":"34.583330","reclong":"-87.500000","year":"1907-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[32.85,52.26667]},"id":"12765","mass":"700","name":"Leonovka","nametype":"Valid","recclass":"L6","reclat":"52.266670","reclong":"32.850000","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.25,48.35]},"id":"12769","mass":"125","name":"Les Ormes","nametype":"Valid","recclass":"L6","reclat":"48.350000","reclong":"3.250000","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4.73333,50.36667]},"id":"12772","mass":"2000","name":"Lesves","nametype":"Valid","recclass":"L6","reclat":"50.366670","reclong":"4.733330","year":"1896-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.18333,-26.15]},"id":"14646","mass":"4000","name":"Lichtenberg","nametype":"Valid","recclass":"H6","reclat":"-26.150000","reclong":"26.183330","year":"1973-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.86667,56.65]},"id":"14650","mass":"6862","name":"Lillaverke","nametype":"Valid","recclass":"H5","reclat":"56.650000","reclong":"15.866670","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8.78333,52.56667]},"id":"14652","mass":"50000","name":"Limerick","nametype":"Valid","recclass":"H5","reclat":"52.566670","reclong":"-8.783330","year":"1813-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.9,52.75]},"id":"14655","mass":"1862","name":"Linum","nametype":"Valid","recclass":"L6","reclat":"52.750000","reclong":"12.900000","year":"1854-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[118.98333,31.63333]},"id":"14659","mass":"498","name":"Lishui","nametype":"Valid","recclass":"L5","reclat":"31.633330","reclong":"118.983330","year":"1978-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.85,50.2]},"id":"14661","mass":"12800","name":"Lissa","nametype":"Valid","recclass":"L6","reclat":"50.200000","reclong":"14.850000","year":"1808-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"2171","fall":"Fell","geolocation":{"type":"Point","coordinates":[-92.08333,37.91667]},"id":"14664","mass":"491","name":"Little Piney","nametype":"Valid","recclass":"L5","reclat":"37.916670","reclong":"-92.083330","year":"1839-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.43333,56]},"id":"14670","mass":"5213","name":"Lixna","nametype":"Valid","recclass":"H4","reclat":"56.000000","reclong":"26.433330","year":"1820-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[71.8,29.53333]},"id":"14675","mass":"1000","name":"Lodran","nametype":"Valid","recclass":"Lodranite","reclat":"29.533330","reclong":"71.800000","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[72.62667,26.96556]},"id":"14678","mass":"40000","name":"Lohawat","nametype":"Valid","recclass":"Howardite","reclat":"26.965560","reclong":"72.626670","year":"1994-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"40",":@computed_region_nnqa_25f4":"2770","fall":"Fell","geolocation":{"type":"Point","coordinates":[-77.21163,38.70066]},"id":"52843","mass":"329.7","name":"Lorton","nametype":"Valid","recclass":"L6","reclat":"38.700660","reclong":"-77.211630","year":"2010-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.83333,38]},"id":"14708","mass":"25","name":"Los Martinez","nametype":"Valid","recclass":"L6","reclat":"38.000000","reclong":"-0.833330","year":"1894-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"20",":@computed_region_nnqa_25f4":"2711","fall":"Fell","geolocation":{"type":"Point","coordinates":[-95.15,36.00833]},"id":"14711","mass":"17000","name":"Lost City","nametype":"Valid","recclass":"H5","reclat":"36.008330","reclong":"-95.150000","year":"1970-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"36",":@computed_region_nnqa_25f4":"1327","fall":"Fell","geolocation":{"type":"Point","coordinates":[-85.75,38.25]},"id":"14716","mass":"1300","name":"Louisville","nametype":"Valid","recclass":"L6","reclat":"38.250000","reclong":"-85.750000","year":"1977-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[19.91667,52]},"id":"14718","mass":"59000","name":"Łowicz","nametype":"Valid","recclass":"Mesosiderite-A3","reclat":"52.000000","reclong":"19.916670","year":"1935-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.15,24.95]},"id":"14721","mass":"9241","name":"Lua","nametype":"Valid","recclass":"L5","reclat":"24.950000","reclong":"75.150000","year":"1926-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.48333,47.85]},"id":"14724","mass":"3500","name":"LucΓ©","nametype":"Valid","recclass":"L6","reclat":"47.850000","reclong":"0.483330","year":"1768-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"31",":@computed_region_nnqa_25f4":"1567","fall":"Fell","geolocation":{"type":"Point","coordinates":[-84.76667,32.03333]},"id":"14753","mass":"340","name":"Lumpkin","nametype":"Valid","recclass":"L6","reclat":"32.033330","reclong":"-84.766670","year":"1869-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[103.3,24.8]},"id":"14754","mass":"2520","name":"Lunan","nametype":"Valid","recclass":"H6","reclat":"24.800000","reclong":"103.300000","year":"1980-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.03333,56.21667]},"id":"14755","mass":"11000","name":"LundsgΓ₯rd","nametype":"Valid","recclass":"L6","reclat":"56.216670","reclong":"13.033330","year":"1889-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.7,61.2]},"id":"14756","mass":"885","name":"Luotolax","nametype":"Valid","recclass":"Howardite","reclat":"61.200000","reclong":"27.700000","year":"1813-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5,46.21667]},"id":"14757","mass":"14000","name":"Luponnas","nametype":"Valid","recclass":"H3-5","reclat":"46.216670","reclong":"5.000000","year":"1753-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.43333,-7.21667]},"id":"14759","name":"Lusaka","nametype":"Valid","recclass":"Unknown","reclat":"-7.216670","reclong":"29.433330","year":"1951-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[97,19]},"id":"14764","mass":"540","name":"Mabwe-Khoywa","nametype":"Valid","recclass":"L5","reclat":"19.000000","reclong":"97.000000","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-36.66667,-5.2]},"id":"15370","mass":"1500","name":"Macau","nametype":"Valid","recclass":"H5","reclat":"-5.200000","reclong":"-36.666670","year":"1836-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.24222,-15.21222]},"id":"15371","mass":"93200","name":"Machinga","nametype":"Valid","recclass":"L6","reclat":"-15.212220","reclong":"35.242220","year":"1981-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.95,-28.83333]},"id":"15372","mass":"1995","name":"Macibini","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"-28.833330","reclong":"31.950000","year":"1936-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[86.36667,25.91667]},"id":"15379","mass":"1000","name":"Madhipura","nametype":"Valid","recclass":"L","reclat":"25.916670","reclong":"86.366670","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.53333,-7.75]},"id":"15380","mass":"400","name":"Madiun","nametype":"Valid","recclass":"L6","reclat":"-7.750000","reclong":"111.533330","year":"1935-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.71667,40.41667]},"id":"15382","mass":"400","name":"Madrid","nametype":"Valid","recclass":"L6","reclat":"40.416670","reclong":"-3.716670","year":"1896-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-49.93333,-26.16667]},"id":"15383","mass":"600","name":"Mafra","nametype":"Valid","recclass":"L3-4","reclat":"-26.166670","reclong":"-49.933330","year":"1941-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.51667,37.86667]},"id":"15386","mass":"5000","name":"Magnesia","nametype":"Valid","recclass":"Iron, IAB-sHL","reclat":"37.866670","reclong":"27.516670","year":"1899-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.65,-19.48333]},"id":"15387","mass":"666.6","name":"Magombedze","nametype":"Valid","recclass":"H3-5","reclat":"-19.483330","reclong":"31.650000","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[95.78333,27.66667]},"id":"47361","mass":"70500","name":"Mahadevpur","nametype":"Valid","recclass":"H4/5","reclat":"27.666670","reclong":"95.783330","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.38333,12.83333]},"id":"30751","mass":"4629","name":"Maigatari-Danduma","nametype":"Valid","recclass":"H5/6","reclat":"12.833330","reclong":"9.383330","year":"2004-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"11",":@computed_region_nnqa_25f4":"611","fall":"Fell","geolocation":{"type":"Point","coordinates":[-104,32.21667]},"id":"15393","mass":"150","name":"Malaga","nametype":"Valid","recclass":"OC","reclat":"32.216670","reclong":"-104.000000","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.75,9.5]},"id":"15394","mass":"2000","name":"Malakal","nametype":"Valid","recclass":"L5","reclat":"9.500000","reclong":"31.750000","year":"1970-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.51667,-3.13333]},"id":"15395","mass":"470","name":"Malampaka","nametype":"Valid","recclass":"H","reclat":"-3.133330","reclong":"33.516670","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-63.23333,-28.93333]},"id":"15397","name":"Malotas","nametype":"Valid","recclass":"H5","reclat":"-28.933330","reclong":"-63.233330","year":"1931-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.76667,-29.45]},"id":"15400","mass":"807","name":"Malvern","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"-29.450000","reclong":"26.766670","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[62.08333,45.21667]},"id":"15401","mass":"1000","name":"Mamra Springs","nametype":"Valid","recclass":"L6","reclat":"45.216670","reclong":"62.083330","year":"1927-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[86.7,23.05]},"id":"15402","mass":"1700","name":"Manbhoom","nametype":"Valid","recclass":"LL6","reclat":"23.050000","reclong":"86.700000","year":"1863-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.1,20.96667]},"id":"15403","mass":"50","name":"Manegaon","nametype":"Valid","recclass":"Diogenite","reclat":"20.966670","reclong":"76.100000","year":"1843-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.6,-17.65]},"id":"15405","mass":"22300","name":"Mangwendi","nametype":"Valid","recclass":"LL6","reclat":"-17.650000","reclong":"31.600000","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[44.63333,45.81667]},"id":"15409","mass":"3555","name":"Manych","nametype":"Valid","recclass":"LL3.4","reclat":"45.816670","reclong":"44.633330","year":"1951-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[72.08333,34.23333]},"id":"15414","mass":"4500","name":"Mardan","nametype":"Valid","recclass":"H5","reclat":"34.233330","reclong":"72.083330","year":"1948-01-01T00:00:00.000"} -,{"fall":"Fell","id":"15418","mass":"114","name":"Maria Linden","nametype":"Valid","recclass":"L4","year":"1925-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"19",":@computed_region_nnqa_25f4":"471","fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.38333,42.71667]},"id":"15419","mass":"340","name":"Mariaville","nametype":"Valid","recclass":"Iron","reclat":"42.716670","reclong":"-99.383330","year":"1898-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.46745,54.76183]},"id":"48973","mass":"25.81","name":"Maribo","nametype":"Valid","recclass":"CM2","reclat":"54.761830","reclong":"11.467450","year":"2009-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.25,4.66667]},"id":"15421","mass":"3200","name":"Maridi","nametype":"Valid","recclass":"H6","reclat":"4.666670","reclong":"29.250000","year":"1941-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-49.93333,-22.25]},"id":"15422","mass":"2500","name":"Marilia","nametype":"Valid","recclass":"H4","reclat":"-22.250000","reclong":"-49.933330","year":"1971-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"16",":@computed_region_nnqa_25f4":"287","fall":"Fell","geolocation":{"type":"Point","coordinates":[-91.6,41.9]},"id":"15424","mass":"28400","name":"Marion (Iowa)","nametype":"Valid","recclass":"L6","reclat":"41.900000","reclong":"-91.600000","year":"1847-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.5,61.5]},"id":"15426","mass":"45000","name":"Marjalahti","nametype":"Valid","recclass":"Pallasite, PMG","reclat":"61.500000","reclong":"30.500000","year":"1902-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.15,44.5]},"id":"15429","mass":"3000","name":"Marmande","nametype":"Valid","recclass":"L5","reclat":"44.500000","reclong":"0.150000","year":"1848-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[48.1,-14.2]},"id":"15430","mass":"6000","name":"Maromandia","nametype":"Valid","recclass":"L6","reclat":"-14.200000","reclong":"48.100000","year":"2002-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"39",":@computed_region_nnqa_25f4":"2740","fall":"Fell","geolocation":{"type":"Point","coordinates":[-84.1,35.8]},"id":"15436","mass":"1443","name":"Maryville","nametype":"Valid","recclass":"L6","reclat":"35.800000","reclong":"-84.100000","year":"1983-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.86667,45.36667]},"id":"15438","mass":"1000","name":"Mascombes","nametype":"Valid","recclass":"L6","reclat":"45.366670","reclong":"1.866670","year":"1836-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0,0]},"id":"53653","mass":"24.54","name":"Mason Gully","nametype":"Valid","recclass":"H5","reclat":"0.000000","reclong":"0.000000","year":"2010-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.61667,48.13333]},"id":"15443","mass":"1600","name":"MΓ€ssing","nametype":"Valid","recclass":"Howardite","reclat":"48.133330","reclong":"12.616670","year":"1803-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.13333,48.18333]},"id":"15446","mass":"19000","name":"Mauerkirchen","nametype":"Valid","recclass":"L6","reclat":"48.183330","reclong":"13.133330","year":"1768-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[57,-20]},"id":"15447","mass":"220","name":"Mauritius","nametype":"Valid","recclass":"L6","reclat":"-20.000000","reclong":"57.000000","year":"1801-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.08333,8.96667]},"id":"15451","mass":"4850","name":"Mayo Belwa","nametype":"Valid","recclass":"Aubrite","reclat":"8.966670","reclong":"12.083330","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-101.68333,24.68333]},"id":"15453","mass":"4000","name":"Mazapil","nametype":"Valid","recclass":"Iron, IAB-sLL","reclat":"24.683330","reclong":"-101.683330","year":"1885-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30,-1.21667]},"id":"15454","mass":"4975","name":"Maziba","nametype":"Valid","recclass":"L6","reclat":"-1.216670","reclong":"30.000000","year":"1942-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[34.16667,1.06667]},"id":"15455","mass":"150000","name":"Mbale","nametype":"Valid","recclass":"L5/6","reclat":"1.066670","reclong":"34.166670","year":"1992-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-67.5,-27.25]},"id":"15467","mass":"31","name":"Medanitos","nametype":"Valid","recclass":"Eucrite-cm","reclat":"-27.250000","reclong":"-67.500000","year":"1953-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.8,29.01667]},"id":"15469","mass":"22","name":"Meerut","nametype":"Valid","recclass":"H5","reclat":"29.016670","reclong":"77.800000","year":"1861-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[106.88333,-6.23333]},"id":"15470","mass":"24750","name":"Meester-Cornelis","nametype":"Valid","recclass":"H5","reclat":"-6.233330","reclong":"106.883330","year":"1915-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.15,53.18333]},"id":"15485","mass":"10500","name":"Menow","nametype":"Valid","recclass":"H4","reclat":"53.183330","reclong":"13.150000","year":"1862-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.21817,46.81867]},"id":"15486","mass":"28.9","name":"Menziswyl","nametype":"Valid","recclass":"L5","reclat":"46.818670","reclong":"7.218170","year":"1903-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.06667,55.05]},"id":"15489","mass":"4000","name":"Mern","nametype":"Valid","recclass":"L6","reclat":"55.050000","reclong":"12.066670","year":"1878-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.66667,0]},"id":"15491","mass":"6000","name":"Meru","nametype":"Valid","recclass":"LL6","reclat":"0.000000","reclong":"37.666670","year":"1945-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[81.98333,25.48333]},"id":"15492","mass":"71400","name":"Merua","nametype":"Valid","recclass":"H5","reclat":"25.483330","reclong":"81.983330","year":"1920-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.56667,38.18333]},"id":"15495","mass":"2405","name":"Messina","nametype":"Valid","recclass":"L5","reclat":"38.183330","reclong":"15.566670","year":"1955-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.1,50.58333]},"id":"16626","mass":"870","name":"Meuselbach","nametype":"Valid","recclass":"L6","reclat":"50.583330","reclong":"11.100000","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.25,45.76667]},"id":"16627","mass":"1300","name":"Mezel","nametype":"Valid","recclass":"L6","reclat":"45.766670","reclong":"3.250000","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.73333,46.5]},"id":"16628","mass":"22700","name":"MezΓΆ-Madaras","nametype":"Valid","recclass":"L3.7","reclat":"46.500000","reclong":"25.733330","year":"1852-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.61667,25.9]},"id":"16629","mass":"350","name":"Mhow","nametype":"Valid","recclass":"L6","reclat":"25.900000","reclong":"83.616670","year":"1827-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.7,34.8]},"id":"16631","mass":"1100","name":"Mianchi","nametype":"Valid","recclass":"H5","reclat":"34.800000","reclong":"111.700000","year":"1980-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.16667,54.56667]},"id":"16632","mass":"1600","name":"Middlesbrough","nametype":"Valid","recclass":"L6","reclat":"54.566670","reclong":"-1.166670","year":"1881-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"41",":@computed_region_nnqa_25f4":"2996","fall":"Fell","geolocation":{"type":"Point","coordinates":[-90.36556,42.9075]},"id":"52090","mass":"3584","name":"Mifflin","nametype":"Valid","recclass":"L5","reclat":"42.907500","reclong":"-90.365560","year":"2010-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.96667,48.06667]},"id":"16634","mass":"8000","name":"Mighei","nametype":"Valid","recclass":"CM2","reclat":"48.066670","reclong":"30.966670","year":"1889-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[133.22,35.56833]},"id":"16635","mass":"6380","name":"Mihonoseki","nametype":"Valid","recclass":"L6","reclat":"35.568330","reclong":"133.220000","year":"1992-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[17.53333,46.23333]},"id":"16636","mass":"224.2","name":"Mike","nametype":"Valid","recclass":"L6","reclat":"46.233330","reclong":"17.533330","year":"1944-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.1,46.18333]},"id":"16640","mass":"10000","name":"Milena","nametype":"Valid","recclass":"L6","reclat":"46.183330","reclong":"16.100000","year":"1842-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[120.36667,-26.45]},"id":"16643","mass":"330000","name":"Millbillillie","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"-26.450000","reclong":"120.366670","year":"1960-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"15",":@computed_region_nnqa_25f4":"11","fall":"Fell","geolocation":{"type":"Point","coordinates":[-92.05,35.4]},"id":"16645","mass":"16700","name":"Miller (Arkansas)","nametype":"Valid","recclass":"H5","reclat":"35.400000","reclong":"-92.050000","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.93333,35.07833]},"id":"16692","mass":"1040","name":"Minamino","nametype":"Valid","recclass":"L","reclat":"35.078330","reclong":"136.933330","year":"1632-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.7,37.28333]},"id":"16696","mass":"42","name":"Mineo","nametype":"Valid","recclass":"Pallasite","reclat":"37.283330","reclong":"14.700000","year":"1826-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[120.66667,32.33333]},"id":"16697","mass":"5500","name":"Min-Fan-Zhun","nametype":"Valid","recclass":"LL6","reclat":"32.333330","reclong":"120.666670","year":"1952-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.6,47.7]},"id":"16700","mass":"550","name":"Minnichhof","nametype":"Valid","recclass":"OC","reclat":"47.700000","reclong":"16.600000","year":"1905-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.25,25.68333]},"id":"16701","mass":"8510","name":"Mirzapur","nametype":"Valid","recclass":"L5","reclat":"25.683330","reclong":"83.250000","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23,56.66667]},"id":"16703","mass":"5800","name":"Misshof","nametype":"Valid","recclass":"H5","reclat":"56.666670","reclong":"23.000000","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.93333,61.73333]},"id":"16707","mass":"100.7","name":"Mjelleim","nametype":"Valid","recclass":"H","reclat":"61.733330","reclong":"5.933330","year":"1898-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[24.03333,46.8]},"id":"16709","mass":"300000","name":"Mocs","nametype":"Valid","recclass":"L5-6","reclat":"46.800000","reclong":"24.033330","year":"1882-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1290","fall":"Fell","geolocation":{"type":"Point","coordinates":[-101.1,38.5]},"id":"16711","mass":"35000","name":"Modoc (1905)","nametype":"Valid","recclass":"L6","reclat":"38.500000","reclong":"-101.100000","year":"1905-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[174.4,-39.63333]},"id":"16713","mass":"4500","name":"Mokoia","nametype":"Valid","recclass":"CV3","reclat":"-39.633330","reclong":"174.400000","year":"1908-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.16667,38.11667]},"id":"16715","mass":"144000","name":"Molina","nametype":"Valid","recclass":"H5","reclat":"38.116670","reclong":"-1.166670","year":"1858-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.46667,-31.25]},"id":"16717","mass":"150","name":"Molteno","nametype":"Valid","recclass":"Howardite","reclat":"-31.250000","reclong":"26.466670","year":"1953-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"2957","fall":"Fell","geolocation":{"type":"Point","coordinates":[-102.85833,31.60833]},"id":"16719","mass":"2587","name":"Monahans (1998)","nametype":"Valid","recclass":"H5","reclat":"31.608330","reclong":"-102.858330","year":"1998-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"636","fall":"Fell","geolocation":{"type":"Point","coordinates":[-80.5,35.25]},"id":"16720","mass":"8600","name":"Monroe","nametype":"Valid","recclass":"H4","reclat":"35.250000","reclong":"-80.500000","year":"1849-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8.25,38.01667]},"id":"16725","mass":"4885","name":"Monte das Fortes","nametype":"Valid","recclass":"L5","reclat":"38.016670","reclong":"-8.250000","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.35,43.26667]},"id":"16726","mass":"3130","name":"Monte Milone","nametype":"Valid","recclass":"L5","reclat":"43.266670","reclong":"13.350000","year":"1846-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.9625,43.39056]},"id":"16727","mass":"149000","name":"MontferrΓ©","nametype":"Valid","recclass":"H5","reclat":"43.390560","reclong":"1.962500","year":"1923-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.58333,47.63333]},"id":"16729","mass":"500","name":"Montlivault","nametype":"Valid","recclass":"L6","reclat":"47.633330","reclong":"1.583330","year":"1838-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.35,-15.96667]},"id":"16733","name":"Monze","nametype":"Valid","recclass":"L6","reclat":"-15.966670","reclong":"27.350000","year":"1950-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"2431","fall":"Fell","geolocation":{"type":"Point","coordinates":[-79.38333,35.41667]},"id":"16736","mass":"1880","name":"Moore County","nametype":"Valid","recclass":"Eucrite-cm","reclat":"35.416670","reclong":"-79.383330","year":"1913-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8.33333,52.45]},"id":"16737","mass":"3520","name":"Mooresfort","nametype":"Valid","recclass":"H5","reclat":"52.450000","reclong":"-8.333330","year":"1810-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[145.6,-40.975]},"id":"16738","mass":"8887.5","name":"Moorleah","nametype":"Valid","recclass":"L6","reclat":"-40.975000","reclong":"145.600000","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.83333,28.78333]},"id":"16740","mass":"70","name":"Moradabad","nametype":"Valid","recclass":"L6","reclat":"28.783330","reclong":"78.833330","year":"1808-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[18.53333,49.6]},"id":"16742","mass":"633","name":"MorΓ‘vka","nametype":"Valid","recclass":"H5","reclat":"49.600000","reclong":"18.533330","year":"2000-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.13333,44.6]},"id":"16747","mass":"1300","name":"Mornans","nametype":"Valid","recclass":"H5","reclat":"44.600000","reclong":"5.133330","year":"1875-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.7,59.43333]},"id":"36592","mass":"3763","name":"Moss","nametype":"Valid","recclass":"CO3.6","reclat":"59.433330","reclong":"10.700000","year":"2006-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.33333,26.83333]},"id":"16759","mass":"1500","name":"Moti-ka-nagla","nametype":"Valid","recclass":"H6","reclat":"26.833330","reclong":"77.333330","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.5,45.2]},"id":"16762","mass":"9150","name":"Motta di Conti","nametype":"Valid","recclass":"H4","reclat":"45.200000","reclong":"8.500000","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[141.7,-29.8]},"id":"16766","mass":"11300","name":"Mount Browne","nametype":"Valid","recclass":"H6","reclat":"-29.800000","reclong":"141.700000","year":"1902-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4.8,18.7]},"id":"16804","mass":"110000","name":"Mount Tazerzait","nametype":"Valid","recclass":"L5","reclat":"18.700000","reclong":"4.800000","year":"1991-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.86667,44.08333]},"id":"16805","mass":"17000","name":"Mount Vaisi","nametype":"Valid","recclass":"Stone-uncl","reclat":"44.083330","reclong":"6.866670","year":"1637-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.5,-11.5]},"id":"16820","mass":"1100","name":"Mtola","nametype":"Valid","recclass":"Stone-uncl","reclat":"-11.500000","reclong":"33.500000","year":"1944-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.01667,12.63333]},"id":"16841","mass":"4400","name":"Muddoor","nametype":"Valid","recclass":"L5","reclat":"12.633330","reclong":"77.016670","year":"1865-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[80.83333,9.33333]},"id":"16851","mass":"25.5","name":"Mulletiwu","nametype":"Valid","recclass":"L","reclat":"9.333330","reclong":"80.833330","year":"1795-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[90.21667,24.5]},"id":"16874","mass":"4703","name":"Muraid","nametype":"Valid","recclass":"L6","reclat":"24.500000","reclong":"90.216670","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[145.2,-36.61667]},"id":"16875","mass":"100000","name":"Murchison","nametype":"Valid","recclass":"CM2","reclat":"-36.616670","reclong":"145.200000","year":"1969-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"36",":@computed_region_nnqa_25f4":"237","fall":"Fell","geolocation":{"type":"Point","coordinates":[-88.1,36.6]},"id":"16882","mass":"12600","name":"Murray","nametype":"Valid","recclass":"CM2","reclat":"36.600000","reclong":"-88.100000","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[85.53333,26.13333]},"id":"16885","mass":"1245","name":"Muzaffarpur","nametype":"Valid","recclass":"Iron, IAB-sHL","reclat":"26.133330","reclong":"85.533330","year":"1964-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[72.63333,23.05]},"id":"16887","name":"Myhee Caunta","nametype":"Valid","recclass":"OC","reclat":"23.050000","reclong":"72.633330","year":"1842-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1,12]},"id":"16889","mass":"8165","name":"Nadiabondi","nametype":"Valid","recclass":"H5","reclat":"12.000000","reclong":"1.000000","year":"1956-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[140.06167,38.12167]},"id":"16890","mass":"1810","name":"Nagai","nametype":"Valid","recclass":"L6","reclat":"38.121670","reclong":"140.061670","year":"1922-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.21667,26.98333]},"id":"16892","mass":"20","name":"Nagaria","nametype":"Valid","recclass":"Eucrite-cm","reclat":"26.983330","reclong":"78.216670","year":"1875-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[19.5,49.16667]},"id":"16893","mass":"6100","name":"Nagy-BorovΓ©","nametype":"Valid","recclass":"L5","reclat":"49.166670","reclong":"19.500000","year":"1895-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.35,31.31667]},"id":"16898","mass":"10000","name":"Nakhla","nametype":"Valid","recclass":"Martian (nakhlite)","reclat":"31.316670","reclong":"30.350000","year":"1911-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[100.08333,13.73333]},"id":"16899","mass":"23200","name":"Nakhon Pathom","nametype":"Valid","recclass":"L6","reclat":"13.733330","reclong":"100.083330","year":"1923-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[79.2,12.28333]},"id":"16902","mass":"4500","name":"Nammianthal","nametype":"Valid","recclass":"H5","reclat":"12.283330","reclong":"79.200000","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[103.5,35.66667]},"id":"16903","mass":"52900","name":"Nan Yang Pao","nametype":"Valid","recclass":"L6","reclat":"35.666670","reclong":"103.500000","year":"1917-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"45",":@computed_region_nnqa_25f4":"419","fall":"Fell","geolocation":{"type":"Point","coordinates":[-77.16667,38.41667]},"id":"16904","mass":"7500","name":"Nanjemoy","nametype":"Valid","recclass":"H6","reclat":"38.416670","reclong":"-77.166670","year":"1825-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[121.8,32.11667]},"id":"16907","mass":"529","name":"Nantong","nametype":"Valid","recclass":"H6","reclat":"32.116670","reclong":"121.800000","year":"1984-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77,19.25]},"id":"16908","mass":"17000","name":"Naoki","nametype":"Valid","recclass":"H6","reclat":"19.250000","reclong":"77.000000","year":"1928-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[51.5,33.75]},"id":"16909","mass":"2700","name":"Naragh","nametype":"Valid","recclass":"H6","reclat":"33.750000","reclong":"51.500000","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[150.68889,-34.05]},"id":"16912","mass":"367.5","name":"Narellan","nametype":"Valid","recclass":"L6","reclat":"-34.050000","reclong":"150.688890","year":"1928-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.51667,42.51667]},"id":"16914","name":"Narni","nametype":"Valid","recclass":"Stone-uncl","reclat":"42.516670","reclong":"12.516670","year":"0921-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[165.9,-21.73333]},"id":"16922","mass":"347","name":"Nassirah","nametype":"Valid","recclass":"H4","reclat":"-21.733330","reclong":"165.900000","year":"1936-01-01T00:00:00.000"} -,{"fall":"Fell","id":"16923","mass":"1.4","name":"Natal","nametype":"Valid","recclass":"Stone-uncl","year":"1973-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.66667,21.25]},"id":"16927","mass":"105","name":"Nawapali","nametype":"Valid","recclass":"CM2","reclat":"21.250000","reclong":"83.666670","year":"1890-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.46528,36.44917]},"id":"16934","mass":"420","name":"Neagari","nametype":"Valid","recclass":"L6","reclat":"36.449170","reclong":"136.465280","year":"1995-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[83.48333,18.68333]},"id":"16935","mass":"4500","name":"Nedagolla","nametype":"Valid","recclass":"Iron, ungrouped","reclat":"18.683330","reclong":"83.483330","year":"1870-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.33333,9.5]},"id":"16941","mass":"2450","name":"Nejo","nametype":"Valid","recclass":"L6","reclat":"9.500000","reclong":"35.333330","year":"1970-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.5,56.5]},"id":"16945","mass":"10250","name":"Nerft","nametype":"Valid","recclass":"L6","reclat":"56.500000","reclong":"21.500000","year":"1864-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.80833,47.525]},"id":"16950","mass":"6189","name":"Neuschwanstein","nametype":"Valid","recclass":"EL6","reclat":"47.525000","reclong":"10.808330","year":"2002-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"38",":@computed_region_nnqa_25f4":"2615","fall":"Fell","geolocation":{"type":"Point","coordinates":[-81.76667,40]},"id":"16953","mass":"230000","name":"New Concord","nametype":"Valid","recclass":"L6","reclat":"40.000000","reclong":"-81.766670","year":"1860-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.68333,15.36667]},"id":"16954","mass":"12000","name":"New Halfa","nametype":"Valid","recclass":"L4","reclat":"15.366670","reclong":"35.683330","year":"1994-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"22",":@computed_region_nnqa_25f4":"1667","fall":"Fell","geolocation":{"type":"Point","coordinates":[-90.10976,29.94718]},"id":"16960","mass":"19256","name":"New Orleans","nametype":"Valid","recclass":"H5","reclat":"29.947180","reclong":"-90.109760","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.41667,-7.45]},"id":"16966","mass":"1393","name":"Ngawi","nametype":"Valid","recclass":"LL3.6","reclat":"-7.450000","reclong":"111.416670","year":"1883-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-4.38333,13.85]},"id":"16968","mass":"37500","name":"N'Goureyma","nametype":"Valid","recclass":"Iron, ungrouped","reclat":"13.850000","reclong":"-4.383330","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.43333,49.03333]},"id":"16970","name":"Nicorps","nametype":"Valid","recclass":"Stone-uncl","reclat":"49.033330","reclong":"-1.433330","year":"1750-01-01T00:00:00.000"} -,{"fall":"Fell","id":"16974","mass":"3.3","name":"Niger (L6)","nametype":"Valid","recclass":"L6","year":"1967-01-01T00:00:00.000"} -,{"fall":"Fell","id":"16975","mass":"3.3","name":"Niger (LL6)","nametype":"Valid","recclass":"LL6","year":"1967-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.63333,52.45]},"id":"16976","mass":"3996","name":"Nikolaevka","nametype":"Valid","recclass":"H4","reclat":"52.450000","reclong":"78.633330","year":"1935-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.33333,56.11667]},"id":"16977","mass":"6000","name":"Nikolskoe","nametype":"Valid","recclass":"L4","reclat":"56.116670","reclong":"37.333330","year":"1954-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[121.48333,29.86667]},"id":"16980","mass":"14250","name":"Ningbo","nametype":"Valid","recclass":"Iron, IVA","reclat":"29.866670","reclong":"121.483330","year":"1975-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[105.90667,32.925]},"id":"16981","mass":"4610","name":"Ningqiang","nametype":"Valid","recclass":"C3-ung","reclat":"32.925000","reclong":"105.906670","year":"1983-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[131.56667,34.2]},"id":"16982","mass":"467","name":"Nio","nametype":"Valid","recclass":"H3-4","reclat":"34.200000","reclong":"131.566670","year":"1897-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[30.7,-28.56667]},"id":"16983","mass":"17200","name":"N'Kandhla","nametype":"Valid","recclass":"Iron, IID","reclat":"-28.566670","reclong":"30.700000","year":"1912-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"49",":@computed_region_nnqa_25f4":"1683","fall":"Fell","geolocation":{"type":"Point","coordinates":[-69.48333,44.08333]},"id":"16984","mass":"2300","name":"Nobleborough","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"44.083330","reclong":"-69.483330","year":"1823-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"35",":@computed_region_nnqa_25f4":"2238","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.055,40.08528]},"id":"16985","mass":"483.7","name":"Noblesville","nametype":"Valid","recclass":"H4-6","reclat":"40.085280","reclong":"-86.055000","year":"1991-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[130.75,33.725]},"id":"16988","mass":"472","name":"Nogata","nametype":"Valid","recclass":"L6","reclat":"33.725000","reclong":"130.750000","year":"0861-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-59.83333,-32.36667]},"id":"16989","mass":"4000","name":"Nogoya","nametype":"Valid","recclass":"CM2","reclat":"-32.366670","reclong":"-59.833330","year":"1879-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"15",":@computed_region_nnqa_25f4":"10","fall":"Fell","geolocation":{"type":"Point","coordinates":[-92.26667,36.21667]},"id":"16994","mass":"1050","name":"Norfork","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"36.216670","reclong":"-92.266670","year":"1918-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1252","fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.86667,39.68333]},"id":"17922","mass":"1100000","name":"Norton County","nametype":"Valid","recclass":"Aubrite","reclat":"39.683330","reclong":"-99.866670","year":"1948-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.52722,45.29167]},"id":"17930","mass":"177","name":"Noventa Vicentina","nametype":"Valid","recclass":"H4","reclat":"45.291670","reclong":"11.527220","year":"1971-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[46,54.81667]},"id":"17933","mass":"1900","name":"Novo-Urei","nametype":"Valid","recclass":"Ureilite","reclat":"54.816670","reclong":"46.000000","year":"1886-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[31.33333,58.55]},"id":"17934","name":"Novy-Ergi","nametype":"Valid","recclass":"Stone-uncl","reclat":"58.550000","reclong":"31.333330","year":"1662-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22,56]},"id":"17935","mass":"1001","name":"Novy-Projekt","nametype":"Valid","recclass":"OC","reclat":"56.000000","reclong":"22.000000","year":"1908-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[102.46667,42.91667]},"id":"17936","mass":"250","name":"Noyan-Bogdo","nametype":"Valid","recclass":"L6","reclat":"42.916670","reclong":"102.466670","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-102.13333,24.3]},"id":"17938","mass":"50000","name":"Nuevo Mercurio","nametype":"Valid","recclass":"H5","reclat":"24.300000","reclong":"-102.133330","year":"1978-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.75,41.63333]},"id":"17959","mass":"5000","name":"Nulles","nametype":"Valid","recclass":"H6","reclat":"41.633330","reclong":"0.750000","year":"1851-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[141.86667,43.33333]},"id":"17960","mass":"363","name":"Numakai","nametype":"Valid","recclass":"H4","reclat":"43.333330","reclong":"141.866670","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[94.91667,21.20833]},"id":"17969","mass":"737.6","name":"Nyaung","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"21.208330","reclong":"94.916670","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.025,47.55]},"id":"17970","mass":"1100","name":"NyirΓ‘brany","nametype":"Valid","recclass":"LL5","reclat":"47.550000","reclong":"22.025000","year":"1914-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[55.26667,57.78333]},"id":"17979","mass":"500000","name":"Ochansk","nametype":"Valid","recclass":"H4","reclat":"57.783330","reclong":"55.266670","year":"1887-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.05,52.28333]},"id":"17988","mass":"1400","name":"Oesede","nametype":"Valid","recclass":"H5","reclat":"52.283330","reclong":"8.050000","year":"1927-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23,58.5]},"id":"17989","mass":"6000","name":"Oesel","nametype":"Valid","recclass":"L6","reclat":"58.500000","reclong":"23.000000","year":"1855-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.03333,47.88333]},"id":"17990","mass":"3750","name":"OfehΓ©rtΓ³","nametype":"Valid","recclass":"L6","reclat":"47.883330","reclong":"22.033330","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[130.2,33.28333]},"id":"17994","mass":"14360","name":"Ogi","nametype":"Valid","recclass":"H6","reclat":"33.283330","reclong":"130.200000","year":"1741-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23.58333,46.06667]},"id":"17995","mass":"16250","name":"Ohaba","nametype":"Valid","recclass":"H5","reclat":"46.066670","reclong":"23.583330","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.5,6.75]},"id":"17996","mass":"7700","name":"Ohuma","nametype":"Valid","recclass":"L5","reclat":"6.750000","reclong":"8.500000","year":"1963-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-5.4,38.18333]},"id":"17997","mass":"5850","name":"Ojuelos Altos","nametype":"Valid","recclass":"L6","reclat":"38.183330","reclong":"-5.400000","year":"1926-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[139.21667,36.18333]},"id":"17998","mass":"194","name":"Okabe","nametype":"Valid","recclass":"H5","reclat":"36.183330","reclong":"139.216670","year":"1958-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[135.2,35.08333]},"id":"18000","mass":"4742","name":"Okano","nametype":"Valid","recclass":"Iron, IIAB","reclat":"35.083330","reclong":"135.200000","year":"1904-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.5,50.83333]},"id":"18002","mass":"12000","name":"Okniny","nametype":"Valid","recclass":"LL6","reclat":"50.833330","reclong":"25.500000","year":"1834-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8.16667,52.95]},"id":"18009","mass":"16570","name":"Oldenburg (1930)","nametype":"Valid","recclass":"L6","reclat":"52.950000","reclong":"8.166670","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.03333,39]},"id":"18012","name":"Oliva-Gandia","nametype":"Valid","recclass":"Stone-uncl","reclat":"39.000000","reclong":"-0.033330","year":"1520-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.06667,38.71667]},"id":"18013","mass":"150000","name":"Olivenza","nametype":"Valid","recclass":"LL5","reclat":"38.716670","reclong":"-7.066670","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-2.1,39.56667]},"id":"18015","mass":"40000","name":"Olmedilla de AlarcΓ³n","nametype":"Valid","recclass":"H5","reclat":"39.566670","reclong":"-2.100000","year":"1929-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[161.80833,64.02]},"id":"18019","mass":"250000","name":"Omolon","nametype":"Valid","recclass":"Pallasite, PMG","reclat":"64.020000","reclong":"161.808330","year":"1981-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.38333,43.88333]},"id":"18026","mass":"14000","name":"Orgueil","nametype":"Valid","recclass":"CI1","reclat":"43.883330","reclong":"1.383330","year":"1864-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"30",":@computed_region_nnqa_25f4":"1078","fall":"Fell","geolocation":{"type":"Point","coordinates":[-81.36222,28.5475]},"id":"34489","mass":"180","name":"Orlando","nametype":"Valid","recclass":"Eucrite","reclat":"28.547500","reclong":"-81.362220","year":"2004-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.15,47.11667]},"id":"18030","mass":"6000","name":"Ornans","nametype":"Valid","recclass":"CO3.4","reclat":"47.116670","reclong":"6.150000","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[8,48.5]},"id":"18033","mass":"4500","name":"Ortenau","nametype":"Valid","recclass":"Stone-uncl","reclat":"48.500000","reclong":"8.000000","year":"1671-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.93333,42.13333]},"id":"18034","mass":"3400","name":"Orvinio","nametype":"Valid","recclass":"H6","reclat":"42.133330","reclong":"12.933330","year":"1872-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.4,58.88333]},"id":"18042","mass":"246","name":"OterΓΈy","nametype":"Valid","recclass":"L6","reclat":"58.883330","reclong":"9.400000","year":"1928-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[140.35,38.4]},"id":"18045","mass":"6510","name":"Otomi","nametype":"Valid","recclass":"H","reclat":"38.400000","reclong":"140.350000","year":"1867-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1947","fall":"Fell","geolocation":{"type":"Point","coordinates":[-95.21667,38.6]},"id":"18046","mass":"840","name":"Ottawa","nametype":"Valid","recclass":"LL6","reclat":"38.600000","reclong":"-95.216670","year":"1896-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.08,12.9]},"id":"56729","mass":"4440","name":"Ouadangou","nametype":"Valid","recclass":"L5","reclat":"12.900000","reclong":"0.080000","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.57717,30.18]},"id":"18050","mass":"1215.5","name":"Oued el Hadjar","nametype":"Valid","recclass":"LL6","reclat":"30.180000","reclong":"-6.577170","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-13.1,24.3]},"id":"31282","mass":"17000","name":"Oum Dreyga","nametype":"Valid","recclass":"H3-5","reclat":"24.300000","reclong":"-13.100000","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8.28,37.60833]},"id":"18052","mass":"20000","name":"Ourique","nametype":"Valid","recclass":"H4","reclat":"37.608330","reclong":"-8.280000","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16,-18]},"id":"18055","mass":"121.5","name":"Ovambo","nametype":"Valid","recclass":"L6","reclat":"-18.000000","reclong":"16.000000","year":"1900-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-5.86667,43.4]},"id":"18058","mass":"205","name":"Oviedo","nametype":"Valid","recclass":"H5","reclat":"43.400000","reclong":"-5.866670","year":"1856-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28.83333,51.33333]},"id":"18062","name":"Owrucz","nametype":"Valid","recclass":"OC","reclat":"51.333330","reclong":"28.833330","year":"1775-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.3,21.05]},"id":"18068","mass":"3400","name":"Pacula","nametype":"Valid","recclass":"L6","reclat":"21.050000","reclong":"-99.300000","year":"1881-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25,55.66667]},"id":"18069","mass":"3858","name":"Padvarninkai","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"55.666670","reclong":"25.000000","year":"1929-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[120.45583,17.74333]},"id":"18072","mass":"515","name":"Paitan","nametype":"Valid","recclass":"H6","reclat":"17.743330","reclong":"120.455830","year":"1910-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"32",":@computed_region_nnqa_25f4":"503","fall":"Fell","geolocation":{"type":"Point","coordinates":[-89.71667,32.31667]},"id":"18073","name":"Palahatchie","nametype":"Valid","recclass":"OC","reclat":"32.316670","reclong":"-89.716670","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-65.1,-23.11667]},"id":"18074","mass":"1430","name":"Palca de Aparzo","nametype":"Valid","recclass":"L5","reclat":"-23.116670","reclong":"-65.100000","year":"1988-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[118.61667,43.48333]},"id":"18077","mass":"18000","name":"Palinshih","nametype":"Valid","recclass":"Iron","reclat":"43.483330","reclong":"118.616670","year":"1914-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"2122","fall":"Fell","geolocation":{"type":"Point","coordinates":[-91.5,39.8]},"id":"18079","mass":"135","name":"Palmyra","nametype":"Valid","recclass":"L3","reclat":"39.800000","reclong":"-91.500000","year":"1926-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"4",":@computed_region_nnqa_25f4":"1657","fall":"Fell","geolocation":{"type":"Point","coordinates":[-157.78333,21.3]},"id":"18082","mass":"682","name":"Palolo Valley","nametype":"Valid","recclass":"H5","reclat":"21.300000","reclong":"-157.783330","year":"1949-01-01T00:00:00.000"} -,{"fall":"Found","id":"32591","mass":"69.5","name":"Dominion Range 03239","nametype":"Valid","recclass":"L6","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[120.7,15.08333]},"id":"18093","mass":"10500","name":"Pampanga","nametype":"Valid","recclass":"L5","reclat":"15.083330","reclong":"120.700000","year":"1859-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[124.28333,8.06667]},"id":"18098","mass":"2130","name":"Pantar","nametype":"Valid","recclass":"H5","reclat":"8.066670","reclong":"124.283330","year":"1938-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"15",":@computed_region_nnqa_25f4":"1023","fall":"Fell","geolocation":{"type":"Point","coordinates":[-90.5,36.06667]},"id":"18101","mass":"408000","name":"Paragould","nametype":"Valid","recclass":"LL5","reclat":"36.066670","reclong":"-90.500000","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-40.7,-6.23333]},"id":"18102","mass":"2000","name":"Parambu","nametype":"Valid","recclass":"LL5","reclat":"-6.233330","reclong":"-40.700000","year":"1967-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-51.66667,-19.13333]},"id":"18103","mass":"100000","name":"Paranaiba","nametype":"Valid","recclass":"L6","reclat":"-19.133330","reclong":"-51.666670","year":"1956-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"34",":@computed_region_nnqa_25f4":"1863","fall":"Fell","geolocation":{"type":"Point","coordinates":[-87.67917,41.48472]},"id":"18106","mass":"18000","name":"Park Forest","nametype":"Valid","recclass":"L5","reclat":"41.484720","reclong":"-87.679170","year":"2003-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.35,9.23333]},"id":"18108","mass":"77600","name":"Parnallee","nametype":"Valid","recclass":"LL3.6","reclat":"9.233330","reclong":"78.350000","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[85.4,26.2]},"id":"18109","mass":"800","name":"Parsa","nametype":"Valid","recclass":"EH3","reclat":"26.200000","reclong":"85.400000","year":"1942-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"11",":@computed_region_nnqa_25f4":"1994","fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.4,36.21667]},"id":"18110","mass":"5100","name":"Pasamonte","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"36.216670","reclong":"-103.400000","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.05,20.93694]},"id":"18112","mass":"4375","name":"Patora","nametype":"Valid","recclass":"H6","reclat":"20.936940","reclong":"82.050000","year":"1969-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-48.56667,-19.53333]},"id":"18116","mass":"2121","name":"Patrimonio","nametype":"Valid","recclass":"L6","reclat":"-19.533330","reclong":"-48.566670","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.96667,38.13333]},"id":"18118","mass":"12","name":"Patti","nametype":"Valid","recclass":"Iron","reclat":"38.133330","reclong":"14.966670","year":"1922-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[91.18333,23.15]},"id":"18171","mass":"37350","name":"Patwar","nametype":"Valid","recclass":"Mesosiderite-A1","reclat":"23.150000","reclong":"91.183330","year":"1935-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.51667,43.46667]},"id":"18173","mass":"2968","name":"Pavel","nametype":"Valid","recclass":"H5","reclat":"43.466670","reclong":"25.516670","year":"1966-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[77.03333,52.3]},"id":"18175","mass":"142.5","name":"Pavlodar (stone)","nametype":"Valid","recclass":"H5","reclat":"52.300000","reclong":"77.033330","year":"1938-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.98333,48.53333]},"id":"18176","mass":"40000","name":"Pavlograd","nametype":"Valid","recclass":"L6","reclat":"48.533330","reclong":"35.983330","year":"1826-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[43,52.03333]},"id":"18177","mass":"2000","name":"Pavlovka","nametype":"Valid","recclass":"Howardite","reclat":"52.033330","reclong":"43.000000","year":"1882-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.54217,11.33367]},"id":"18179","name":"PΓͺ","nametype":"Valid","recclass":"L6","reclat":"11.333670","reclong":"-3.542170","year":"1989-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-117.93333,56.13333]},"id":"18180","mass":"45760","name":"Peace River","nametype":"Valid","recclass":"L6","reclat":"56.133330","reclong":"-117.933330","year":"1963-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.25,51.66667]},"id":"18181","mass":"117.8","name":"Peckelsheim","nametype":"Valid","recclass":"Diogenite-pm","reclat":"51.666670","reclong":"9.250000","year":"1953-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"47",":@computed_region_nnqa_25f4":"2185","fall":"Fell","geolocation":{"type":"Point","coordinates":[-73.91667,41.28333]},"id":"18782","mass":"12570","name":"Peekskill","nametype":"Valid","recclass":"H6","reclat":"41.283330","reclong":"-73.916670","year":"1992-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"3062","fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.11667,30.125]},"id":"18786","mass":"70000","name":"PeΓ±a Blanca Spring","nametype":"Valid","recclass":"Aubrite","reclat":"30.125000","reclong":"-103.116670","year":"1946-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.5,-10.66667]},"id":"18792","mass":"165","name":"Peramiho","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"-10.666670","reclong":"35.500000","year":"1899-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[91,23.325]},"id":"18793","mass":"23474","name":"Perpeti","nametype":"Valid","recclass":"L6","reclat":"23.325000","reclong":"91.000000","year":"1935-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.43333,56.4]},"id":"18797","mass":"2","name":"Perth","nametype":"Valid","recclass":"LL5","reclat":"56.400000","reclong":"-3.433330","year":"1830-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[39.43333,56.63333]},"id":"18798","mass":"66000","name":"Pervomaisky","nametype":"Valid","recclass":"L6","reclat":"56.633330","reclong":"39.433330","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[66.08333,55.5]},"id":"18799","mass":"3393","name":"Pesyanoe","nametype":"Valid","recclass":"Aubrite","reclat":"55.500000","reclong":"66.083330","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.42,14.052]},"id":"18800","mass":"189","name":"PΓ©tΓ¨lkolΓ©","nametype":"Valid","recclass":"H5","reclat":"14.052000","reclong":"0.420000","year":"1995-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"39",":@computed_region_nnqa_25f4":"2017","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.63333,35.3]},"id":"18801","mass":"1800","name":"Petersburg","nametype":"Valid","recclass":"Eucrite-pmict","reclat":"35.300000","reclong":"-86.633330","year":"1855-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.33333,53.53333]},"id":"18804","name":"Pettiswood","nametype":"Valid","recclass":"Stone-uncl","reclat":"53.533330","reclong":"-7.333330","year":"1779-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"17",":@computed_region_nnqa_25f4":"1255","fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.25,40]},"id":"18808","mass":"57900","name":"Phillips County (stone)","nametype":"Valid","recclass":"L6","reclat":"40.000000","reclong":"-99.250000","year":"1901-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[108.58333,11.25]},"id":"18809","mass":"500","name":"Phu Hong","nametype":"Valid","recclass":"H4","reclat":"11.250000","reclong":"108.583330","year":"1887-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[105.48333,12]},"id":"18811","mass":"7800","name":"Phum Sambo","nametype":"Valid","recclass":"H4","reclat":"12.000000","reclong":"105.483330","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[108.1,15.71667]},"id":"18812","mass":"11000","name":"Phuoc-Binh","nametype":"Valid","recclass":"L5","reclat":"15.716670","reclong":"108.100000","year":"1941-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.50222,44.24417]},"id":"18813","mass":"13.1","name":"Piancaldoli","nametype":"Valid","recclass":"LL3.4","reclat":"44.244170","reclong":"11.502220","year":"1968-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6.23333,41.36667]},"id":"18816","name":"Picote","nametype":"Valid","recclass":"Stone-uncl","reclat":"41.366670","reclong":"-6.233330","year":"1843-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[25.73333,58.66667]},"id":"18822","mass":"23250","name":"Pillistfer","nametype":"Valid","recclass":"EL6","reclat":"58.666670","reclong":"25.733330","year":"1863-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[73.94167,26.03472]},"id":"18831","mass":"42000","name":"Piplia Kalan","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"26.034720","reclong":"73.941670","year":"1996-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[18.71667,-32.86667]},"id":"18832","mass":"37","name":"Piquetberg","nametype":"Valid","recclass":"H","reclat":"-32.866670","reclong":"18.716670","year":"1881-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[88.45,25.8]},"id":"18834","mass":"842","name":"Pirgunje","nametype":"Valid","recclass":"L6","reclat":"25.800000","reclong":"88.450000","year":"1882-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76,29.58333]},"id":"18835","mass":"1161","name":"Pirthalla","nametype":"Valid","recclass":"H6","reclat":"29.583330","reclong":"76.000000","year":"1884-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"31",":@computed_region_nnqa_25f4":"207","fall":"Fell","geolocation":{"type":"Point","coordinates":[-83.51667,31.95]},"id":"18837","mass":"3760","name":"Pitts","nametype":"Valid","recclass":"Iron, IAB-ung","reclat":"31.950000","reclong":"-83.516670","year":"1921-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"2018","fall":"Fell","geolocation":{"type":"Point","coordinates":[-96.11667,30.7]},"id":"18846","mass":"2085","name":"Plantersville","nametype":"Valid","recclass":"H6","reclat":"30.700000","reclong":"-96.116670","year":"1930-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.70972,45.275]},"id":"51706","mass":"6913","name":"Pleşcoi","nametype":"Valid","recclass":"L5-6","reclat":"45.275000","reclong":"26.709720","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.11667,50.53333]},"id":"18849","mass":"39","name":"Ploschkovitz","nametype":"Valid","recclass":"L5","reclat":"50.533330","reclong":"14.116670","year":"1723-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[104.91667,11.58333]},"id":"18851","mass":"96","name":"Pnompehn","nametype":"Valid","recclass":"L6","reclat":"11.583330","reclong":"104.916670","year":"1868-01-01T00:00:00.000"} -,{"fall":"Found","id":"32592","mass":"290.89999999999998","name":"Dominion Range 03240","nametype":"Valid","recclass":"LL5","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[12.13333,50.93333]},"id":"18853","mass":"3000","name":"Pohlitz","nametype":"Valid","recclass":"L5","reclat":"50.933330","reclong":"12.133330","year":"1819-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.66667,26.71667]},"id":"18858","mass":"350","name":"Pokhra","nametype":"Valid","recclass":"H5","reclat":"26.716670","reclong":"82.666670","year":"1866-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.015,66.34833]},"id":"18860","mass":"253.6","name":"Pollen","nametype":"Valid","recclass":"CM2","reclat":"66.348330","reclong":"14.015000","year":"1942-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-4.31944,53.03639]},"id":"18865","mass":"157","name":"Pontlyfni","nametype":"Valid","recclass":"Winonaite","reclat":"53.036390","reclong":"-4.319440","year":"1931-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"11",":@computed_region_nnqa_25f4":"1987","fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.295,34.175]},"id":"18874","mass":"71400","name":"Portales Valley","nametype":"Valid","recclass":"H6","reclat":"34.175000","reclong":"-103.295000","year":"1998-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-8,38.5]},"id":"18876","mass":"4500","name":"Portugal","nametype":"Valid","recclass":"Stone-uncl","reclat":"38.500000","reclong":"-8.000000","year":"1796-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[118.5,31.41667]},"id":"18879","mass":"665","name":"Po-wang Chen","nametype":"Valid","recclass":"LL","reclat":"31.416670","reclong":"118.500000","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13.94083,48.3025]},"id":"18883","mass":"2125","name":"Prambachkirchen","nametype":"Valid","recclass":"L6","reclat":"48.302500","reclong":"13.940830","year":"1932-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.03333,49.66667]},"id":"18887","mass":"5555","name":"Pribram","nametype":"Valid","recclass":"H5","reclat":"49.666670","reclong":"14.033330","year":"1959-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"38",":@computed_region_nnqa_25f4":"2566","fall":"Fell","geolocation":{"type":"Point","coordinates":[-83.85,39.11667]},"id":"18888","mass":"900","name":"Pricetown","nametype":"Valid","recclass":"L6","reclat":"39.116670","reclong":"-83.850000","year":"1893-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.51667,39.35]},"id":"45984","mass":"500","name":"Puerto LΓ‘pice","nametype":"Valid","recclass":"Eucrite-br","reclat":"39.350000","reclong":"-3.516670","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[75.18333,23.36667]},"id":"18899","mass":"560","name":"Pulsora","nametype":"Valid","recclass":"H5","reclat":"23.366670","reclong":"75.183330","year":"1863-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.26667,52.76667]},"id":"18901","mass":"250000","name":"Pultusk","nametype":"Valid","recclass":"H5","reclat":"52.766670","reclong":"21.266670","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.95,13.33333]},"id":"18902","mass":"100","name":"Punganaru","nametype":"Valid","recclass":"Stone-uncl","reclat":"13.333330","reclong":"78.950000","year":"1811-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-53.05,-29.03333]},"id":"18905","mass":"300000","name":"Putinga","nametype":"Valid","recclass":"L6","reclat":"-29.033330","reclong":"-53.050000","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[121.5,32.08333]},"id":"18907","mass":"1275","name":"Qidong","nametype":"Valid","recclass":"L/LL5","reclat":"32.083330","reclong":"121.500000","year":"1982-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[106.46667,26.53333]},"id":"18908","mass":"2600","name":"Qingzhen","nametype":"Valid","recclass":"EH3","reclat":"26.533330","reclong":"106.466670","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[28.7,-30.11667]},"id":"22357","mass":"7000","name":"Queen's Mercy","nametype":"Valid","recclass":"H6","reclat":"-30.116670","reclong":"28.700000","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[95.18333,17.76667]},"id":"22358","mass":"6045","name":"Quenggouk","nametype":"Valid","recclass":"H4","reclat":"17.766670","reclong":"95.183330","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.66667,39]},"id":"22360","mass":"10750","name":"Quesa","nametype":"Valid","recclass":"Iron, IAB-ung","reclat":"39.000000","reclong":"-0.666670","year":"1898-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[126.13333,44.61667]},"id":"22361","mass":"17450","name":"Quija","nametype":"Valid","recclass":"H","reclat":"44.616670","reclong":"126.133330","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.25,46.6]},"id":"22363","mass":"65","name":"Quincay","nametype":"Valid","recclass":"L6","reclat":"46.600000","reclong":"0.250000","year":"1851-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-65.45,-26.66667]},"id":"22368","mass":"5000","name":"Raco","nametype":"Valid","recclass":"H5","reclat":"-26.666670","reclong":"-65.450000","year":"1957-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.465,27.72528]},"id":"22371","mass":"10200","name":"Raghunathpura","nametype":"Valid","recclass":"Iron, IIAB","reclat":"27.725280","reclong":"76.465000","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[70.2,28.225]},"id":"31302","mass":"67225","name":"Rahimyar Khan","nametype":"Valid","recclass":"L5","reclat":"28.225000","reclong":"70.200000","year":"1983-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.03333,52.98333]},"id":"22376","mass":"9000","name":"Rakovka","nametype":"Valid","recclass":"L6","reclat":"52.983330","reclong":"37.033330","year":"1878-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.9,26.45]},"id":"22384","mass":"3766","name":"Ramnagar","nametype":"Valid","recclass":"L6","reclat":"26.450000","reclong":"82.900000","year":"1940-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[87.76667,24.16667]},"id":"22385","mass":"100","name":"Rampurhat","nametype":"Valid","recclass":"LL","reclat":"24.166670","reclong":"87.766670","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[6.93333,51.88333]},"id":"22386","mass":"4682","name":"Ramsdorf","nametype":"Valid","recclass":"L6","reclat":"51.883330","reclong":"6.933330","year":"1958-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[87.08333,23.98333]},"id":"22387","mass":"290.39999999999998","name":"Ranchapur","nametype":"Valid","recclass":"H4","reclat":"23.983330","reclong":"87.083330","year":"1917-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-100.81667,19.86667]},"id":"22390","mass":"300","name":"Rancho de la Presa","nametype":"Valid","recclass":"H5","reclat":"19.866670","reclong":"-100.816670","year":"1899-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[72.01667,25.38333]},"id":"22392","mass":"3224.5","name":"Rangala","nametype":"Valid","recclass":"L6","reclat":"25.383330","reclong":"72.016670","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[115.7,38.2]},"id":"22394","mass":"4910","name":"Raoyang","nametype":"Valid","recclass":"L6","reclat":"38.200000","reclong":"115.700000","year":"1919-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[50.15,26.66667]},"id":"22395","mass":"6.1","name":"Ras Tanura","nametype":"Valid","recclass":"H6","reclat":"26.666670","reclong":"50.150000","year":"1961-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.53333,43.5]},"id":"22396","mass":"24700","name":"Rasgrad","nametype":"Valid","recclass":"Stone-uncl","reclat":"43.500000","reclong":"26.533330","year":"1740-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[17.98333,52.2]},"id":"22398","mass":"910","name":"Ratyn","nametype":"Valid","recclass":"Stone-uncl","reclat":"52.200000","reclong":"17.983330","year":"1880-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"8",":@computed_region_nnqa_25f4":"1391","fall":"Fell","geolocation":{"type":"Point","coordinates":[-119.75812,38.13742]},"id":"53502","mass":"18.41","name":"Red Canyon Lake","nametype":"Valid","recclass":"H5","reclat":"38.137420","reclong":"-119.758120","year":"2007-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-5.33333,42.475]},"id":"22584","mass":"17300","name":"Reliegos","nametype":"Valid","recclass":"L5","reclat":"42.475000","reclong":"-5.333330","year":"1947-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.36667,-6.73333]},"id":"22585","mass":"10000","name":"Rembang","nametype":"Valid","recclass":"Iron, IVA","reclat":"-6.733330","reclong":"111.366670","year":"1919-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.28333,44.76667]},"id":"22586","mass":"1000","name":"Renazzo","nametype":"Valid","recclass":"CR2","reclat":"44.766670","reclong":"11.283330","year":"1824-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-65.28333,-32.75]},"id":"22587","mass":"300","name":"Renca","nametype":"Valid","recclass":"L5","reclat":"-32.750000","reclong":"-65.283330","year":"1925-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[116.13333,38.66667]},"id":"22589","mass":"355","name":"Renqiu","nametype":"Valid","recclass":"L6","reclat":"38.666670","reclong":"116.133330","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[45.66667,48.6]},"id":"22590","mass":"7000","name":"Repeev Khutor","nametype":"Valid","recclass":"Iron, IIF","reclat":"48.600000","reclong":"45.666670","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-118.95,51.33333]},"id":"22592","mass":"1","name":"Revelstoke","nametype":"Valid","recclass":"CI1","reclat":"51.333330","reclong":"-118.950000","year":"1965-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[76.66667,28.2]},"id":"22593","mass":"3332","name":"Rewari","nametype":"Valid","recclass":"L6","reclat":"28.200000","reclong":"76.666670","year":"1929-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"37",":@computed_region_nnqa_25f4":"2388","fall":"Fell","geolocation":{"type":"Point","coordinates":[-83.03333,35.03333]},"id":"22597","mass":"668","name":"Rich Mountain","nametype":"Valid","recclass":"L6","reclat":"35.033330","reclong":"-83.033330","year":"1903-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-66.15,-44.11667]},"id":"24140","mass":"20000","name":"Uzcudun","nametype":"Valid","recclass":"L","reclat":"-44.116670","reclong":"-66.150000","year":"1948-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"3",":@computed_region_nnqa_25f4":"569","fall":"Fell","geolocation":{"type":"Point","coordinates":[-102.31667,46.88333]},"id":"22599","mass":"90000","name":"Richardton","nametype":"Valid","recclass":"H5","reclat":"46.883330","reclong":"-102.316670","year":"1918-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"23",":@computed_region_nnqa_25f4":"2885","fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.03333,31.25]},"id":"22602","mass":"1900","name":"Richland Springs","nametype":"Valid","recclass":"OC","reclat":"31.250000","reclong":"-99.033330","year":"1980-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"40",":@computed_region_nnqa_25f4":"2764","fall":"Fell","geolocation":{"type":"Point","coordinates":[-77.5,37.46667]},"id":"22603","mass":"1800","name":"Richmond","nametype":"Valid","recclass":"LL5","reclat":"37.466670","reclong":"-77.500000","year":"1828-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-49.8,-26.1]},"id":"22611","mass":"1310","name":"Rio Negro","nametype":"Valid","recclass":"L4","reclat":"-26.100000","reclong":"-49.800000","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.51667,45.48333]},"id":"22614","mass":"103.3","name":"Rivolta de Bassi","nametype":"Valid","recclass":"Stone-uncl","reclat":"45.483330","reclong":"9.516670","year":"1491-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"35",":@computed_region_nnqa_25f4":"150","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.28333,41.08333]},"id":"22637","mass":"340","name":"Rochester","nametype":"Valid","recclass":"H6","reclat":"41.083330","reclong":"-86.283330","year":"1876-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[150.51667,-23.38333]},"id":"22640","mass":"1641","name":"Rockhampton","nametype":"Valid","recclass":"Stone-uncl","reclat":"-23.383330","reclong":"150.516670","year":"1895-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.55,42.3]},"id":"22641","mass":"400","name":"Roda","nametype":"Valid","recclass":"Diogenite","reclat":"42.300000","reclong":"0.550000","year":"1871-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.8,50.35]},"id":"22642","mass":"2900","name":"Rodach","nametype":"Valid","recclass":"Stone-uncl","reclat":"50.350000","reclong":"10.800000","year":"1775-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"50",":@computed_region_nnqa_25f4":"361","fall":"Fell","geolocation":{"type":"Point","coordinates":[-83.95,44.51667]},"id":"22766","mass":"10600","name":"Rose City","nametype":"Valid","recclass":"H5","reclat":"44.516670","reclong":"-83.950000","year":"1921-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-2.51667,52.76667]},"id":"22773","mass":"3500","name":"Rowton","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"52.766670","reclong":"-2.516670","year":"1876-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.83333,-1.45]},"id":"22780","mass":"465.5","name":"Ruhobobo","nametype":"Valid","recclass":"L6","reclat":"-1.450000","reclong":"29.833330","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[36.53333,0.26667]},"id":"22782","mass":"67","name":"Rumuruti","nametype":"Valid","recclass":"R3.8-6","reclat":"0.266670","reclong":"36.533330","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[38.76667,-10.26667]},"id":"22783","mass":"6000","name":"Rupota","nametype":"Valid","recclass":"L4-6","reclat":"-10.266670","reclong":"38.766670","year":"1949-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[34.5,51.13333]},"id":"22791","mass":"13000","name":"Ryechki","nametype":"Valid","recclass":"L5","reclat":"51.133330","reclong":"34.500000","year":"1914-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.08333,27.43333]},"id":"22792","mass":"1250","name":"Sabetmahet","nametype":"Valid","recclass":"H5","reclat":"27.433330","reclong":"82.083330","year":"1855-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[91.66667,23.08333]},"id":"22793","mass":"478","name":"Sabrum","nametype":"Valid","recclass":"LL6","reclat":"23.083330","reclong":"91.666670","year":"1999-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.88333,51.53333]},"id":"22796","name":"Sagan","nametype":"Valid","recclass":"Stone-uncl","reclat":"51.533330","reclong":"14.883330","year":"1636-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.38333,43.73333]},"id":"23101","mass":"14000","name":"Saint-Sauveur","nametype":"Valid","recclass":"EH5","reclat":"43.733330","reclong":"1.383330","year":"1914-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.23333,45.3]},"id":"23102","mass":"271000","name":"Saint-SΓ©verin","nametype":"Valid","recclass":"LL6","reclat":"45.300000","reclong":"0.233330","year":"1966-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.3,35.66667]},"id":"23103","mass":"4180","name":"Sakauchi","nametype":"Valid","recclass":"Iron","reclat":"35.666670","reclong":"136.300000","year":"1913-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"12",":@computed_region_nnqa_25f4":"2409","fall":"Fell","geolocation":{"type":"Point","coordinates":[-122.96944,44.97917]},"id":"23107","mass":"61.4","name":"Salem","nametype":"Valid","recclass":"L6","reclat":"44.979170","reclong":"-122.969440","year":"1981-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4.63333,46.05]},"id":"23111","mass":"9000","name":"Salles","nametype":"Valid","recclass":"L5","reclat":"46.050000","reclong":"4.633330","year":"1798-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.05,52.75]},"id":"23114","mass":"43","name":"Salzwedel","nametype":"Valid","recclass":"LL5","reclat":"52.750000","reclong":"11.050000","year":"1985-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[74.86667,25.66667]},"id":"23115","mass":"2462","name":"Samelia","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"25.666670","reclong":"74.866670","year":"1921-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"8",":@computed_region_nnqa_25f4":"1174","fall":"Fell","geolocation":{"type":"Point","coordinates":[-117.6625,33.48472]},"id":"23128","mass":"56","name":"San Juan Capistrano","nametype":"Valid","recclass":"H6","reclat":"33.484720","reclong":"-117.662500","year":"1973-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[13,43.66667]},"id":"31315","mass":"237","name":"San Michele","nametype":"Valid","recclass":"L6","reclat":"43.666670","reclong":"13.000000","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-71.4,-31.01667]},"id":"23130","mass":"282","name":"San Pedro de Quiles","nametype":"Valid","recclass":"L6","reclat":"-31.016670","reclong":"-71.400000","year":"1956-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-100.65,19.76667]},"id":"34063","mass":"460","name":"San Pedro Jacuaro","nametype":"Valid","recclass":"LL6","reclat":"19.766670","reclong":"-100.650000","year":"1968-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-51.86667,-29.2]},"id":"23161","mass":"400","name":"Santa Barbara","nametype":"Valid","recclass":"L4","reclat":"-29.200000","reclong":"-51.866670","year":"1873-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-99.33333,24.16667]},"id":"23164","mass":"60","name":"Santa Cruz","nametype":"Valid","recclass":"CM2","reclat":"24.166670","reclong":"-99.333330","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-61.7,-33.9]},"id":"23165","mass":"5500","name":"Santa Isabel","nametype":"Valid","recclass":"L6","reclat":"-33.900000","reclong":"-61.700000","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-68.489444,-31.535556]},"id":"50909","mass":"4000","name":"Santa Lucia (2008)","nametype":"Valid","recclass":"L6","reclat":"-31.535556","reclong":"-68.489444","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-49.38056,-20.81]},"id":"23171","mass":"927","name":"SΓ£o Jose do Rio Preto","nametype":"Valid","recclass":"H4","reclat":"-20.810000","reclong":"-49.380560","year":"1962-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[46.55,52.55]},"id":"23176","mass":"200000","name":"Saratov","nametype":"Valid","recclass":"L4","reclat":"52.550000","reclong":"46.550000","year":"1918-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[137.78333,34.71667]},"id":"23187","mass":"695","name":"Sasagase","nametype":"Valid","recclass":"H","reclat":"34.716670","reclong":"137.783330","year":"1688-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.85,43.15]},"id":"23188","mass":"4000","name":"Sauguis","nametype":"Valid","recclass":"L6","reclat":"43.150000","reclong":"-0.850000","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[29.86667,47.21667]},"id":"23190","mass":"2500","name":"Savtschenskoje","nametype":"Valid","recclass":"LL4","reclat":"47.216670","reclong":"29.866670","year":"1894-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[139.4,35.86667]},"id":"23192","mass":"430","name":"Sayama","nametype":"Valid","recclass":"CM2","reclat":"35.866670","reclong":"139.400000","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[17.56667,49.23333]},"id":"23455","mass":"412","name":"Sazovice","nametype":"Valid","recclass":"L5","reclat":"49.233330","reclong":"17.566670","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.05,53.35]},"id":"23457","mass":"7000","name":"Schellin","nametype":"Valid","recclass":"L","reclat":"53.350000","reclong":"15.050000","year":"1715-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"47",":@computed_region_nnqa_25f4":"2142","fall":"Fell","geolocation":{"type":"Point","coordinates":[-73.95028,42.86083]},"id":"23458","mass":"283.3","name":"Schenectady","nametype":"Valid","recclass":"H5","reclat":"42.860830","reclong":"-73.950280","year":"1968-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.46667,48.11667]},"id":"23460","mass":"8000","name":"SchΓΆnenberg","nametype":"Valid","recclass":"L6","reclat":"48.116670","reclong":"10.466670","year":"1846-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"49",":@computed_region_nnqa_25f4":"1727","fall":"Fell","geolocation":{"type":"Point","coordinates":[-69.2,44.36667]},"id":"23472","mass":"5400","name":"Searsmont","nametype":"Valid","recclass":"H5","reclat":"44.366670","reclong":"-69.200000","year":"1871-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.13333,38.3]},"id":"23473","mass":"240","name":"SedikΓΆy","nametype":"Valid","recclass":"L6","reclat":"38.300000","reclong":"27.133330","year":"1917-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.78333,26.75]},"id":"23476","mass":"6930","name":"Segowlie","nametype":"Valid","recclass":"LL6","reclat":"26.750000","reclong":"84.783330","year":"1853-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[107.33333,-7.23333]},"id":"23481","mass":"1590","name":"Selakopi","nametype":"Valid","recclass":"H5","reclat":"-7.233330","reclong":"107.333330","year":"1939-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[4.98333,22.83333]},"id":"23483","mass":"150","name":"Seldebourak","nametype":"Valid","recclass":"H5","reclat":"22.833330","reclong":"4.983330","year":"1947-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[79,22.25]},"id":"23487","mass":"691","name":"Semarkona","nametype":"Valid","recclass":"LL3.00","reclat":"22.250000","reclong":"79.000000","year":"1940-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-0.05,41.71667]},"id":"23495","mass":"4000","name":"Sena","nametype":"Valid","recclass":"H4","reclat":"41.716670","reclong":"-0.050000","year":"1773-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[140.51167,39.43833]},"id":"23496","mass":"866","name":"Senboku","nametype":"Valid","recclass":"H6","reclat":"39.438330","reclong":"140.511670","year":"1993-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[79.50083,21.68389]},"id":"23500","mass":"20000","name":"Seoni","nametype":"Valid","recclass":"H6","reclat":"21.683890","reclong":"79.500830","year":"1966-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23.56667,41.05]},"id":"23501","mass":"8500","name":"Seres","nametype":"Valid","recclass":"H4","reclat":"41.050000","reclong":"23.566670","year":"1818-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-36.76667,-8.38333]},"id":"23502","mass":"1800","name":"Serra de MagΓ©","nametype":"Valid","recclass":"Eucrite-cm","reclat":"-8.383330","reclong":"-36.766670","year":"1923-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-44.21667,-19.46667]},"id":"23504","mass":"350","name":"Sete Lagoas","nametype":"Valid","recclass":"H4","reclat":"-19.466670","reclong":"-44.216670","year":"1908-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-6,37.41667]},"id":"23508","mass":"180","name":"Sevilla","nametype":"Valid","recclass":"LL4","reclat":"37.416670","reclong":"-6.000000","year":"1862-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[36.6,50.61667]},"id":"23509","mass":"101000","name":"Sevrukovo","nametype":"Valid","recclass":"L5","reclat":"50.616670","reclong":"36.600000","year":"1874-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.71667,34.75]},"id":"23512","mass":"7000","name":"Sfax","nametype":"Valid","recclass":"L6","reclat":"34.750000","reclong":"10.716670","year":"1989-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[87.3,23.1]},"id":"23521","mass":"4000","name":"Shalka","nametype":"Valid","recclass":"Diogenite","reclat":"23.100000","reclong":"87.300000","year":"1850-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"40",":@computed_region_nnqa_25f4":"921","fall":"Fell","geolocation":{"type":"Point","coordinates":[-76.7,37.83333]},"id":"23525","mass":"1265","name":"Sharps","nametype":"Valid","recclass":"H3.4","reclat":"37.833330","reclong":"-76.700000","year":"1921-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-80.16667,44.05]},"id":"23529","mass":"18600","name":"Shelburne","nametype":"Valid","recclass":"L5","reclat":"44.050000","reclong":"-80.166670","year":"1904-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.83333,24.55]},"id":"23530","mass":"5000","name":"Shergotty","nametype":"Valid","recclass":"Martian (shergottite)","reclat":"24.550000","reclong":"84.833330","year":"1865-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[120.06667,33.65]},"id":"23531","mass":"605","name":"Sheyang","nametype":"Valid","recclass":"L6","reclat":"33.650000","reclong":"120.066670","year":"1976-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[87.5775,25.85]},"id":"23534","mass":"3679.7","name":"Shikarpur","nametype":"Valid","recclass":"L6","reclat":"25.850000","reclong":"87.577500","year":"1921-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[125.66667,43.5]},"id":"23582","mass":"3900","name":"Shuangyang","nametype":"Valid","recclass":"H5","reclat":"43.500000","reclong":"125.666670","year":"1971-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[74.83333,33.71667]},"id":"23583","mass":"5000","name":"Shupiyan","nametype":"Valid","recclass":"H6","reclat":"33.716670","reclong":"74.833330","year":"1912-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[90.16667,24.33333]},"id":"23584","mass":"3200","name":"Shytal","nametype":"Valid","recclass":"L6","reclat":"24.333330","reclong":"90.166670","year":"1863-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[11.6,43.11667]},"id":"23586","mass":"3700","name":"Siena","nametype":"Valid","recclass":"LL5","reclat":"43.116670","reclong":"11.600000","year":"1794-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[134.65333,46.16]},"id":"23593","mass":"23000000","name":"Sikhote-Alin","nametype":"Valid","recclass":"Iron, IIAB","reclat":"46.160000","reclong":"134.653330","year":"1947-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-101.38333,20.93333]},"id":"23594","mass":"1710","name":"Silao","nametype":"Valid","recclass":"H5","reclat":"20.933330","reclong":"-101.383330","year":"1995-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.26667,44.11667]},"id":"55584","mass":"0.15","name":"Silistra","nametype":"Valid","recclass":"Achondrite-ung","reclat":"44.116670","reclong":"27.266670","year":"1917-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[7.53333,49.98333]},"id":"23603","mass":"1222","name":"Simmern","nametype":"Valid","recclass":"H5","reclat":"49.983330","reclong":"7.533330","year":"1920-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[32.48333,30.9]},"id":"23606","mass":"1455","name":"Sinai","nametype":"Valid","recclass":"L6","reclat":"30.900000","reclong":"32.483330","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[69.55,26.21667]},"id":"23611","mass":"8400","name":"Sindhri","nametype":"Valid","recclass":"H5","reclat":"26.216670","reclong":"69.550000","year":"1901-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.2,39.3]},"id":"23613","mass":"2000","name":"Sinnai","nametype":"Valid","recclass":"H6","reclat":"39.300000","reclong":"9.200000","year":"1956-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"19",":@computed_region_nnqa_25f4":"2351","fall":"Fell","geolocation":{"type":"Point","coordinates":[-103.66667,42.58333]},"id":"23614","mass":"4100","name":"Sioux County","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"42.583330","reclong":"-103.666670","year":"1933-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[82.58333,20.91667]},"id":"23616","mass":"1600","name":"Sitathali","nametype":"Valid","recclass":"H5","reclat":"20.916670","reclong":"82.583330","year":"1875-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[36.13583,39.82467]},"id":"23617","mass":"40000","name":"Sivas","nametype":"Valid","recclass":"H6","reclat":"39.824670","reclong":"36.135830","year":"1989-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[119.86667,32.43333]},"id":"23619","mass":"630","name":"Sixiangkou","nametype":"Valid","recclass":"L5","reclat":"32.433330","reclong":"119.866670","year":"1989-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.86667,59.73333]},"id":"23621","mass":"850","name":"Ski","nametype":"Valid","recclass":"L6","reclat":"59.733330","reclong":"10.866670","year":"1848-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.6,45.68333]},"id":"23626","mass":"1708","name":"Slavetic","nametype":"Valid","recclass":"H5","reclat":"45.683330","reclong":"15.600000","year":"1868-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35,55]},"id":"23645","mass":"2750","name":"Slobodka","nametype":"Valid","recclass":"L4","reclat":"55.000000","reclong":"35.000000","year":"1818-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.06667,27.13333]},"id":"23660","mass":"72.900000000000006","name":"Soheria","nametype":"Valid","recclass":"OC","reclat":"27.133330","reclong":"84.066670","year":"1960-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[21.86667,43.66667]},"id":"23661","mass":"80000","name":"Soko-Banja","nametype":"Valid","recclass":"LL4","reclat":"43.666670","reclong":"21.866670","year":"1877-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.73333,47.36667]},"id":"23663","mass":"54","name":"Sologne","nametype":"Valid","recclass":"H5","reclat":"47.366670","reclong":"1.733330","year":"1860-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[22.005,54.00883]},"id":"53829","mass":"1066","name":"SoΕ‚tmany","nametype":"Valid","recclass":"L6","reclat":"54.008830","reclong":"22.005000","year":"2011-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[135.33333,35.16667]},"id":"23667","mass":"17100","name":"Sone","nametype":"Valid","recclass":"H5","reclat":"35.166670","reclong":"135.333330","year":"1866-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[125,45.25]},"id":"23668","mass":"36900","name":"Songyuan","nametype":"Valid","recclass":"L6","reclat":"45.250000","reclong":"125.000000","year":"1993-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23.5,44.41667]},"id":"23670","mass":"958","name":"Sopot","nametype":"Valid","recclass":"OC","reclat":"44.416670","reclong":"23.500000","year":"1927-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[33.63333,1.7]},"id":"23671","mass":"2050","name":"Soroti","nametype":"Valid","recclass":"Iron, ungrouped","reclat":"1.700000","reclong":"33.633330","year":"1945-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[0.05,44.75]},"id":"23081","mass":"360","name":"St. Caprais-de-Quinsac","nametype":"Valid","recclass":"L6","reclat":"44.750000","reclong":"0.050000","year":"1883-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.5,46.95]},"id":"23082","mass":"5500","name":"St. Christophe-la-Chartreuse","nametype":"Valid","recclass":"L6","reclat":"46.950000","reclong":"-1.500000","year":"1841-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.75,51.05]},"id":"23083","mass":"700","name":"St. Denis Westrem","nametype":"Valid","recclass":"L6","reclat":"51.050000","reclong":"3.750000","year":"1855-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-1.15,48.01667]},"id":"23087","mass":"4000","name":"St. Germain-du-Pinel","nametype":"Valid","recclass":"H6","reclat":"48.016670","reclong":"-1.150000","year":"1890-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"18",":@computed_region_nnqa_25f4":"2223","fall":"Fell","geolocation":{"type":"Point","coordinates":[-90.23333,38.7]},"id":"23089","mass":"1000","name":"St. Louis","nametype":"Valid","recclass":"H4","reclat":"38.700000","reclong":"-90.233330","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.41667,-32.01667]},"id":"23090","mass":"13780","name":"St. Mark's","nametype":"Valid","recclass":"EH5","reclat":"-32.016670","reclong":"27.416670","year":"1903-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"45",":@computed_region_nnqa_25f4":"424","fall":"Fell","geolocation":{"type":"Point","coordinates":[-76.38333,38.16667]},"id":"23091","mass":"24.3","name":"St. Mary's County","nametype":"Valid","recclass":"LL3.3","reclat":"38.166670","reclong":"-76.383330","year":"1919-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3.93333,48.45]},"id":"23092","mass":"8300","name":"St. Mesmin","nametype":"Valid","recclass":"LL6","reclat":"48.450000","reclong":"3.933330","year":"1866-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.2,61.65]},"id":"23093","mass":"17000","name":"St. Michel","nametype":"Valid","recclass":"L6","reclat":"61.650000","reclong":"27.200000","year":"1910-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[2.95,43.43333]},"id":"23097","mass":"134.30000000000001","name":"St.-Chinian","nametype":"Valid","recclass":"L6","reclat":"43.433330","reclong":"2.950000","year":"1959-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.95,59.93333]},"id":"23712","mass":"34000","name":"StΓ€lldalen","nametype":"Valid","recclass":"H5","reclat":"59.933330","reclong":"14.950000","year":"1876-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[15.56667,49.28333]},"id":"23713","mass":"52000","name":"Stannern","nametype":"Valid","recclass":"Eucrite-mmict","reclat":"49.283330","reclong":"15.566670","year":"1808-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[41.98333,45.05]},"id":"23717","mass":"1500","name":"Stavropol","nametype":"Valid","recclass":"L6","reclat":"45.050000","reclong":"41.983330","year":"1857-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[3,50.76667]},"id":"23099","mass":"4960","name":"Ste. Marguerite","nametype":"Valid","recclass":"H4","reclat":"50.766670","reclong":"3.000000","year":"1962-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[55.98333,53.66667]},"id":"23724","mass":"325000","name":"Sterlitamak","nametype":"Valid","recclass":"Iron, IIIAB","reclat":"53.666670","reclong":"55.983330","year":"1990-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[9.05,52.53333]},"id":"23726","name":"Stolzenau","nametype":"Valid","recclass":"Stone-uncl","reclat":"52.533330","reclong":"9.050000","year":"1647-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"24",":@computed_region_nnqa_25f4":"1040","fall":"Fell","geolocation":{"type":"Point","coordinates":[-73.13333,41.2]},"id":"23728","mass":"50","name":"Stratford","nametype":"Valid","recclass":"L6","reclat":"41.200000","reclong":"-73.133330","year":"1974-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.25,56.58333]},"id":"23729","mass":"13400","name":"Strathmore","nametype":"Valid","recclass":"L6","reclat":"56.583330","reclong":"-3.250000","year":"1917-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-3.95,50.38333]},"id":"23732","mass":"10400","name":"Stretchleigh","nametype":"Valid","recclass":"Stone-uncl","reclat":"50.383330","reclong":"-3.950000","year":"1623-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-72.97806,45.96861]},"id":"23733","mass":"25400","name":"St-Robert","nametype":"Valid","recclass":"H5","reclat":"45.968610","reclong":"-72.978060","year":"1994-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"15",":@computed_region_nnqa_25f4":"955","fall":"Fell","geolocation":{"type":"Point","coordinates":[-90.66667,36.48333]},"id":"23736","mass":"3500","name":"Success","nametype":"Valid","recclass":"L6","reclat":"36.483330","reclong":"-90.666670","year":"1924-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[16.26333,50.53806]},"id":"23737","mass":"815.3","name":"Suchy Dul","nametype":"Valid","recclass":"L6","reclat":"50.538060","reclong":"16.263330","year":"1969-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[113.46667,31.61667]},"id":"23738","mass":"260000","name":"Suizhou","nametype":"Valid","recclass":"L6","reclat":"31.616670","reclong":"113.466670","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[78.03333,12.66667]},"id":"48951","mass":"110000","name":"Sulagiri","nametype":"Valid","recclass":"LL6","reclat":"12.666670","reclong":"78.033330","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.28333,25.93333]},"id":"23741","mass":"1710.5","name":"Sultanpur","nametype":"Valid","recclass":"L/LL6","reclat":"25.933330","reclong":"84.283330","year":"1916-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[133.16667,44.86667]},"id":"23745","mass":"637","name":"Sungach","nametype":"Valid","recclass":"H5","reclat":"44.866670","reclong":"133.166670","year":"1935-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[84.21667,26.71667]},"id":"23760","mass":"7235","name":"Supuhee","nametype":"Valid","recclass":"H6","reclat":"26.716670","reclong":"84.216670","year":"1865-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"8",":@computed_region_nnqa_25f4":"1187","fall":"Fell","geolocation":{"type":"Point","coordinates":[-120.90806,38.80389]},"id":"55529","mass":"992.5","name":"Sutter's Mill","nametype":"Valid","recclass":"C","reclat":"38.803890","reclong":"-120.908060","year":"2012-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"29",":@computed_region_nnqa_25f4":"1637","fall":"Fell","geolocation":{"type":"Point","coordinates":[-86.2945,33.18836]},"id":"23773","mass":"5560","name":"Sylacauga","nametype":"Valid","recclass":"H4","reclat":"33.188360","reclong":"-86.294500","year":"1954-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[14.65,49.4]},"id":"23776","mass":"7540","name":"Tabor","nametype":"Valid","recclass":"H5","reclat":"49.400000","reclong":"14.650000","year":"1753-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[5.41667,36.18333]},"id":"23778","mass":"9000","name":"Tadjera","nametype":"Valid","recclass":"L5","reclat":"36.183330","reclong":"5.416670","year":"1867-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-134.20139,59.70444]},"id":"23782","mass":"10000","name":"Tagish Lake","nametype":"Valid","recclass":"C2-ung","reclat":"59.704440","reclong":"-134.201390","year":"2000-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[137.305,34.72]},"id":"23784","mass":"1000","name":"Tahara","nametype":"Valid","recclass":"H4/5","reclat":"34.720000","reclong":"137.305000","year":"1991-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[134.9,35.38333]},"id":"23789","mass":"720","name":"Takenouchi","nametype":"Valid","recclass":"H5","reclat":"35.383330","reclong":"134.900000","year":"1880-01-01T00:00:00.000"} -,{"fall":"Fell","id":"23791","mass":"1421","name":"Talampaya","nametype":"Valid","recclass":"Eucrite-cm","year":"1995-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[112.76667,-7.75]},"id":"23795","mass":"10500","name":"Tambakwatu","nametype":"Valid","recclass":"L6","reclat":"-7.750000","reclong":"112.766670","year":"1975-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.015,31.16333]},"id":"48691","mass":"100000","name":"Tamdakht","nametype":"Valid","recclass":"H5","reclat":"31.163330","reclong":"-7.015000","year":"2008-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[136.23333,35.43333]},"id":"23801","mass":"905","name":"TanΓ©","nametype":"Valid","recclass":"L5","reclat":"35.433330","reclong":"136.233330","year":"1918-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[122.9,45.4]},"id":"23873","mass":"3850","name":"Taonan","nametype":"Valid","recclass":"L5","reclat":"45.400000","reclong":"122.900000","year":"1965-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[10.41667,32.95]},"id":"23884","mass":"12000","name":"Tatahouine","nametype":"Valid","recclass":"Diogenite","reclat":"32.950000","reclong":"10.416670","year":"1931-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[43.73333,19.38333]},"id":"23885","mass":"2500","name":"Tathlith","nametype":"Valid","recclass":"L6","reclat":"19.383330","reclong":"43.733330","year":"1967-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[44.45,35.13333]},"id":"23887","mass":"6000","name":"Tauk","nametype":"Valid","recclass":"L6","reclat":"35.133330","reclong":"44.450000","year":"1929-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[23.5,46.71667]},"id":"23888","mass":"21000","name":"Tauti","nametype":"Valid","recclass":"L6","reclat":"46.716670","reclong":"23.500000","year":"1937-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[142.95,-25.73333]},"id":"23897","mass":"160000","name":"Tenham","nametype":"Valid","recclass":"L6","reclat":"-25.733330","reclong":"142.950000","year":"1879-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[26.95,58.03333]},"id":"23898","mass":"28500","name":"Tennasilm","nametype":"Valid","recclass":"L4","reclat":"58.033330","reclong":"26.950000","year":"1872-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[70.6,33.4]},"id":"23908","mass":"342","name":"Thal","nametype":"Valid","recclass":"H6","reclat":"33.400000","reclong":"70.600000","year":"1950-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[37.15028,-1.00278]},"id":"54493","mass":"14200","name":"Thika","nametype":"Valid","recclass":"L6","reclat":"-1.002780","reclong":"37.150280","year":"2011-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[27.58333,-29.33333]},"id":"23976","mass":"45300","name":"Thuathe","nametype":"Valid","recclass":"H4/5","reclat":"-29.333330","reclong":"27.583330","year":"2002-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[118.99,32.94667]},"id":"23984","mass":"2232","name":"Tianzhang","nametype":"Valid","recclass":"H5","reclat":"32.946670","reclong":"118.990000","year":"1986-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[17.11667,49.6]},"id":"23989","mass":"28000","name":"Tieschitz","nametype":"Valid","recclass":"H/L3.6","reclat":"49.600000","reclong":"17.116670","year":"1878-01-01T00:00:00.000"} -,{":@computed_region_cbhk_fwbd":"34",":@computed_region_nnqa_25f4":"1762","fall":"Fell","geolocation":{"type":"Point","coordinates":[-89.68333,38.2]},"id":"23998","mass":"74800","name":"Tilden","nametype":"Valid","recclass":"L6","reclat":"38.200000","reclong":"-89.683330","year":"1927-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[1.53333,14.25]},"id":"23999","mass":"3000","name":"Tillaberi","nametype":"Valid","recclass":"L6","reclat":"14.250000","reclong":"1.533330","year":"1970-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[35.2,54.5]},"id":"24004","mass":"65500","name":"Timochin","nametype":"Valid","recclass":"H5","reclat":"54.500000","reclong":"35.200000","year":"1807-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[79.41667,13.63333]},"id":"24009","mass":"230","name":"Tirupati","nametype":"Valid","recclass":"H6","reclat":"13.633330","reclong":"79.416670","year":"1934-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[-7.61123,29.48195]},"id":"54823","mass":"7000","name":"Tissint","nametype":"Valid","recclass":"Martian (shergottite)","reclat":"29.481950","reclong":"-7.611230","year":"2011-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[111.53333,-7.08333]},"id":"24011","mass":"20000","name":"Tjabe","nametype":"Valid","recclass":"H6","reclat":"-7.083330","reclong":"111.533330","year":"1869-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[106.58333,-6.66667]},"id":"24012","mass":"16500","name":"Tjerebon","nametype":"Valid","recclass":"L5","reclat":"-6.666670","reclong":"106.583330","year":"1922-01-01T00:00:00.000"} -,{"fall":"Fell","geolocation":{"type":"Point","coordinates":[34.76667,47.85]},"id":"24019","mass":"600","name":"Tomakovka","nametype":"Valid","recclass":"LL6","reclat":"47.850000","reclong":"34.766670","year":"1905-01-01T00:00:00.000"}] +[ + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.08333, 50.775] }, + "id": "1", + "mass": "21", + "name": "Aachen", + "nametype": "Valid", + "recclass": "L5", + "reclat": "50.775000", + "reclong": "6.083330", + "year": "1880-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.23333, 56.18333] }, + "id": "2", + "mass": "720", + "name": "Aarhus", + "nametype": "Valid", + "recclass": "H6", + "reclat": "56.183330", + "reclong": "10.233330", + "year": "1951-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-113, 54.21667] }, + "id": "6", + "mass": "107000", + "name": "Abee", + "nametype": "Valid", + "recclass": "EH4", + "reclat": "54.216670", + "reclong": "-113.000000", + "year": "1952-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.9, 16.88333] }, + "id": "10", + "mass": "1914", + "name": "Acapulco", + "nametype": "Valid", + "recclass": "Acapulcoite", + "reclat": "16.883330", + "reclong": "-99.900000", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-64.95, -33.16667] }, + "id": "370", + "mass": "780", + "name": "Achiras", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-33.166670", + "reclong": "-64.950000", + "year": "1902-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [71.8, 32.1] }, + "id": "379", + "mass": "4239", + "name": "Adhi Kot", + "nametype": "Valid", + "recclass": "EH4", + "reclat": "32.100000", + "reclong": "71.800000", + "year": "1919-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [95.16667, 44.83333] }, + "id": "390", + "mass": "910", + "name": "Adzhi-Bogdo (stone)", + "nametype": "Valid", + "recclass": "LL3-6", + "reclat": "44.833330", + "reclong": "95.166670", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.61667, 44.21667] }, + "id": "392", + "mass": "30000", + "name": "Agen", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.216670", + "reclong": "0.616670", + "year": "1814-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-65.23333, -31.6] }, + "id": "398", + "mass": "1620", + "name": "Aguada", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-31.600000", + "reclong": "-65.233330", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-64.55, -30.86667] }, + "id": "417", + "mass": "1440", + "name": "Aguila Blanca", + "nametype": "Valid", + "recclass": "L", + "reclat": "-30.866670", + "reclong": "-64.550000", + "year": "1920-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-9.57028, 16.39806] }, + "id": "423", + "mass": "1000", + "name": "Aioun el Atrouss", + "nametype": "Valid", + "recclass": "Diogenite-pm", + "reclat": "16.398060", + "reclong": "-9.570280", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.38333, 19.08333] }, + "id": "424", + "mass": "24000", + "name": "AΓ―r", + "nametype": "Valid", + "recclass": "L6", + "reclat": "19.083330", + "reclong": "8.383330", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [2.33333, 50.66667] }, + "id": "425", + "name": "Aire-sur-la-Lys", + "nametype": "Valid", + "recclass": "Unknown", + "reclat": "50.666670", + "reclong": "2.333330", + "year": "1769-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.05, 29.51667] }, + "id": "426", + "mass": "779", + "name": "Akaba", + "nametype": "Valid", + "recclass": "L6", + "reclat": "29.516670", + "reclong": "35.050000", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.95, 29.71667] }, + "id": "427", + "mass": "1800", + "name": "Akbarpur", + "nametype": "Valid", + "recclass": "H4", + "reclat": "29.716670", + "reclong": "77.950000", + "year": "1838-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.43333, 8.91667] }, + "id": "432", + "mass": "3000", + "name": "Akwanga", + "nametype": "Valid", + "recclass": "H", + "reclat": "8.916670", + "reclong": "8.433330", + "year": "1959-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [42.81667, 39.91667] }, + "id": "433", + "mass": "50000", + "name": "Akyumak", + "nametype": "Valid", + "recclass": "Iron, IVA", + "reclat": "39.916670", + "reclong": "42.816670", + "year": "1981-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [39.51667, 24.41667] }, + "id": "446", + "mass": "160", + "name": "Al Rais", + "nametype": "Valid", + "recclass": "CR2-an", + "reclat": "24.416670", + "reclong": "39.516670", + "year": "1957-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28.96, 13.66033] }, + "id": "447", + "mass": "700", + "name": "Al Zarnkh", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "13.660330", + "reclong": "28.960000", + "year": "2001-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4.08333, 44.11667] }, + "id": "448", + "mass": "6000", + "name": "Alais", + "nametype": "Valid", + "recclass": "CI1", + "reclat": "44.116670", + "reclong": "4.083330", + "year": "1806-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.01667, 44.65] }, + "id": "453", + "mass": "2000", + "name": "Albareto", + "nametype": "Valid", + "recclass": "L/LL4", + "reclat": "44.650000", + "reclong": "11.016670", + "year": "1766-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.66667, 2] }, + "id": "454", + "mass": "625", + "name": "Alberta", + "nametype": "Valid", + "recclass": "L", + "reclat": "2.000000", + "reclong": "22.666670", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.01533, 45.82133] }, + "id": "458", + "mass": "252", + "name": "Alby sur ChΓ©ran", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "45.821330", + "reclong": "6.015330", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.78333, 51.78333] }, + "id": "461", + "mass": "700", + "name": "Aldsworth", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "51.783330", + "reclong": "-1.783330", + "year": "1835-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.13333, 36.23333] }, + "id": "462", + "mass": "3200", + "name": "Aleppo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.233330", + "reclong": "37.133330", + "year": "1873-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.75, 44.88333] }, + "id": "463", + "mass": "908", + "name": "Alessandria", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.883330", + "reclong": "8.750000", + "year": "1860-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.81667, 50.95] }, + "id": "465", + "mass": "9251", + "name": "Alexandrovsky", + "nametype": "Valid", + "recclass": "H4", + "reclat": "50.950000", + "reclong": "31.816670", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.15, 45.26667] }, + "id": "466", + "mass": "228000", + "name": "Alfianello", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.266670", + "reclong": "10.150000", + "year": "1883-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "50", + ":@computed_region_nnqa_25f4": "429", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-85.88333, 42.53333] }, + "id": "2276", + "mass": "32000", + "name": "Allegan", + "nametype": "Valid", + "recclass": "H5", + "reclat": "42.533330", + "reclong": "-85.883330", + "year": "1899-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-105.31667, 26.96667] }, + "id": "2278", + "mass": "2000000", + "name": "Allende", + "nametype": "Valid", + "recclass": "CV3", + "reclat": "26.966670", + "reclong": "-105.316670", + "year": "1969-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [32.41275, 20.74575] }, + "id": "48915", + "mass": "3950", + "name": "Almahata Sitta", + "nametype": "Valid", + "recclass": "Ureilite-an", + "reclat": "20.745750", + "reclong": "32.412750", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [44.21556, 35.27333] }, + "id": "2284", + "mass": "6000", + "name": "Alta'ameem", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "35.273330", + "reclong": "44.215560", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.25, 27.66667] }, + "id": "2290", + "mass": "6400", + "name": "Ambapur Nagla", + "nametype": "Valid", + "recclass": "H5", + "reclat": "27.666670", + "reclong": "78.250000", + "year": "1895-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [85.56667, 26.58333] }, + "id": "2294", + "mass": "2700", + "name": "Andhara", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "26.583330", + "reclong": "85.566670", + "year": "1880-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "49", + ":@computed_region_nnqa_25f4": "1723", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-70.75, 44.61667] }, + "id": "2295", + "mass": "3200", + "name": "Andover", + "nametype": "Valid", + "recclass": "L6", + "reclat": "44.616670", + "reclong": "-70.750000", + "year": "1898-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.5, 48.7] }, + "id": "2296", + "mass": "600", + "name": "Andreevka", + "nametype": "Valid", + "recclass": "L3", + "reclat": "48.700000", + "reclong": "37.500000", + "year": "1969-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.86667, 20.88333] }, + "id": "2298", + "mass": "17900", + "name": "Andura", + "nametype": "Valid", + "recclass": "H6", + "reclat": "20.883330", + "reclong": "76.866670", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Found", + "geolocation": { "type": "Point", "coordinates": [0, 0] }, + "id": "50693", + "mass": "256.8", + "name": "Northwest Africa 5815", + "nametype": "Valid", + "recclass": "L5", + "reclat": "0.000000", + "reclong": "0.000000" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.55, 47.46667] }, + "id": "2301", + "name": "Angers", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.466670", + "reclong": "-0.550000", + "year": "1822-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-44.31667, -22.96667] }, + "id": "2302", + "mass": "1500", + "name": "Angra dos Reis (stone)", + "nametype": "Valid", + "recclass": "Angrite", + "reclat": "-22.966670", + "reclong": "-44.316670", + "year": "1869-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [39.71667, 9.53333] }, + "id": "2304", + "mass": "6500", + "name": "Ankober", + "nametype": "Valid", + "recclass": "H4", + "reclat": "9.533330", + "reclong": "39.716670", + "year": "1942-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [105.18333, 25.15] }, + "id": "2305", + "mass": "2500", + "name": "Anlong", + "nametype": "Valid", + "recclass": "H5", + "reclat": "25.150000", + "reclong": "105.183330", + "year": "1971-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [140.78556, 40.81056] }, + "id": "2313", + "mass": "320", + "name": "Aomori", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.810560", + "reclong": "140.785560", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-2.71667, 53.58333] }, + "id": "2318", + "mass": "15000", + "name": "Appley Bridge", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "53.583330", + "reclong": "-2.716670", + "year": "1914-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.38333, 43.86667] }, + "id": "2320", + "mass": "3200", + "name": "Apt", + "nametype": "Valid", + "recclass": "L6", + "reclat": "43.866670", + "reclong": "5.383330", + "year": "1803-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-66, -33] }, + "id": "2325", + "mass": "810", + "name": "Arbol Solo", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-33.000000", + "reclong": "-66.000000", + "year": "1954-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "2697", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-94.3, 38.5] }, + "id": "2329", + "mass": "5070", + "name": "Archie", + "nametype": "Valid", + "recclass": "H6", + "reclat": "38.500000", + "reclong": "-94.300000", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-60.66667, -31.41667] }, + "id": "2340", + "mass": "7450", + "name": "Arroyo Aguiar", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-31.416670", + "reclong": "-60.666670", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.03333, 42.45] }, + "id": "2345", + "mass": "41", + "name": "Asco", + "nametype": "Valid", + "recclass": "H6", + "reclat": "42.450000", + "reclong": "9.033330", + "year": "1805-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "774", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-97.01, 31.805] }, + "id": "48954", + "mass": "9500", + "name": "Ash Creek", + "nametype": "Valid", + "recclass": "L6", + "reclat": "31.805000", + "reclong": "-97.010000", + "year": "2009-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.3, 52.05] }, + "id": "2346", + "mass": "1300", + "name": "Ashdon", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.050000", + "reclong": "0.300000", + "year": "1923-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.55, 43.03333] }, + "id": "2353", + "mass": "2000", + "name": "Assisi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.033330", + "reclong": "12.550000", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [80.625, 25.25417] }, + "id": "4883", + "mass": "1280", + "name": "Atarra", + "nametype": "Valid", + "recclass": "L4", + "reclat": "25.254170", + "reclong": "80.625000", + "year": "1920-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.66667, 20.06667] }, + "id": "4884", + "mass": "94.2", + "name": "Atemajac", + "nametype": "Valid", + "recclass": "L6", + "reclat": "20.066670", + "reclong": "-103.666670", + "year": "1896-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "29", + ":@computed_region_nnqa_25f4": "3134", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87, 34.75] }, + "id": "4885", + "mass": "265", + "name": "Athens", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "34.750000", + "reclong": "-87.000000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "20", + ":@computed_region_nnqa_25f4": "602", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96.15, 34.31667] }, + "id": "4888", + "mass": "1384.2", + "name": "Atoka", + "nametype": "Valid", + "recclass": "L6", + "reclat": "34.316670", + "reclong": "-96.150000", + "year": "1945-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.16667, 44.38333] }, + "id": "4893", + "mass": "800", + "name": "Aubres", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "44.383330", + "reclong": "5.166670", + "year": "1836-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.66667, 36.16667] }, + "id": "4899", + "mass": "50000", + "name": "Aumale", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.166670", + "reclong": "3.666670", + "year": "1865-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.23333, 44.33333] }, + "id": "4900", + "mass": "2000", + "name": "Aumieres", + "nametype": "Valid", + "recclass": "L6", + "reclat": "44.333330", + "reclong": "3.233330", + "year": "1842-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.58333, 43.08333] }, + "id": "4903", + "mass": "50000", + "name": "Ausson", + "nametype": "Valid", + "recclass": "L5", + "reclat": "43.083330", + "reclong": "0.583330", + "year": "1858-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-49.95083, -21.46028] }, + "id": "4905", + "mass": "9330", + "name": "Avanhandava", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-21.460280", + "reclong": "-49.950830", + "year": "1952-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.5, 46] }, + "id": "4906", + "mass": "1230", + "name": "Avce", + "nametype": "Valid", + "recclass": "Iron, IIAB", + "reclat": "46.000000", + "reclong": "13.500000", + "year": "1908-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.5, 25] }, + "id": "4907", + "mass": "146", + "name": "Avilez", + "nametype": "Valid", + "recclass": "H", + "reclat": "25.000000", + "reclong": "-103.500000", + "year": "1855-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [32.83333, 2.71667] }, + "id": "4910", + "mass": "134", + "name": "Awere", + "nametype": "Valid", + "recclass": "L4", + "reclat": "2.716670", + "reclong": "32.833330", + "year": "1968-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "11", + ":@computed_region_nnqa_25f4": "1989", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-108, 36.8] }, + "id": "4913", + "mass": "2830", + "name": "Aztec", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.800000", + "reclong": "-108.000000", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [38, 48.6] }, + "id": "4917", + "mass": "18000", + "name": "Bachmut", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.600000", + "reclong": "38.000000", + "year": "1814-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.5, 28.48333] }, + "id": "4922", + "mass": "10322", + "name": "Bahjoi", + "nametype": "Valid", + "recclass": "Iron, IAB-sLL", + "reclat": "28.483330", + "reclong": "78.500000", + "year": "1934-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "2373", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-82.48333, 35.96667] }, + "id": "4925", + "mass": "3700", + "name": "Bald Mountain", + "nametype": "Valid", + "recclass": "L4", + "reclat": "35.966670", + "reclong": "-82.483330", + "year": "1929-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "32", + ":@computed_region_nnqa_25f4": "495", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-88.66667, 34.5] }, + "id": "4926", + "mass": "345", + "name": "Baldwyn", + "nametype": "Valid", + "recclass": "L6", + "reclat": "34.500000", + "reclong": "-88.666670", + "year": "1922-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.38333, 5.38333] }, + "id": "4928", + "mass": "1000", + "name": "Bali", + "nametype": "Valid", + "recclass": "CV3", + "reclat": "5.383330", + "reclong": "16.383330", + "year": "1907-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [101.18333, 16.66667] }, + "id": "4934", + "mass": "16700", + "name": "Ban Rong Du", + "nametype": "Valid", + "recclass": "Iron, ungrouped", + "reclat": "16.666670", + "reclong": "101.183330", + "year": "1993-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [107.6, -6.91667] }, + "id": "4935", + "mass": "11500", + "name": "Bandong", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "-6.916670", + "reclong": "107.600000", + "year": "1871-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.33333, 27.7] }, + "id": "4936", + "mass": "15000", + "name": "Bansur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "27.700000", + "reclong": "76.333330", + "year": "1892-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.2, 30.4] }, + "id": "4937", + "mass": "14", + "name": "Banswal", + "nametype": "Valid", + "recclass": "L5", + "reclat": "30.400000", + "reclong": "78.200000", + "year": "1913-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [106, -6.33333] }, + "id": "4938", + "mass": "629", + "name": "Banten", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "-6.333330", + "reclong": "106.000000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.05, 43.95] }, + "id": "4942", + "mass": "6400", + "name": "Barbotan", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.950000", + "reclong": "-0.050000", + "year": "1790-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [2.16667, 41.36667] }, + "id": "4944", + "name": "Barcelona (stone)", + "nametype": "Valid", + "recclass": "OC", + "reclat": "41.366670", + "reclong": "2.166670", + "year": "1704-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-2.5, 42.38333] }, + "id": "4946", + "mass": "3200", + "name": "Barea", + "nametype": "Valid", + "recclass": "Mesosiderite-A1", + "reclat": "42.383330", + "reclong": "-2.500000", + "year": "1842-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.08333, 52.73333] }, + "id": "4947", + "mass": "23.2", + "name": "Barnaul", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.733330", + "reclong": "84.083330", + "year": "1904-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.1, 52] }, + "id": "4948", + "mass": "17", + "name": "Barntrup", + "nametype": "Valid", + "recclass": "LL4", + "reclat": "52.000000", + "reclong": "9.100000", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.8, 31.61667] }, + "id": "4949", + "mass": "4500", + "name": "Baroti", + "nametype": "Valid", + "recclass": "L6", + "reclat": "31.616670", + "reclong": "76.800000", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.33972, 52.56528] }, + "id": "4954", + "mass": "44000", + "name": "Barwell", + "nametype": "Valid", + "recclass": "L5", + "reclat": "52.565280", + "reclong": "-1.339720", + "year": "1965-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-5.9, 15.78333] }, + "id": "44876", + "mass": "29560", + "name": "Bassikounou", + "nametype": "Valid", + "recclass": "H5", + "reclat": "15.783330", + "reclong": "-5.900000", + "year": "2006-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [20.93583, 52.03333] }, + "id": "4957", + "mass": "15500", + "name": "BaszkΓ³wka", + "nametype": "Valid", + "recclass": "L5", + "reclat": "52.033330", + "reclong": "20.935830", + "year": "1994-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "21", + ":@computed_region_nnqa_25f4": "662", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-98.31667, 45.41667] }, + "id": "4974", + "mass": "21000", + "name": "Bath", + "nametype": "Valid", + "recclass": "H4", + "reclat": "45.416670", + "reclong": "-98.316670", + "year": "1892-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "36", + ":@computed_region_nnqa_25f4": "1921", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-83.75, 38.25] }, + "id": "4975", + "mass": "86000", + "name": "Bath Furnace", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.250000", + "reclong": "-83.750000", + "year": "1902-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "10", + ":@computed_region_nnqa_25f4": "2397", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-117.18913, 40.66813] }, + "id": "56133", + "mass": "2900", + "name": "Battle Mountain", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.668130", + "reclong": "-117.189130", + "year": "2012-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.18333, 11.08333] }, + "id": "4976", + "mass": "1557", + "name": "Bawku", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "11.083330", + "reclong": "-0.183330", + "year": "1989-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "2216", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-93.5, 36.75] }, + "id": "4977", + "mass": "611", + "name": "Baxter", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.750000", + "reclong": "-93.500000", + "year": "1916-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1285", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-101.2, 39.8] }, + "id": "4984", + "mass": "16000", + "name": "Beardsley", + "nametype": "Valid", + "recclass": "H5", + "reclat": "39.800000", + "reclong": "-101.200000", + "year": "1929-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-117.33333, 51.16667] }, + "id": "4986", + "mass": "14000", + "name": "Beaver Creek", + "nametype": "Valid", + "recclass": "H5", + "reclat": "51.166670", + "reclong": "-117.333330", + "year": "1893-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-4.1, 53.01667] }, + "id": "4993", + "mass": "794", + "name": "Beddgelert", + "nametype": "Valid", + "recclass": "H5", + "reclat": "53.016670", + "reclong": "-4.100000", + "year": "1949-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "1978", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96.46667, 33.6] }, + "id": "5005", + "mass": "375", + "name": "Bells", + "nametype": "Valid", + "recclass": "C2-ung", + "reclat": "33.600000", + "reclong": "-96.466670", + "year": "1961-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-64.86667, -32.33333] }, + "id": "5009", + "name": "Belville", + "nametype": "Valid", + "recclass": "OC", + "reclat": "-32.333330", + "reclong": "-64.866670", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.91667, 25.36667] }, + "id": "5011", + "mass": "3700", + "name": "Benares (a)", + "nametype": "Valid", + "recclass": "LL4", + "reclat": "25.366670", + "reclong": "82.916670", + "year": "1798-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8.15, 32.25] }, + "id": "30443", + "mass": "25000", + "name": "Benguerir", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "32.250000", + "reclong": "-8.150000", + "year": "2004-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.8, 32.86667] }, + "id": "5018", + "mass": "19000", + "name": "Beni M'hira", + "nametype": "Valid", + "recclass": "L6", + "reclat": "32.866670", + "reclong": "10.800000", + "year": "2001-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "34", + ":@computed_region_nnqa_25f4": "1869", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-89.15, 39.08333] }, + "id": "5021", + "mass": "1770.5", + "name": "Benld", + "nametype": "Valid", + "recclass": "H6", + "reclat": "39.083330", + "reclong": "-89.150000", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28.41667, -26.16667] }, + "id": "5023", + "mass": "3880", + "name": "Benoni", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-26.166670", + "reclong": "28.416670", + "year": "1943-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7, 30] }, + "id": "5024", + "mass": "45000", + "name": "Bensour", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "30.000000", + "reclong": "-7.000000", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-67.55, 45.95] }, + "id": "5026", + "mass": "2840", + "name": "Benton", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "45.950000", + "reclong": "-67.550000", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-58.32833, -31.91] }, + "id": "48975", + "mass": "270", + "name": "Berduc", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-31.910000", + "reclong": "-58.328330", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.65, 11.65] }, + "id": "5028", + "mass": "18000", + "name": "BΓ©rΓ©ba", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "11.650000", + "reclong": "-3.650000", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.8, 41.68333] }, + "id": "5029", + "mass": "1440", + "name": "Berlanguillas", + "nametype": "Valid", + "recclass": "L6", + "reclat": "41.683330", + "reclong": "-3.800000", + "year": "1811-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "9", + ":@computed_region_nnqa_25f4": "1072", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-105.02325, 40.30583] }, + "id": "47355", + "mass": "960", + "name": "Berthoud", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "40.305830", + "reclong": "-105.023250", + "year": "2004-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "47", + ":@computed_region_nnqa_25f4": "2030", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-73.83333, 42.53333] }, + "id": "5032", + "mass": "13.9", + "name": "Bethlehem", + "nametype": "Valid", + "recclass": "H", + "reclat": "42.533330", + "reclong": "-73.833330", + "year": "1859-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.23333, 43.21667] }, + "id": "5034", + "mass": "2000", + "name": "Beuste", + "nametype": "Valid", + "recclass": "L5", + "reclat": "43.216670", + "reclong": "-0.233330", + "year": "1859-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.5, 33.88333] }, + "id": "5035", + "mass": "1100", + "name": "Beyrout", + "nametype": "Valid", + "recclass": "LL3.8", + "reclat": "33.883330", + "reclong": "35.500000", + "year": "1921-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [74.83333, 20.88333] }, + "id": "5037", + "mass": "18", + "name": "Bhagur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "20.883330", + "reclong": "74.833330", + "year": "1877-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [73.11528, 26.50833] }, + "id": "36591", + "mass": "678", + "name": "Bhawad", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "26.508330", + "reclong": "73.115280", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [71.46667, 20.83333] }, + "id": "5039", + "mass": "100", + "name": "Bherai", + "nametype": "Valid", + "recclass": "L6", + "reclat": "20.833330", + "reclong": "71.466670", + "year": "1893-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [90.65, 22.68333] }, + "id": "5040", + "mass": "1047", + "name": "Bhola", + "nametype": "Valid", + "recclass": "LL3-6", + "reclat": "22.683330", + "reclong": "90.650000", + "year": "1940-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [86.9, 22.08333] }, + "id": "5041", + "mass": "2500", + "name": "Bholghati", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "22.083330", + "reclong": "86.900000", + "year": "1905-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23.2, 53.1] }, + "id": "5042", + "mass": "4000", + "name": "Bialystok", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "53.100000", + "reclong": "23.200000", + "year": "1827-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.16667, 50.13333] }, + "id": "5043", + "mass": "1900", + "name": "Bielokrynitschie", + "nametype": "Valid", + "recclass": "H4", + "reclat": "50.133330", + "reclong": "27.166670", + "year": "1887-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.08333, 12.45] }, + "id": "5045", + "mass": "25000", + "name": "Bilanga", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "12.450000", + "reclong": "-0.083330", + "year": "1999-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.67639, -33.15639] }, + "id": "5051", + "mass": "488.1", + "name": "Binningup", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-33.156390", + "reclong": "115.676390", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.3, 13.76667] }, + "id": "5056", + "mass": "560", + "name": "Birni N'konni", + "nametype": "Valid", + "recclass": "H4", + "reclat": "13.766670", + "reclong": "5.300000", + "year": "1923-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "33", + ":@computed_region_nnqa_25f4": "657", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-80.28333, 34.16667] }, + "id": "5059", + "mass": "6000", + "name": "Bishopville", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "34.166670", + "reclong": "-80.283330", + "year": "1843-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.6, 25.38333] }, + "id": "5060", + "mass": "1039", + "name": "Bishunpur", + "nametype": "Valid", + "recclass": "LL3.15", + "reclat": "25.383330", + "reclong": "82.600000", + "year": "1895-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.16667, 49.78333] }, + "id": "5063", + "mass": "1850", + "name": "Bjelaja Zerkov", + "nametype": "Valid", + "recclass": "H6", + "reclat": "49.783330", + "reclong": "30.166670", + "year": "1796-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.8, 60.4] }, + "id": "5064", + "mass": "330000", + "name": "BjurbΓΆle", + "nametype": "Valid", + "recclass": "L/LL4", + "reclat": "60.400000", + "reclong": "25.800000", + "year": "1899-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "48", + ":@computed_region_nnqa_25f4": "2495", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-78.08333, 40.91667] }, + "id": "5065", + "mass": "705", + "name": "Black Moshannan Park", + "nametype": "Valid", + "recclass": "L5", + "reclat": "40.916670", + "reclong": "-78.083330", + "year": "1941-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "20", + ":@computed_region_nnqa_25f4": "2164", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-97.33333, 36.83333] }, + "id": "5068", + "mass": "2381", + "name": "Blackwell", + "nametype": "Valid", + "recclass": "L5", + "reclat": "36.833330", + "reclong": "-97.333330", + "year": "1906-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "3063", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-98.83333, 31.83333] }, + "id": "5071", + "mass": "5100", + "name": "Blanket", + "nametype": "Valid", + "recclass": "L6", + "reclat": "31.833330", + "reclong": "-98.833330", + "year": "1909-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.63333, 49.36667] }, + "id": "5072", + "mass": "470", + "name": "Blansko", + "nametype": "Valid", + "recclass": "H6", + "reclat": "49.366670", + "reclong": "16.633330", + "year": "1833-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "34", + ":@computed_region_nnqa_25f4": "1795", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-89.00417, 40.48] }, + "id": "5076", + "mass": "67.8", + "name": "Bloomington", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "40.480000", + "reclong": "-89.004170", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.83333, 33.83333] }, + "id": "5090", + "mass": "7500", + "name": "Bo Xian", + "nametype": "Valid", + "recclass": "LL3.9", + "reclat": "33.833330", + "reclong": "115.833330", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-102, 23] }, + "id": "5093", + "mass": "56", + "name": "Bocas", + "nametype": "Valid", + "recclass": "L6", + "reclat": "23.000000", + "reclong": "-102.000000", + "year": "1804-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.7, 12.5] }, + "id": "5097", + "mass": "8800", + "name": "Bogou", + "nametype": "Valid", + "recclass": "Iron, IAB-MG", + "reclat": "12.500000", + "reclong": "0.700000", + "year": "1962-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [131.63333, 44.55] }, + "id": "5098", + "mass": "256000", + "name": "Boguslavka", + "nametype": "Valid", + "recclass": "Iron, IIAB", + "reclat": "44.550000", + "reclong": "131.633330", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.05, 44.86667] }, + "id": "5110", + "mass": "1676", + "name": "Borgo San Donino", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "44.866670", + "reclong": "10.050000", + "year": "1808-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.03333, 21.95] }, + "id": "5111", + "mass": "8600", + "name": "Bori", + "nametype": "Valid", + "recclass": "L6", + "reclat": "21.950000", + "reclong": "78.033330", + "year": "1894-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [52.48333, 54.23333] }, + "id": "5112", + "mass": "1342", + "name": "Boriskino", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "54.233330", + "reclong": "52.483330", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [24.28333, 48.15] }, + "id": "5113", + "mass": "7000", + "name": "Borkut", + "nametype": "Valid", + "recclass": "L5", + "reclat": "48.150000", + "reclong": "24.283330", + "year": "1852-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.86667, 55.46667] }, + "id": "5114", + "mass": "500", + "name": "Borodino", + "nametype": "Valid", + "recclass": "H5", + "reclat": "55.466670", + "reclong": "35.866670", + "year": "1812-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.88333, 51.33333] }, + "id": "5117", + "mass": "614", + "name": "Botschetschki", + "nametype": "Valid", + "recclass": "L4", + "reclat": "51.333330", + "reclong": "33.883330", + "year": "1823-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-11.3715, 17.71067] }, + "id": "57168", + "mass": "190", + "name": "Boumdeid (2003)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "17.710670", + "reclong": "-11.371500", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-11.34133, 17.17493] }, + "id": "57167", + "mass": "3599", + "name": "Boumdeid (2011)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "17.174930", + "reclong": "-11.341330", + "year": "2011-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.33333, 54.56667] }, + "id": "5121", + "mass": "5460", + "name": "Bovedy", + "nametype": "Valid", + "recclass": "L3", + "reclat": "54.566670", + "reclong": "-6.333330", + "year": "1969-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "48", + ":@computed_region_nnqa_25f4": "2455", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-80.08333, 40.5] }, + "id": "5128", + "mass": "762", + "name": "Bradford Woods", + "nametype": "Valid", + "recclass": "L", + "reclat": "40.500000", + "reclong": "-80.083330", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.3, 50.6] }, + "id": "5133", + "mass": "39000", + "name": "Braunau", + "nametype": "Valid", + "recclass": "Iron, IIAB", + "reclat": "50.600000", + "reclong": "16.300000", + "year": "1847-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.18361, 50.66694] }, + "id": "5134", + "mass": "1500", + "name": "Breitscheid", + "nametype": "Valid", + "recclass": "H5", + "reclat": "50.666940", + "reclong": "8.183610", + "year": "1956-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.1, 53.4] }, + "id": "5135", + "mass": "7250", + "name": "BremervΓΆrde", + "nametype": "Valid", + "recclass": "H/L3.9", + "reclat": "53.400000", + "reclong": "9.100000", + "year": "1855-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [59.31667, 52.13333] }, + "id": "5140", + "mass": "219", + "name": "Brient", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "52.133330", + "reclong": "59.316670", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-112.88333, 53.9] }, + "id": "5156", + "mass": "303000", + "name": "Bruderheim", + "nametype": "Valid", + "recclass": "L6", + "reclat": "53.900000", + "reclong": "-112.883330", + "year": "1960-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [64.60035, 39.77978] }, + "id": "30448", + "mass": "5300", + "name": "Bukhara", + "nametype": "Valid", + "recclass": "CV3", + "reclat": "39.779780", + "reclong": "64.600350", + "year": "2001-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "5163", + "mass": "2250", + "name": "Bulls Run", + "nametype": "Valid", + "recclass": "Iron?", + "year": "1964-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [129.19, -31.35] }, + "id": "48653", + "mass": "324", + "name": "Bunburra Rockhole", + "nametype": "Valid", + "recclass": "Eucrite", + "reclat": "-31.350000", + "reclong": "129.190000", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.58333, 10.01667] }, + "id": "5165", + "mass": "357", + "name": "Bununu", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "10.016670", + "reclong": "9.583330", + "year": "1942-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [48, 5] }, + "id": "5169", + "mass": "120000", + "name": "Bur-Gheluai", + "nametype": "Valid", + "recclass": "H5", + "reclat": "5.000000", + "reclong": "48.000000", + "year": "1919-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "36", + ":@computed_region_nnqa_25f4": "256", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-82.23722, 37.62194] }, + "id": "5175", + "mass": "1504", + "name": "Burnwell", + "nametype": "Valid", + "recclass": "H4-an", + "reclat": "37.621940", + "reclong": "-82.237220", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.23333, 40.2] }, + "id": "5177", + "mass": "25000", + "name": "Bursa", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.200000", + "reclong": "29.233330", + "year": "1946-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.78333, 46.45] }, + "id": "5178", + "mass": "5000", + "name": "Buschhof", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.450000", + "reclong": "25.783330", + "year": "1863-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.83333, 26.78333] }, + "id": "5181", + "mass": "1500", + "name": "Bustee", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "26.783330", + "reclong": "82.833330", + "year": "1852-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.08333, 27.08333] }, + "id": "5183", + "mass": "29000", + "name": "Butsura", + "nametype": "Valid", + "recclass": "H6", + "reclat": "27.083330", + "reclong": "84.083330", + "year": "1861-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-109.84817, 52.996] }, + "id": "48654", + "mass": "41000", + "name": "Buzzard Coulee", + "nametype": "Valid", + "recclass": "H4", + "reclat": "52.996000", + "reclong": "-109.848170", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.16667, 37.98333] }, + "id": "5185", + "mass": "25000", + "name": "Cabezo de Mayo", + "nametype": "Valid", + "recclass": "L/LL6", + "reclat": "37.983330", + "reclong": "-1.166670", + "year": "1870-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "15", + ":@computed_region_nnqa_25f4": "1029", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-93.5, 35.5] }, + "id": "5186", + "mass": "48500", + "name": "Cabin Creek", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "35.500000", + "reclong": "-93.500000", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [20.33333, 43.83889] }, + "id": "5187", + "mass": "212", + "name": "Cacak", + "nametype": "Valid", + "recclass": "OC", + "reclat": "43.838890", + "reclong": "20.333330", + "year": "1919-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-76.51, 3.405] }, + "id": "45976", + "mass": "478", + "name": "Cali", + "nametype": "Valid", + "recclass": "H/L4", + "reclat": "3.405000", + "reclong": "-76.510000", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [122.33333, 11.75] }, + "id": "5200", + "mass": "2400", + "name": "Calivo", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "11.750000", + "reclong": "122.333330", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-40.16667, -7.03333] }, + "id": "5249", + "mass": "23680", + "name": "Campos Sales", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-7.033330", + "reclong": "-40.166670", + "year": "1991-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.6, 39.8] }, + "id": "5250", + "mass": "4000", + "name": "Γ‡anakkale", + "nametype": "Valid", + "recclass": "L6", + "reclat": "39.800000", + "reclong": "26.600000", + "year": "1964-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.66667, 41.25] }, + "id": "5251", + "mass": "945", + "name": "CaΓ±ellas", + "nametype": "Valid", + "recclass": "H4", + "reclat": "41.250000", + "reclong": "1.666670", + "year": "1861-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-5.15, 43.38333] }, + "id": "5252", + "mass": "34000", + "name": "Cangas de Onis", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.383330", + "reclong": "-5.150000", + "year": "1866-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "9", + ":@computed_region_nnqa_25f4": "1448", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-105.24139, 38.47028] }, + "id": "5253", + "mass": "1400", + "name": "Canon City", + "nametype": "Valid", + "recclass": "H6", + "reclat": "38.470280", + "reclong": "-105.241390", + "year": "1973-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "2695", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-89.58333, 37.26667] }, + "id": "5260", + "mass": "2300", + "name": "Cape Girardeau", + "nametype": "Valid", + "recclass": "H6", + "reclat": "37.266670", + "reclong": "-89.583330", + "year": "1846-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-64.55, -30.88333] }, + "id": "5264", + "mass": "750", + "name": "Capilla del Monte", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-30.883330", + "reclong": "-64.550000", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-69.04389, -16.66444] }, + "id": "45817", + "mass": "342", + "name": "Carancas", + "nametype": "Valid", + "recclass": "H4-5", + "reclat": "-16.664440", + "reclong": "-69.043890", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27, 38.5] }, + "id": "5265", + "mass": "8", + "name": "Caratash", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "38.500000", + "reclong": "27.000000", + "year": "1902-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "648", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-78.06667, 36.08333] }, + "id": "5291", + "mass": "7300", + "name": "Castalia", + "nametype": "Valid", + "recclass": "H5", + "reclat": "36.083330", + "reclong": "-78.066670", + "year": "1874-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.5, 43.35] }, + "id": "5292", + "name": "Castel Berardenga", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "43.350000", + "reclong": "11.500000", + "year": "1791-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "49", + ":@computed_region_nnqa_25f4": "414", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-68.75, 44.38333] }, + "id": "5293", + "mass": "94", + "name": "Castine", + "nametype": "Valid", + "recclass": "L6", + "reclat": "44.383330", + "reclong": "-68.750000", + "year": "1848-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.2, 39.8] }, + "id": "5295", + "mass": "15000", + "name": "Castrovillari", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "39.800000", + "reclong": "16.200000", + "year": "1583-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "637", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-79.25, 36.5] }, + "id": "5296", + "mass": "1360", + "name": "Caswell County", + "nametype": "Valid", + "recclass": "OC", + "reclat": "36.500000", + "reclong": "-79.250000", + "year": "1810-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-105.23333, 26.46667] }, + "id": "5306", + "mass": "1025", + "name": "Ceniceros", + "nametype": "Valid", + "recclass": "L3.7", + "reclat": "26.466670", + "reclong": "-105.233330", + "year": "1988-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "21", + ":@computed_region_nnqa_25f4": "2684", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96.91667, 43.2] }, + "id": "5307", + "mass": "45.6", + "name": "Centerville", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.200000", + "reclong": "-96.916670", + "year": "1956-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.3, 45.08333] }, + "id": "5308", + "mass": "6460", + "name": "Cereseto", + "nametype": "Valid", + "recclass": "H5", + "reclat": "45.083330", + "reclong": "8.300000", + "year": "1840-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [109.31667, 28.53333] }, + "id": "5313", + "mass": "3700", + "name": "Chadong", + "nametype": "Valid", + "recclass": "L6", + "reclat": "28.533330", + "reclong": "109.316670", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81.66667, 25.36667] }, + "id": "5314", + "mass": "0.5", + "name": "Chail", + "nametype": "Valid", + "recclass": "H6", + "reclat": "25.366670", + "reclong": "81.666670", + "year": "1814-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.48333, 25.85] }, + "id": "5315", + "mass": "8200", + "name": "Chainpur", + "nametype": "Valid", + "recclass": "LL3.4", + "reclat": "25.850000", + "reclong": "83.483330", + "year": "1907-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-58.05, -30.78333] }, + "id": "5316", + "mass": "18300", + "name": "Chajari", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-30.783330", + "reclong": "-58.050000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.01667, 20.26667] }, + "id": "5320", + "mass": "8800", + "name": "Chandakapur", + "nametype": "Valid", + "recclass": "L5", + "reclat": "20.266670", + "reclong": "76.016670", + "year": "1838-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [79.05, 27.28333] }, + "id": "5321", + "mass": "1100", + "name": "Chandpur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "27.283330", + "reclong": "79.050000", + "year": "1885-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.75, 29.08333] }, + "id": "5322", + "mass": "1810", + "name": "Changde", + "nametype": "Valid", + "recclass": "H5", + "reclat": "29.083330", + "reclong": "111.750000", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.05, 46.68333] }, + "id": "5325", + "mass": "31500", + "name": "Chantonnay", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.683330", + "reclong": "1.050000", + "year": "1812-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "39", + ":@computed_region_nnqa_25f4": "2007", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87.33333, 36.16667] }, + "id": "5328", + "mass": "4300", + "name": "Charlotte", + "nametype": "Valid", + "recclass": "Iron, IVA", + "reclat": "36.166670", + "reclong": "-87.333330", + "year": "1835-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.56667, 47.93333] }, + "id": "5329", + "mass": "27000", + "name": "Charsonville", + "nametype": "Valid", + "recclass": "H6", + "reclat": "47.933330", + "reclong": "1.566670", + "year": "1810-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.5, 29.48333] }, + "id": "5330", + "mass": "12000", + "name": "Charwallas", + "nametype": "Valid", + "recclass": "H6", + "reclat": "29.483330", + "reclong": "75.500000", + "year": "1834-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.36667, 47.71667] }, + "id": "5331", + "mass": "4000", + "name": "Chassigny", + "nametype": "Valid", + "recclass": "Martian (chassignite)", + "reclat": "47.716670", + "reclong": "5.366670", + "year": "1815-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [2.91667, 47.93333] }, + "id": "5332", + "mass": "30000", + "name": "ChΓ’teau-Renard", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.933330", + "reclong": "2.916670", + "year": "1841-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.46667, 41.93333] }, + "id": "5334", + "mass": "2945", + "name": "Chaves", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "41.933330", + "reclong": "-7.466670", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [32.5, -3.66667] }, + "id": "5338", + "mass": "2936", + "name": "Chela", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-3.666670", + "reclong": "32.500000", + "year": "1988-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [61.11667, 54.81667] }, + "id": "57165", + "mass": "100000", + "name": "Chelyabinsk", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "54.816670", + "reclong": "61.116670", + "year": "2013-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-5.01472, 23.69639] }, + "id": "47347", + "mass": "100000", + "name": "Chergach ", + "nametype": "Valid", + "recclass": "H5", + "reclat": "23.696390", + "reclong": "-5.014720", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.1, 53.7] }, + "id": "5339", + "mass": "6000", + "name": "Chernyi Bor", + "nametype": "Valid", + "recclass": "H4", + "reclat": "53.700000", + "reclong": "30.100000", + "year": "1964-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "33", + ":@computed_region_nnqa_25f4": "2582", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-81.88333, 35.03333] }, + "id": "5340", + "mass": "8400", + "name": "Cherokee Springs", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "35.033330", + "reclong": "-81.883330", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.81667, 46.55] }, + "id": "5341", + "mass": "705", + "name": "Chervettaz", + "nametype": "Valid", + "recclass": "L5", + "reclat": "46.550000", + "reclong": "6.816670", + "year": "1901-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [34, 50.83333] }, + "id": "5342", + "mass": "1700", + "name": "Chervony Kut", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "50.833330", + "reclong": "34.000000", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.5, 14.5] }, + "id": "5344", + "mass": "72", + "name": "Chetrinahatti", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "14.500000", + "reclong": "76.500000", + "year": "1880-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [101.63333, 17.9] }, + "id": "5345", + "mass": "367", + "name": "Chiang Khan", + "nametype": "Valid", + "recclass": "H6", + "reclat": "17.900000", + "reclong": "101.633330", + "year": "1981-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "48", + ":@computed_region_nnqa_25f4": "2459", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-79.73333, 40.93333] }, + "id": "5349", + "mass": "303", + "name": "Chicora", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "40.933330", + "reclong": "-79.733330", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.395, -10.05944] }, + "id": "5355", + "mass": "3920", + "name": "Chisenga", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "-10.059440", + "reclong": "33.395000", + "year": "1988-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.96667, -17.35] }, + "id": "5356", + "name": "Chitado", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-17.350000", + "reclong": "13.966670", + "year": "1966-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.97667, 47.47083] }, + "id": "5357", + "mass": "4000", + "name": "Chitenay", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.470830", + "reclong": "0.976670", + "year": "1978-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [108.1, -6.95] }, + "id": "5364", + "mass": "1600", + "name": "Cilimus", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-6.950000", + "reclong": "108.100000", + "year": "1979-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "31", + ":@computed_region_nnqa_25f4": "67", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-81.87278, 32.1025] }, + "id": "5374", + "mass": "1455", + "name": "Claxton", + "nametype": "Valid", + "recclass": "L6", + "reclat": "32.102500", + "reclong": "-81.872780", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "5383", + "mass": "48.6", + "name": "Clohars", + "nametype": "Valid", + "recclass": "L4", + "year": "1822-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "41", + ":@computed_region_nnqa_25f4": "877", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-90.28333, 44.9] }, + "id": "5395", + "mass": "104000", + "name": "Colby (Wisconsin)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "44.900000", + "reclong": "-90.283330", + "year": "1917-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [19.38333, -33.13333] }, + "id": "5397", + "mass": "5200", + "name": "Cold Bokkeveld", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "-33.133330", + "reclong": "19.383330", + "year": "1838-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "50", + ":@computed_region_nnqa_25f4": "356", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-84.50778, 43.76111] }, + "id": "5401", + "mass": "469", + "name": "Coleman", + "nametype": "Valid", + "recclass": "L6", + "reclat": "43.761110", + "reclong": "-84.507780", + "year": "1994-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.61667, 42.53333] }, + "id": "5403", + "mass": "5000", + "name": "Collescipoli", + "nametype": "Valid", + "recclass": "H5", + "reclat": "42.533330", + "reclong": "12.616670", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-47.55, -19.85] }, + "id": "5418", + "mass": "20350", + "name": "Conquista", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-19.850000", + "reclong": "-47.550000", + "year": "1965-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-100.86667, 21.16667] }, + "id": "5451", + "mass": "1200", + "name": "Cosina", + "nametype": "Valid", + "recclass": "H5", + "reclat": "21.166670", + "reclong": "-100.866670", + "year": "1844-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.26667, 10.2] }, + "id": "5465", + "mass": "1460", + "name": "Cranganore", + "nametype": "Valid", + "recclass": "L6", + "reclat": "10.200000", + "reclong": "76.266670", + "year": "1917-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "20", + ":@computed_region_nnqa_25f4": "2201", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-97.58333, 35.95] }, + "id": "5470", + "mass": "78.400000000000006", + "name": "Crescent", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "35.950000", + "reclong": "-97.583330", + "year": "1936-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.3, -27.7] }, + "id": "5474", + "mass": "3650", + "name": "Cronstad", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-27.700000", + "reclong": "27.300000", + "year": "1877-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "2332", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-78.13333, 35.63333] }, + "id": "5476", + "mass": "167", + "name": "Cross Roads", + "nametype": "Valid", + "recclass": "H5", + "reclat": "35.633330", + "reclong": "-78.133330", + "year": "1892-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.21667, 54.61667] }, + "id": "5477", + "mass": "4255", + "name": "Crumlin", + "nametype": "Valid", + "recclass": "L5", + "reclat": "54.616670", + "reclong": "-6.216670", + "year": "1902-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "36", + ":@computed_region_nnqa_25f4": "1426", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-84.35, 36.83333] }, + "id": "5496", + "mass": "17000", + "name": "Cumberland Falls", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "36.833330", + "reclong": "-84.350000", + "year": "1919-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "36", + ":@computed_region_nnqa_25f4": "244", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-84.25, 38.4] }, + "id": "5500", + "mass": "6000", + "name": "Cynthiana", + "nametype": "Valid", + "recclass": "L/LL4", + "reclat": "38.400000", + "reclong": "-84.250000", + "year": "1877-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.83333, 35.61667] }, + "id": "5504", + "mass": "18000", + "name": "Dahmani", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "35.616670", + "reclong": "8.833330", + "year": "1981-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.96667, 26.91667] }, + "id": "5511", + "mass": "5650", + "name": "Dandapur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "26.916670", + "reclong": "83.966670", + "year": "1878-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [24.56667, -28.2] }, + "id": "5513", + "mass": "1064", + "name": "Daniel's Kuil", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "-28.200000", + "reclong": "24.566670", + "year": "1868-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "29", + ":@computed_region_nnqa_25f4": "103", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87.06667, 34.4] }, + "id": "5514", + "mass": "2000", + "name": "Danville", + "nametype": "Valid", + "recclass": "L6", + "reclat": "34.400000", + "reclong": "-87.066670", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.65, 49.86667] }, + "id": "6603", + "mass": "100", + "name": "Darmstadt", + "nametype": "Valid", + "recclass": "H5", + "reclat": "49.866670", + "reclong": "8.650000", + "year": "1804-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [59.685, 41.98444] }, + "id": "6604", + "mass": "7000", + "name": "Dashoguz", + "nametype": "Valid", + "recclass": "H5", + "reclat": "41.984440", + "reclong": "59.685000", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-79.95756, -1.87089] }, + "id": "51559", + "mass": "6580", + "name": "Daule", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-1.870890", + "reclong": "-79.957560", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-80, 43] }, + "id": "6621", + "mass": "340", + "name": "De Cewsville", + "nametype": "Valid", + "recclass": "H6", + "reclat": "43.000000", + "reclong": "-80.000000", + "year": "1887-01-01T00:00:00.000Z" + }, + { + ":@computed_region_nnqa_25f4": "2491", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-74, 40.25] }, + "id": "6634", + "mass": "28", + "name": "Deal", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.250000", + "reclong": "-74.000000", + "year": "1829-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.25, 28.56667] }, + "id": "6642", + "mass": "0.8", + "name": "Delhi", + "nametype": "Valid", + "recclass": "L5", + "reclat": "28.566670", + "reclong": "77.250000", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.76667, 51.46667] }, + "id": "6649", + "mass": "16400", + "name": "Demina", + "nametype": "Valid", + "recclass": "L6", + "reclat": "51.466670", + "reclong": "84.766670", + "year": "1911-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "9", + ":@computed_region_nnqa_25f4": "1444", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-104.93056, 39.7825] }, + "id": "6660", + "mass": "230", + "name": "Denver", + "nametype": "Valid", + "recclass": "L6", + "reclat": "39.782500", + "reclong": "-104.930560", + "year": "1967-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [93.86667, 26.68333] }, + "id": "6664", + "mass": "12500", + "name": "Dergaon", + "nametype": "Valid", + "recclass": "H5", + "reclat": "26.683330", + "reclong": "93.866670", + "year": "2001-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [73.61667, 25.73333] }, + "id": "6693", + "mass": "25400", + "name": "Desuri", + "nametype": "Valid", + "recclass": "H6", + "reclat": "25.733330", + "reclong": "73.616670", + "year": "1962-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81, 19] }, + "id": "6694", + "mass": "12000", + "name": "Devgaon", + "nametype": "Valid", + "recclass": "H3.8", + "reclat": "19.000000", + "reclong": "81.000000", + "year": "2001-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.525, 24.225] }, + "id": "6696", + "mass": "1140", + "name": "Devri-Khera", + "nametype": "Valid", + "recclass": "L6", + "reclat": "24.225000", + "reclong": "76.525000", + "year": "1994-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [71.42722, 22.37778] }, + "id": "6698", + "mass": "45000", + "name": "Dhajala", + "nametype": "Valid", + "recclass": "H3.8", + "reclat": "22.377780", + "reclong": "71.427220", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.6, 14.88333] }, + "id": "6699", + "mass": "1800", + "name": "Dharwar", + "nametype": "Valid", + "recclass": "OC", + "reclat": "14.883330", + "reclong": "75.600000", + "year": "1848-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.46667, 32.23333] }, + "id": "7640", + "mass": "32000", + "name": "Dhurmsala", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "32.233330", + "reclong": "76.466670", + "year": "1860-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.32997, 37.35172] }, + "id": "47350", + "mass": "3396", + "name": "Didim", + "nametype": "Valid", + "recclass": "H3-5", + "reclat": "37.351720", + "reclong": "27.329970", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [18.56667, -33.75] }, + "id": "7642", + "mass": "1000", + "name": "Diep River", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-33.750000", + "reclong": "18.566670", + "year": "1906-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-60.46667, -31.88333] }, + "id": "7649", + "mass": "400", + "name": "Distrito Quebracho", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-31.883330", + "reclong": "-60.466670", + "year": "1957-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.5, -7.5] }, + "id": "7652", + "mass": "166000", + "name": "Djati-Pengilon", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-7.500000", + "reclong": "111.500000", + "year": "1884-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.05, 12.73333] }, + "id": "7656", + "mass": "3950", + "name": "Djermaia", + "nametype": "Valid", + "recclass": "H", + "reclat": "12.733330", + "reclong": "15.050000", + "year": "1961-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.55, 36.95] }, + "id": "7657", + "mass": "10000", + "name": "Djoumine", + "nametype": "Valid", + "recclass": "H5-6", + "reclat": "36.950000", + "reclong": "9.550000", + "year": "1999-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [90.33333, 23.5] }, + "id": "7658", + "mass": "3840", + "name": "Dokachi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "23.500000", + "reclong": "90.333330", + "year": "1903-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.3, 50.75] }, + "id": "7659", + "mass": "1600", + "name": "Dolgovoli", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.750000", + "reclong": "25.300000", + "year": "1864-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29, 40] }, + "id": "7661", + "mass": "438", + "name": "Domanitch", + "nametype": "Valid", + "recclass": "L5", + "reclat": "40.000000", + "reclong": "29.000000", + "year": "1907-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [119.03333, 45.5] }, + "id": "7706", + "mass": "128800", + "name": "Dong Ujimqin Qi", + "nametype": "Valid", + "recclass": "Mesosiderite", + "reclat": "45.500000", + "reclong": "119.033330", + "year": "1995-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.45, 21.86667] }, + "id": "7707", + "mass": "230", + "name": "Donga Kohrod", + "nametype": "Valid", + "recclass": "H6", + "reclat": "21.866670", + "reclong": "82.450000", + "year": "1899-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [120.78333, 32.91667] }, + "id": "7708", + "mass": "5500", + "name": "Dongtai", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "32.916670", + "reclong": "120.783330", + "year": "1970-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [112.3, 51.2] }, + "id": "7718", + "mass": "3891", + "name": "Doroninsk", + "nametype": "Valid", + "recclass": "H5-7", + "reclat": "51.200000", + "reclong": "112.300000", + "year": "1805-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.16667, 13.05] }, + "id": "7722", + "mass": "1250", + "name": "Dosso", + "nametype": "Valid", + "recclass": "L6", + "reclat": "13.050000", + "reclong": "3.166670", + "year": "1962-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.3, 32.33333] }, + "id": "7723", + "mass": "1161", + "name": "Douar Mghila", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "32.333330", + "reclong": "-6.300000", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.91667, -13.66667] }, + "id": "7725", + "mass": "642", + "name": "Dowa", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "-13.666670", + "reclong": "33.916670", + "year": "1976-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "39", + ":@computed_region_nnqa_25f4": "2115", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.5, 36.4] }, + "id": "7728", + "mass": "5000", + "name": "Drake Creek", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.400000", + "reclong": "-86.500000", + "year": "1827-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-82.26, 42.52] }, + "id": "7731", + "mass": "47700", + "name": "Dresden (Ontario)", + "nametype": "Valid", + "recclass": "H6", + "reclat": "42.520000", + "reclong": "-82.260000", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [18.44167, 42.45833] }, + "id": "7736", + "mass": "1900", + "name": "Dubrovnik", + "nametype": "Valid", + "recclass": "L3-6", + "reclat": "42.458330", + "reclong": "18.441670", + "year": "1951-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [152.83333, -31.66667] }, + "id": "7743", + "mass": "30", + "name": "Dunbogan", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-31.666670", + "reclong": "152.833330", + "year": "1999-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8.03333, 52.55] }, + "id": "7745", + "mass": "2270", + "name": "Dundrum", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.550000", + "reclong": "-8.033330", + "year": "1865-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [128.25, 43.33333] }, + "id": "7749", + "name": "Dunhua", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "43.333330", + "reclong": "128.250000", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.63333, 30.3] }, + "id": "7750", + "mass": "13200", + "name": "Durala", + "nametype": "Valid", + "recclass": "L6", + "reclat": "30.300000", + "reclong": "76.633330", + "year": "1815-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [39.5, -4] }, + "id": "7752", + "mass": "577", + "name": "Duruma", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-4.000000", + "reclong": "39.500000", + "year": "1853-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [127.26667, 33.43333] }, + "id": "7754", + "mass": "2117", + "name": "Duwun", + "nametype": "Valid", + "recclass": "L6", + "reclat": "33.433330", + "reclong": "127.266670", + "year": "1943-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.31667, -27.2] }, + "id": "7755", + "mass": "3230", + "name": "Dwaleni", + "nametype": "Valid", + "recclass": "H4-6", + "reclat": "-27.200000", + "reclong": "31.316670", + "year": "1970-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82, 26.25] }, + "id": "7757", + "mass": "300", + "name": "Dyalpur", + "nametype": "Valid", + "recclass": "Ureilite", + "reclat": "26.250000", + "reclong": "82.000000", + "year": "1872-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [151, -3] }, + "id": "7758", + "mass": "188", + "name": "Dyarrl Island", + "nametype": "Valid", + "recclass": "Mesosiderite-A1", + "reclat": "-3.000000", + "reclong": "151.000000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "19", + ":@computed_region_nnqa_25f4": "462", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96.47167, 40.78167] }, + "id": "7760", + "mass": "10000", + "name": "Eagle", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "40.781670", + "reclong": "-96.471670", + "year": "1947-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.83333, -17.3] }, + "id": "7774", + "mass": "2400", + "name": "Ehole", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-17.300000", + "reclong": "15.833330", + "year": "1961-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.21667, 48.9] }, + "id": "7775", + "mass": "3000", + "name": "EichstΓ€dt", + "nametype": "Valid", + "recclass": "H5", + "reclat": "48.900000", + "reclong": "11.216670", + "year": "1785-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13, 56.03333] }, + "id": "7776", + "mass": "3336", + "name": "Ekeby", + "nametype": "Valid", + "recclass": "H4", + "reclat": "56.033330", + "reclong": "13.000000", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.78333, 28.26667] }, + "id": "7777", + "mass": "840", + "name": "Ekh Khera", + "nametype": "Valid", + "recclass": "H6", + "reclat": "28.266670", + "reclong": "78.783330", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.25, 34.41667] }, + "id": "7807", + "mass": "10000", + "name": "El Idrissia", + "nametype": "Valid", + "recclass": "L6", + "reclat": "34.416670", + "reclong": "3.250000", + "year": "1989-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-97.37, 25.37] }, + "id": "45977", + "mass": "17226", + "name": "El Paso de Aguila", + "nametype": "Valid", + "recclass": "H5", + "reclat": "25.370000", + "reclong": "-97.370000", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.05167, 19.96722] }, + "id": "7819", + "mass": "5000", + "name": "El Tigre", + "nametype": "Valid", + "recclass": "L6", + "reclat": "19.967220", + "reclong": "-103.051670", + "year": "1993-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "9", + ":@computed_region_nnqa_25f4": "88", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-104.58817, 39.24667] }, + "id": "7822", + "mass": "680.5", + "name": "Elbert", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "39.246670", + "reclong": "-104.588170", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.73333, 50.18333] }, + "id": "7823", + "mass": "107000", + "name": "Elbogen", + "nametype": "Valid", + "recclass": "Iron, IID", + "reclat": "50.183330", + "reclong": "12.733330", + "year": "1400-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.66667, 47.83333] }, + "id": "7824", + "mass": "54640", + "name": "Elenovka", + "nametype": "Valid", + "recclass": "L5", + "reclat": "47.833330", + "reclong": "37.666670", + "year": "1951-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4, 51.75] }, + "id": "10019", + "mass": "1470", + "name": "Ellemeet", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "51.750000", + "reclong": "4.000000", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [151.61667, -29.46667] }, + "id": "10033", + "mass": "127", + "name": "Emmaville", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "-29.466670", + "reclong": "151.616670", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [109.5, 30.3] }, + "id": "10038", + "mass": "8000", + "name": "Enshi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "30.300000", + "reclong": "109.500000", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.35, 47.86667] }, + "id": "10039", + "mass": "127000", + "name": "Ensisheim", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "47.866670", + "reclong": "7.350000", + "year": "1492-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.46667, 48.18333] }, + "id": "10041", + "mass": "277", + "name": "Γ‰pinal", + "nametype": "Valid", + "recclass": "H5", + "reclat": "48.183330", + "reclong": "6.466670", + "year": "1822-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81.89167, 19.03333] }, + "id": "10042", + "mass": "113", + "name": "Erakot", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "19.033330", + "reclong": "81.891670", + "year": "1940-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [44.5, 40.3] }, + "id": "10043", + "mass": "107.2", + "name": "Erevan", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "40.300000", + "reclong": "44.500000", + "year": "1911-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [44.16667, 1.16667] }, + "id": "10044", + "mass": "20000", + "name": "Ergheo", + "nametype": "Valid", + "recclass": "L5", + "reclat": "1.166670", + "reclong": "44.166670", + "year": "1889-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.25, 52.21667] }, + "id": "10049", + "mass": "2250", + "name": "Erxleben", + "nametype": "Valid", + "recclass": "H6", + "reclat": "52.216670", + "reclong": "11.250000", + "year": "1812-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.1, 46.25] }, + "id": "10051", + "mass": "1500", + "name": "Esnandes", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.250000", + "reclong": "-1.100000", + "year": "1837-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.83333, 2.88333] }, + "id": "10055", + "mass": "500", + "name": "Essebi", + "nametype": "Valid", + "recclass": "C2-ung", + "reclat": "2.883330", + "reclong": "30.833330", + "year": "1957-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "16", + ":@computed_region_nnqa_25f4": "277", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-94.83333, 43.41667] }, + "id": "10059", + "mass": "320000", + "name": "Estherville", + "nametype": "Valid", + "recclass": "Mesosiderite-A3/4", + "reclat": "43.416670", + "reclong": "-94.833330", + "year": "1879-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1300", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-97.03333, 39.75] }, + "id": "10074", + "mass": "89400", + "name": "Farmington", + "nametype": "Valid", + "recclass": "L5", + "reclat": "39.750000", + "reclong": "-97.033330", + "year": "1890-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "2439", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-77.53333, 35.55] }, + "id": "10075", + "mass": "56000", + "name": "Farmville", + "nametype": "Valid", + "recclass": "H4", + "reclat": "35.550000", + "reclong": "-77.533330", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [2.81667, 44.38333] }, + "id": "10078", + "mass": "1500", + "name": "Favars", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.383330", + "reclong": "2.816670", + "year": "1844-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "15", + ":@computed_region_nnqa_25f4": "70", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-94.16667, 36.05] }, + "id": "10079", + "mass": "2360", + "name": "Fayetteville", + "nametype": "Valid", + "recclass": "H4", + "reclat": "36.050000", + "reclong": "-94.166670", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.45, 36.88333] }, + "id": "10080", + "mass": "380", + "name": "Feid Chair", + "nametype": "Valid", + "recclass": "H4", + "reclat": "36.883330", + "reclong": "8.450000", + "year": "1875-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "29", + ":@computed_region_nnqa_25f4": "1631", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87.16667, 32.53333] }, + "id": "10081", + "mass": "3200", + "name": "Felix", + "nametype": "Valid", + "recclass": "CO3.3", + "reclat": "32.533330", + "reclong": "-87.166670", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [116.75, 34.6] }, + "id": "10086", + "mass": "82", + "name": "Fenghsien-Ku", + "nametype": "Valid", + "recclass": "H5", + "reclat": "34.600000", + "reclong": "116.750000", + "year": "1924-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "2331", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-81.41667, 36.1] }, + "id": "10088", + "mass": "220", + "name": "Ferguson", + "nametype": "Valid", + "recclass": "OC", + "reclat": "36.100000", + "reclong": "-81.416670", + "year": "1889-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.75333, 43.18111] }, + "id": "10091", + "mass": "10200", + "name": "Fermo", + "nametype": "Valid", + "recclass": "H3-5", + "reclat": "43.181110", + "reclong": "13.753330", + "year": "1996-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "1", + ":@computed_region_nnqa_25f4": "385", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96.85, 47.81667] }, + "id": "10107", + "mass": "17600", + "name": "Fisher", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.816670", + "reclong": "-96.850000", + "year": "1894-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "807", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-97.76667, 30.83333] }, + "id": "10111", + "mass": "3640", + "name": "Florence", + "nametype": "Valid", + "recclass": "H3", + "reclat": "30.833330", + "reclong": "-97.766670", + "year": "1922-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "16", + ":@computed_region_nnqa_25f4": "1785", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-93.66667, 43.25] }, + "id": "10119", + "mass": "152000", + "name": "Forest City", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.250000", + "reclong": "-93.666670", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [146.85833, -33.35] }, + "id": "10120", + "mass": "26000", + "name": "Forest Vale", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-33.350000", + "reclong": "146.858330", + "year": "1942-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "40", + ":@computed_region_nnqa_25f4": "2839", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-78.08333, 36.78333] }, + "id": "10123", + "mass": "6067", + "name": "Forksville", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.783330", + "reclong": "-78.083330", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.31667, 50.95] }, + "id": "10163", + "mass": "240", + "name": "Forsbach", + "nametype": "Valid", + "recclass": "H6", + "reclat": "50.950000", + "reclong": "7.316670", + "year": "1900-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "31", + ":@computed_region_nnqa_25f4": "1470", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-83.96667, 33.01667] }, + "id": "10164", + "mass": "16300", + "name": "Forsyth", + "nametype": "Valid", + "recclass": "L6", + "reclat": "33.016670", + "reclong": "-83.966670", + "year": "1829-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7, 28.25] }, + "id": "10166", + "name": "Fort Flatters", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "28.250000", + "reclong": "7.000000", + "year": "1944-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "29", + ":@computed_region_nnqa_25f4": "99", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87.83333, 34.48333] }, + "id": "10177", + "mass": "650", + "name": "Frankfort (stone)", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "34.483330", + "reclong": "-87.833330", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [113.56694, 31.47556] }, + "id": "52412", + "mass": "23000", + "name": "Fuhe", + "nametype": "Valid", + "recclass": "L5", + "reclat": "31.475560", + "reclong": "113.566940", + "year": "1945-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [130.2, 33.18333] }, + "id": "10836", + "mass": "11620", + "name": "Fukutomi", + "nametype": "Valid", + "recclass": "L5", + "reclat": "33.183330", + "reclong": "130.200000", + "year": "1882-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.33333, 55.33333] }, + "id": "10838", + "name": "FΓΌnen", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "55.333330", + "reclong": "10.333330", + "year": "1654-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [80.81667, 25.95] }, + "id": "10839", + "mass": "4000", + "name": "Futtehpur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "25.950000", + "reclong": "80.816670", + "year": "1822-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.9, 32.9] }, + "id": "10840", + "mass": "2500", + "name": "Fuyang", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "32.900000", + "reclong": "115.900000", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.4, 44.3] }, + "id": "10846", + "mass": "132.69999999999999", + "name": "Galapian", + "nametype": "Valid", + "recclass": "H6", + "reclat": "44.300000", + "reclong": "0.400000", + "year": "1826-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.43333, 7.05] }, + "id": "10848", + "mass": "36.1", + "name": "Galim (a)", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "7.050000", + "reclong": "12.433330", + "year": "1952-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.43333, 7.05] }, + "id": "10849", + "mass": "28", + "name": "Galim (b)", + "nametype": "Valid", + "recclass": "EH3/4-an", + "reclat": "7.050000", + "reclong": "12.433330", + "year": "1952-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.78333, 51.68333] }, + "id": "10850", + "mass": "5000", + "name": "Galkiv", + "nametype": "Valid", + "recclass": "H4", + "reclat": "51.683330", + "reclong": "30.783330", + "year": "1995-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [68.53333, 27.35] }, + "id": "10851", + "mass": "6400", + "name": "Gambat", + "nametype": "Valid", + "recclass": "L6", + "reclat": "27.350000", + "reclong": "68.533330", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-2.18333, 11.65] }, + "id": "10854", + "name": "Gao-Guenie", + "nametype": "Valid", + "recclass": "H5", + "reclat": "11.650000", + "reclong": "-2.183330", + "year": "1960-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [68.53333, 27.88333] }, + "id": "10860", + "mass": "380", + "name": "Garhi Yasin", + "nametype": "Valid", + "recclass": "Iron, IIE", + "reclat": "27.883330", + "reclong": "68.533330", + "year": "1917-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "13", + ":@computed_region_nnqa_25f4": "2985", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-112.13333, 41.68333] }, + "id": "10861", + "mass": "102", + "name": "Garland", + "nametype": "Valid", + "recclass": "Diogenite-pm", + "reclat": "41.683330", + "reclong": "-112.133330", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.03333, 12.85] }, + "id": "44882", + "mass": "4162", + "name": "Gashua", + "nametype": "Valid", + "recclass": "L6", + "reclat": "12.850000", + "reclong": "11.033330", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-2.04167, 14.15083] }, + "id": "10866", + "name": "Gasseltepaoua", + "nametype": "Valid", + "recclass": "H5", + "reclat": "14.150830", + "reclong": "-2.041670", + "year": "2000-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.91667, 12.91667] }, + "id": "10870", + "mass": "725", + "name": "Geidam", + "nametype": "Valid", + "recclass": "H5", + "reclat": "12.916670", + "reclong": "11.916670", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.88333, 35.53333] }, + "id": "10914", + "mass": "14290", + "name": "Gifu", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.533330", + "reclong": "136.883330", + "year": "1909-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.56667, 37.31667] }, + "id": "10917", + "mass": "18000", + "name": "Girgenti", + "nametype": "Valid", + "recclass": "L6", + "reclat": "37.316670", + "reclong": "13.566670", + "year": "1853-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.91667, 9.6] }, + "id": "10919", + "mass": "480", + "name": "Git-Git", + "nametype": "Valid", + "recclass": "L6", + "reclat": "9.600000", + "reclong": "9.916670", + "year": "1947-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.86667, 52.2] }, + "id": "10923", + "mass": "670", + "name": "Glanerbrug", + "nametype": "Valid", + "recclass": "L/LL5", + "reclat": "52.200000", + "reclong": "6.866670", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [107.7, -7.25] }, + "id": "10924", + "mass": "1303", + "name": "Glanggang", + "nametype": "Valid", + "recclass": "H5-6", + "reclat": "-7.250000", + "reclong": "107.700000", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.61667, 57.35] }, + "id": "10926", + "mass": "152000", + "name": "Glasatovo", + "nametype": "Valid", + "recclass": "H4", + "reclat": "57.350000", + "reclong": "37.616670", + "year": "1918-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.3, 52.45972] }, + "id": "10930", + "mass": "767", + "name": "Glatton", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.459720", + "reclong": "-0.300000", + "year": "1991-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.76667, 50.66667] }, + "id": "10936", + "mass": "1750", + "name": "Gnadenfrei", + "nametype": "Valid", + "recclass": "H5", + "reclat": "50.666670", + "reclong": "16.766670", + "year": "1879-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [89.05, 24.23333] }, + "id": "10948", + "mass": "1600", + "name": "Gopalpur", + "nametype": "Valid", + "recclass": "H6", + "reclat": "24.233330", + "reclong": "89.050000", + "year": "1865-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [38.08333, 48.28333] }, + "id": "10949", + "mass": "3618", + "name": "Gorlovka", + "nametype": "Valid", + "recclass": "H3.7", + "reclat": "48.283330", + "reclong": "38.083330", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [2.25, 42.9] }, + "id": "10956", + "mass": "9000", + "name": "Granes", + "nametype": "Valid", + "recclass": "L6", + "reclat": "42.900000", + "reclong": "2.250000", + "year": "1964-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11, 60.66667] }, + "id": "11196", + "mass": "45.5", + "name": "Grefsheim", + "nametype": "Valid", + "recclass": "L5", + "reclat": "60.666670", + "reclong": "11.000000", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-79.61667, 43.2] }, + "id": "50911", + "mass": "215", + "name": "Grimsby", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.200000", + "reclong": "-79.616670", + "year": "2009-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [45.38333, 43.66667] }, + "id": "11206", + "mass": "3500", + "name": "Grosnaja", + "nametype": "Valid", + "recclass": "CV3", + "reclat": "43.666670", + "reclong": "45.383330", + "year": "1861-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [18.71667, 49.26667] }, + "id": "11207", + "mass": "10500", + "name": "Gross-Divina", + "nametype": "Valid", + "recclass": "H5", + "reclat": "49.266670", + "reclong": "18.716670", + "year": "1837-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.58333, 46.35] }, + "id": "11208", + "mass": "8000", + "name": "Grossliebenthal", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.350000", + "reclong": "30.583330", + "year": "1881-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.5, 51.93333] }, + "id": "11426", + "mass": "1000", + "name": "GrΓΌneberg", + "nametype": "Valid", + "recclass": "H4", + "reclat": "51.933330", + "reclong": "15.500000", + "year": "1841-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.63333, 52.86667] }, + "id": "11429", + "mass": "690", + "name": "Grzempach", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.866670", + "reclong": "16.633330", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-58.61667, -33] }, + "id": "11432", + "mass": "22000", + "name": "GualeguaychΓΊ", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-33.000000", + "reclong": "-58.616670", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [122.76389, 39.80417] }, + "id": "11435", + "mass": "2910", + "name": "Guangmingshan", + "nametype": "Valid", + "recclass": "H5", + "reclat": "39.804170", + "reclong": "122.763890", + "year": "1996-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [105, 24.1] }, + "id": "11436", + "name": "Guangnan", + "nametype": "Valid", + "recclass": "L6", + "reclat": "24.100000", + "reclong": "105.000000", + "year": "1983-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [118.4, 37.1] }, + "id": "11437", + "mass": "1900", + "name": "Guangrao", + "nametype": "Valid", + "recclass": "L6", + "reclat": "37.100000", + "reclong": "118.400000", + "year": "1980-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.01667, 38.73333] }, + "id": "11439", + "mass": "39000", + "name": "GuareΓ±a", + "nametype": "Valid", + "recclass": "H6", + "reclat": "38.733330", + "reclong": "-6.016670", + "year": "1892-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [20.23333, 43.76667] }, + "id": "11440", + "mass": "1915", + "name": "GuΓͺa", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "43.766670", + "reclong": "20.233330", + "year": "1891-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.68333, 13.5] }, + "id": "11442", + "mass": "288", + "name": "Guibga", + "nametype": "Valid", + "recclass": "L5", + "reclat": "13.500000", + "reclong": "-0.683330", + "year": "1972-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.98333, 9.91667] }, + "id": "11443", + "mass": "968", + "name": "Guidder", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "9.916670", + "reclong": "13.983330", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.05, 22.98333] }, + "id": "11448", + "mass": "2449", + "name": "Gujargaon", + "nametype": "Valid", + "recclass": "H5", + "reclat": "22.983330", + "reclong": "76.050000", + "year": "1982-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.65833, 11.49167] }, + "id": "11449", + "mass": "100000", + "name": "Gujba", + "nametype": "Valid", + "recclass": "CBa", + "reclat": "11.491670", + "reclong": "11.658330", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [24.7, 42.9] }, + "id": "11450", + "mass": "5700", + "name": "Gumoschnik", + "nametype": "Valid", + "recclass": "H5", + "reclat": "42.900000", + "reclong": "24.700000", + "year": "1904-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.56667, 13.78333] }, + "id": "11464", + "mass": "28", + "name": "Gurram Konda", + "nametype": "Valid", + "recclass": "L6", + "reclat": "13.783330", + "reclong": "78.566670", + "year": "1814-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [42.41667, 9.36667] }, + "id": "11465", + "mass": "34650", + "name": "Gursum", + "nametype": "Valid", + "recclass": "H4/5", + "reclat": "9.366670", + "reclong": "42.416670", + "year": "1981-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.38333, 51.91667] }, + "id": "11466", + "mass": "1000", + "name": "GΓΌtersloh", + "nametype": "Valid", + "recclass": "H3/4", + "reclat": "51.916670", + "reclong": "8.383330", + "year": "1851-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [127.5, 35] }, + "id": "11467", + "mass": "1320", + "name": "Gyokukei", + "nametype": "Valid", + "recclass": "OC", + "reclat": "35.000000", + "reclong": "127.500000", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [139.33333, 35.65] }, + "id": "11468", + "mass": "0.2", + "name": "Hachi-oji", + "nametype": "Valid", + "recclass": "H?", + "reclat": "35.650000", + "reclong": "139.333330", + "year": "1817-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.73333, 50.31667] }, + "id": "11472", + "mass": "9000", + "name": "Hainaut", + "nametype": "Valid", + "recclass": "H3-6", + "reclat": "50.316670", + "reclong": "3.733330", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.23333, 57.81667] }, + "id": "11479", + "mass": "1456", + "name": "Hallingeberg", + "nametype": "Valid", + "recclass": "L3.4", + "reclat": "57.816670", + "reclong": "16.233330", + "year": "1944-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "35", + ":@computed_region_nnqa_25f4": "1205", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.6, 41.38333] }, + "id": "11485", + "mass": "3710", + "name": "Hamlet", + "nametype": "Valid", + "recclass": "LL4", + "reclat": "41.383330", + "reclong": "-86.600000", + "year": "1959-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.53333, 26.8] }, + "id": "11824", + "mass": "1000", + "name": "Haraiya", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "26.800000", + "reclong": "82.533330", + "year": "1878-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.78333, 28.38333] }, + "id": "11829", + "mass": "315", + "name": "Haripura", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "28.383330", + "reclong": "75.783330", + "year": "1921-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "2025", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-94.51167, 32.675] }, + "id": "11830", + "mass": "8360", + "name": "Harleton", + "nametype": "Valid", + "recclass": "L6", + "reclat": "32.675000", + "reclong": "-94.511670", + "year": "1961-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "35", + ":@computed_region_nnqa_25f4": "1855", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.16667, 38.25] }, + "id": "11842", + "mass": "680", + "name": "Harrison County", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.250000", + "reclong": "-86.166670", + "year": "1859-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.70033, 35.2945] }, + "id": "11848", + "mass": "1110.5999999999999", + "name": "Hashima", + "nametype": "Valid", + "recclass": "H4", + "reclat": "35.294500", + "reclong": "136.700330", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.81667, 28.95] }, + "id": "11852", + "mass": "1250", + "name": "Hassi-Jekna", + "nametype": "Valid", + "recclass": "Iron, IAB-sHL", + "reclat": "28.950000", + "reclong": "0.816670", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.51667, 51.65] }, + "id": "11855", + "mass": "29000", + "name": "Hatford", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "51.650000", + "reclong": "-1.516670", + "year": "1628-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.06194, 60.24556] }, + "id": "11859", + "mass": "1544", + "name": "HaverΓΆ", + "nametype": "Valid", + "recclass": "Ureilite", + "reclat": "60.245560", + "reclong": "22.061940", + "year": "1971-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.78333, 55.46667] }, + "id": "11869", + "mass": "3500", + "name": "Hedeskoga", + "nametype": "Valid", + "recclass": "H5", + "reclat": "55.466670", + "reclong": "13.783330", + "year": "1922-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.66667, 27.33333] }, + "id": "11870", + "mass": "6100", + "name": "Hedjaz", + "nametype": "Valid", + "recclass": "L3.7-6", + "reclat": "27.333330", + "reclong": "35.666670", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-84.1, 10] }, + "id": "11875", + "mass": "1000", + "name": "Heredia", + "nametype": "Valid", + "recclass": "H5", + "reclat": "10.000000", + "reclong": "-84.100000", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [17.66667, 59.85] }, + "id": "11878", + "mass": "20000", + "name": "Hessle", + "nametype": "Valid", + "recclass": "H5", + "reclat": "59.850000", + "reclong": "17.666670", + "year": "1869-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [130.43333, 33.6] }, + "id": "11883", + "mass": "750", + "name": "Higashi-koen", + "nametype": "Valid", + "recclass": "H5", + "reclat": "33.600000", + "reclong": "130.433330", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-4.23333, 55.9] }, + "id": "11884", + "mass": "4500", + "name": "High Possil", + "nametype": "Valid", + "recclass": "L6", + "reclat": "55.900000", + "reclong": "-4.233330", + "year": "1804-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [132.38333, 34.45] }, + "id": "11889", + "mass": "414", + "name": "Hiroshima", + "nametype": "Valid", + "recclass": "H5", + "reclat": "34.450000", + "reclong": "132.383330", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.47278, 1.345] }, + "id": "44714", + "mass": "167.7", + "name": "Hoima", + "nametype": "Valid", + "recclass": "H6", + "reclat": "1.345000", + "reclong": "31.472780", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.2, 64.43333] }, + "id": "11893", + "mass": "305.5", + "name": "HΓΆkmark", + "nametype": "Valid", + "recclass": "L4", + "reclat": "64.433330", + "reclong": "21.200000", + "year": "1954-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "7", + ":@computed_region_nnqa_25f4": "990", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-110.18333, 34.9] }, + "id": "11894", + "mass": "220000", + "name": "Holbrook", + "nametype": "Valid", + "recclass": "L/LL6", + "reclat": "34.900000", + "reclong": "-110.183330", + "year": "1912-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [38.41667, 9.06667] }, + "id": "11895", + "mass": "1415", + "name": "Holetta", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "9.066670", + "reclong": "38.416670", + "year": "1923-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "16", + ":@computed_region_nnqa_25f4": "284", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-91.86667, 41.8] }, + "id": "11901", + "mass": "230000", + "name": "Homestead", + "nametype": "Valid", + "recclass": "L5", + "reclat": "41.800000", + "reclong": "-91.866670", + "year": "1875-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "4", + ":@computed_region_nnqa_25f4": "1657", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-157.86667, 21.3] }, + "id": "11904", + "mass": "2420", + "name": "Honolulu", + "nametype": "Valid", + "recclass": "L5", + "reclat": "21.300000", + "reclong": "-157.866670", + "year": "1825-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.5, 35.66667] }, + "id": "11913", + "mass": "180", + "name": "Hotse", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.666670", + "reclong": "115.500000", + "year": "1956-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1293", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-100.45, 39.35] }, + "id": "11915", + "mass": "266.10000000000002", + "name": "Hoxie", + "nametype": "Valid", + "recclass": "OC", + "reclat": "39.350000", + "reclong": "-100.450000", + "year": "1963-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.33333, 46.1] }, + "id": "11916", + "mass": "49000", + "name": "Hraschina", + "nametype": "Valid", + "recclass": "Iron, IID", + "reclat": "46.100000", + "reclong": "16.333330", + "year": "1751-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [106.63241, 26.46469] }, + "id": "54719", + "mass": "1600", + "name": "Huaxi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "26.464690", + "reclong": "106.632410", + "year": "2010-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.91667, 50.3] }, + "id": "11986", + "mass": "112", + "name": "Hungen", + "nametype": "Valid", + "recclass": "H6", + "reclat": "50.300000", + "reclong": "8.916670", + "year": "1877-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.68333, 61.18333] }, + "id": "11989", + "mass": "14000", + "name": "Hvittis", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "61.183330", + "reclong": "22.683330", + "year": "1901-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.7, 52.28333] }, + "id": "11992", + "mass": "2000", + "name": "IbbenbΓΌren", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "52.283330", + "reclong": "7.700000", + "year": "1870-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-45, -20] }, + "id": "11993", + "mass": "2500", + "name": "Ibitira", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "-20.000000", + "reclong": "-45.000000", + "year": "1957-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35, 38] }, + "id": "11994", + "name": "Ibrisim", + "nametype": "Valid", + "recclass": "OC", + "reclat": "38.000000", + "reclong": "35.000000", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.93333, 58.2] }, + "id": "11995", + "mass": "3973", + "name": "Ichkala", + "nametype": "Valid", + "recclass": "H6", + "reclat": "58.200000", + "reclong": "82.933330", + "year": "1936-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28.33333, -32.1] }, + "id": "12000", + "mass": "3457", + "name": "Idutywa", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-32.100000", + "reclong": "28.333330", + "year": "1956-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-51.83333, -23.2] }, + "id": "12003", + "mass": "1200", + "name": "Iguaracu", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-23.200000", + "reclong": "-51.833330", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [145.36667, -6.03333] }, + "id": "12004", + "mass": "7330", + "name": "Ijopega", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-6.033330", + "reclong": "145.366670", + "year": "1975-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [46.66667, 39.75] }, + "id": "12027", + "mass": "27000", + "name": "Indarch", + "nametype": "Valid", + "recclass": "EH4", + "reclat": "39.750000", + "reclong": "46.666670", + "year": "1891-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "525", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-94.4, 39.08333] }, + "id": "12028", + "mass": "880", + "name": "Independence", + "nametype": "Valid", + "recclass": "L6", + "reclat": "39.083330", + "reclong": "-94.400000", + "year": "1917-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [112, 41] }, + "id": "12037", + "mass": "3000", + "name": "Inner Mongolia", + "nametype": "Valid", + "recclass": "L6", + "reclat": "41.000000", + "reclong": "112.000000", + "year": "1963-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-111.3375, 53.415] }, + "id": "12039", + "mass": "4576", + "name": "Innisfree", + "nametype": "Valid", + "recclass": "L5", + "reclat": "53.415000", + "reclong": "-111.337500", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-54.5, -25.5] }, + "id": "12043", + "mass": "7000", + "name": "Ipiranga", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-25.500000", + "reclong": "-54.500000", + "year": "1972-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.8, -8.93333] }, + "id": "12049", + "mass": "1300", + "name": "Ishinga", + "nametype": "Valid", + "recclass": "H", + "reclat": "-8.933330", + "reclong": "33.800000", + "year": "1954-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-57.95, -31.18333] }, + "id": "12053", + "mass": "3050", + "name": "Isthilart", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-31.183330", + "reclong": "-57.950000", + "year": "1928-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-44.33333, -3.4] }, + "id": "12056", + "mass": "2024", + "name": "Itapicuru-Mirim", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-3.400000", + "reclong": "-44.333330", + "year": "1879-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-12.95217, 26.59083] }, + "id": "12058", + "mass": "4720", + "name": "Itqiy", + "nametype": "Valid", + "recclass": "EH7-an", + "reclat": "26.590830", + "reclong": "-12.952170", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [32.43333, -8.41667] }, + "id": "12063", + "mass": "704.5", + "name": "Ivuna", + "nametype": "Valid", + "recclass": "CI1", + "reclat": "-8.416670", + "reclong": "32.433330", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.9, -32.5] }, + "id": "12065", + "mass": "48000", + "name": "Jackalsfontein", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-32.500000", + "reclong": "21.900000", + "year": "1903-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [68.41667, 26.75] }, + "id": "12067", + "mass": "973", + "name": "Jajh deh Kot Lalu", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "26.750000", + "reclong": "68.416670", + "year": "1926-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "12068", + "mass": "700", + "name": "Jalanash", + "nametype": "Valid", + "recclass": "Ureilite", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75, 31] }, + "id": "12069", + "mass": "1967", + "name": "Jalandhar", + "nametype": "Valid", + "recclass": "Iron", + "reclat": "31.000000", + "reclong": "75.000000", + "year": "1621-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.33333, 18.75] }, + "id": "12072", + "mass": "22", + "name": "Jamkheir", + "nametype": "Valid", + "recclass": "H6", + "reclat": "18.750000", + "reclong": "75.333330", + "year": "1866-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [105.8, 39.7] }, + "id": "12074", + "mass": "20500", + "name": "Jartai", + "nametype": "Valid", + "recclass": "L6", + "reclat": "39.700000", + "reclong": "105.800000", + "year": "1979-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [20.44167, 43.83333] }, + "id": "12078", + "mass": "34000", + "name": "Jelica", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "43.833330", + "reclong": "20.441670", + "year": "1889-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "12079", + "mass": "450", + "name": "Jemlapur", + "nametype": "Valid", + "recclass": "L6", + "year": "1901-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.05217, 46.42137] }, + "id": "51589", + "mass": "3667", + "name": "Jesenice", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.421370", + "reclong": "14.052170", + "year": "2009-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [72.38333, 31.3] }, + "id": "12085", + "mass": "5900", + "name": "Jhung", + "nametype": "Valid", + "recclass": "L5", + "reclat": "31.300000", + "reclong": "72.383330", + "year": "1873-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [104.91667, 31.91667] }, + "id": "12086", + "mass": "222", + "name": "Jiange", + "nametype": "Valid", + "recclass": "H5", + "reclat": "31.916670", + "reclong": "104.916670", + "year": "1964-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [109.5, 30.80833] }, + "id": "12087", + "mass": "600000", + "name": "Jianshi", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "30.808330", + "reclong": "109.500000", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [126.16667, 44.05] }, + "id": "12171", + "mass": "4000000", + "name": "Jilin", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.050000", + "reclong": "126.166670", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [70.31333, 22.68] }, + "id": "47362", + "mass": "100", + "name": "Jodiya", + "nametype": "Valid", + "recclass": "L5", + "reclat": "22.680000", + "reclong": "70.313330", + "year": "2006-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [24.4, 55.7] }, + "id": "12173", + "mass": "30", + "name": "Jodzie", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "55.700000", + "reclong": "24.400000", + "year": "1877-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "9", + ":@computed_region_nnqa_25f4": "1072", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-104.9, 40.35] }, + "id": "12198", + "mass": "40300", + "name": "Johnstown", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "40.350000", + "reclong": "-104.900000", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.83333, -11.85] }, + "id": "12199", + "mass": "483", + "name": "Jolomba", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "-11.850000", + "reclong": "15.833330", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.45, 45.43333] }, + "id": "12202", + "mass": "5000", + "name": "Jonzac", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "45.433330", + "reclong": "-0.450000", + "year": "1819-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.41667, 35.5] }, + "id": "12203", + "mass": "100000", + "name": "Juancheng", + "nametype": "Valid", + "recclass": "H5", + "reclat": "35.500000", + "reclong": "115.416670", + "year": "1997-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.8, 12.85] }, + "id": "12207", + "mass": "680", + "name": "Judesegeri", + "nametype": "Valid", + "recclass": "H6", + "reclat": "12.850000", + "reclong": "76.800000", + "year": "1876-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.2, -7.71667] }, + "id": "12209", + "mass": "32490", + "name": "Jumapalo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-7.716670", + "reclong": "111.200000", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [118.8, 35.2] }, + "id": "12210", + "mass": "950", + "name": "Junan", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.200000", + "reclong": "118.800000", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.27, 38.74028] }, + "id": "12213", + "mass": "25250", + "name": "Juromenha", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "38.740280", + "reclong": "-7.270000", + "year": "1968-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4.3, 44.71667] }, + "id": "12214", + "mass": "91000", + "name": "Juvinas", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "44.716670", + "reclong": "4.300000", + "year": "1821-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.3, 47.35] }, + "id": "12218", + "mass": "3000", + "name": "Kaba", + "nametype": "Valid", + "recclass": "CV3", + "reclat": "47.350000", + "reclong": "21.300000", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.21667, 11.85] }, + "id": "12220", + "mass": "13400", + "name": "Kabo", + "nametype": "Valid", + "recclass": "H4", + "reclat": "11.850000", + "reclong": "8.216670", + "year": "1971-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.33333, 27.08333] }, + "id": "12221", + "mass": "89", + "name": "Kadonah", + "nametype": "Valid", + "recclass": "H6", + "reclat": "27.083330", + "reclong": "78.333330", + "year": "1822-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [79.96667, 27.25] }, + "id": "12222", + "mass": "230", + "name": "Kaee", + "nametype": "Valid", + "recclass": "H5", + "reclat": "27.250000", + "reclong": "79.966670", + "year": "1838-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.83333, 49.86667] }, + "id": "12227", + "mass": "1900", + "name": "Kagarlyk", + "nametype": "Valid", + "recclass": "L6", + "reclat": "49.866670", + "reclong": "30.833330", + "year": "1908-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [48.3, 15] }, + "id": "12228", + "mass": "2000", + "name": "Kaidun", + "nametype": "Valid", + "recclass": "CR2", + "reclat": "15.000000", + "reclong": "48.300000", + "year": "1980-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [53.25, 55.43333] }, + "id": "12229", + "mass": "200000", + "name": "Kainsaz", + "nametype": "Valid", + "recclass": "CO3.2", + "reclat": "55.433330", + "reclong": "53.250000", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.51667, 12.38333] }, + "id": "12230", + "mass": "350", + "name": "Kakangari", + "nametype": "Valid", + "recclass": "K3", + "reclat": "12.383330", + "reclong": "78.516670", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.66667, 45.13333] }, + "id": "12231", + "mass": "577", + "name": "Kakowa", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.133330", + "reclong": "21.666670", + "year": "1858-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.5, -6.83333] }, + "id": "12232", + "mass": "950", + "name": "Kalaba", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-6.833330", + "reclong": "29.500000", + "year": "1951-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [73.98333, 17.83333] }, + "id": "12236", + "mass": "4500", + "name": "Kalumbi", + "nametype": "Valid", + "recclass": "L6", + "reclat": "17.833330", + "reclong": "73.983330", + "year": "1879-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81.46667, 26.03333] }, + "id": "12238", + "mass": "2770", + "name": "Kamalpur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "26.033330", + "reclong": "81.466670", + "year": "1942-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [139.95667, 36.04167] }, + "id": "12240", + "mass": "448", + "name": "Kamiomi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "36.041670", + "reclong": "139.956670", + "year": "1913-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.8, 14.18333] }, + "id": "12241", + "mass": "1293", + "name": "Kamsagar", + "nametype": "Valid", + "recclass": "L6", + "reclat": "14.183330", + "reclong": "75.800000", + "year": "1902-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [65.78333, 31.6] }, + "id": "12243", + "mass": "299", + "name": "Kandahar (Afghanistan)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "31.600000", + "reclong": "65.783330", + "year": "1959-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.5, -7] }, + "id": "12245", + "mass": "1630", + "name": "Kangean", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-7.000000", + "reclong": "115.500000", + "year": "1908-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.3, 32.08333] }, + "id": "12246", + "mass": "400", + "name": "Kangra Valley", + "nametype": "Valid", + "recclass": "H5", + "reclat": "32.083330", + "reclong": "76.300000", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.63333, 4.7] }, + "id": "12251", + "mass": "11355", + "name": "Kapoeta", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "4.700000", + "reclong": "33.633330", + "year": "1942-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [73.22329, 20.33916] }, + "id": "47357", + "mass": "1600", + "name": "Kaprada", + "nametype": "Valid", + "recclass": "L5/6", + "reclat": "20.339160", + "reclong": "73.223290", + "year": "2004-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [73.36667, 42.45] }, + "id": "12253", + "mass": "3500", + "name": "Kaptal-Aryk", + "nametype": "Valid", + "recclass": "L6", + "reclat": "42.450000", + "reclong": "73.366670", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81.01667, 47.21667] }, + "id": "12256", + "mass": "3000", + "name": "Karakol", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "47.216670", + "reclong": "81.016670", + "year": "1840-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.58333, -3.5] }, + "id": "12258", + "mass": "2220", + "name": "Karatu", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "-3.500000", + "reclong": "35.583330", + "year": "1963-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.15, 12.9] }, + "id": "12260", + "mass": "180", + "name": "Karewar", + "nametype": "Valid", + "recclass": "L6", + "reclat": "12.900000", + "reclong": "7.150000", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [67.16667, 27.8] }, + "id": "12262", + "mass": "22000", + "name": "Karkh", + "nametype": "Valid", + "recclass": "L6", + "reclat": "27.800000", + "reclong": "67.166670", + "year": "1905-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [71.6, 31.58333] }, + "id": "12263", + "mass": "2950", + "name": "Karloowala", + "nametype": "Valid", + "recclass": "L6", + "reclat": "31.583330", + "reclong": "71.600000", + "year": "1955-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [139.91667, -35.08333] }, + "id": "12264", + "mass": "41730", + "name": "Karoonda", + "nametype": "Valid", + "recclass": "CK4", + "reclat": "-35.083330", + "reclong": "139.916670", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.76667, 35.36667] }, + "id": "12266", + "mass": "710", + "name": "Kasamatsu", + "nametype": "Valid", + "recclass": "H", + "reclat": "35.366670", + "reclong": "136.766670", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.58333, 29.58333] }, + "id": "30740", + "mass": "16820", + "name": "Kasauli", + "nametype": "Valid", + "recclass": "H4", + "reclat": "29.583330", + "reclong": "77.583330", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.08333, 11.33333] }, + "id": "35465", + "mass": "1500", + "name": "Katagum", + "nametype": "Valid", + "recclass": "L6", + "reclat": "11.333330", + "reclong": "10.083330", + "year": "1999-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.81333, 25.14333] }, + "id": "47351", + "mass": "6800", + "name": "Kavarpura", + "nametype": "Valid", + "recclass": "Iron, IIE-an", + "reclat": "25.143330", + "reclong": "75.813330", + "year": "2006-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.78, 39.26333] }, + "id": "12268", + "mass": "85000", + "name": "Kayakent", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "39.263330", + "reclong": "31.780000", + "year": "1961-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [112.01667, -7.75] }, + "id": "12270", + "mass": "3300", + "name": "Kediri", + "nametype": "Valid", + "recclass": "L4", + "reclat": "-7.750000", + "reclong": "112.016670", + "year": "1940-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.41822, 36.54194] }, + "id": "53654", + "mass": "5760", + "name": "Kemer", + "nametype": "Valid", + "recclass": "L4", + "reclat": "36.541940", + "reclong": "29.418220", + "year": "2008-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "3190", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96, 29.45] }, + "id": "12275", + "mass": "6937", + "name": "Kendleton", + "nametype": "Valid", + "recclass": "L4", + "reclat": "29.450000", + "reclong": "-96.000000", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [86.70278, 20.4625] }, + "id": "12276", + "mass": "6669.2", + "name": "Kendrapara", + "nametype": "Valid", + "recclass": "H4-5", + "reclat": "20.462500", + "reclong": "86.702780", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.3, 48.4] }, + "id": "12282", + "mass": "5000", + "name": "Kerilis", + "nametype": "Valid", + "recclass": "H5", + "reclat": "48.400000", + "reclong": "-3.300000", + "year": "1874-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.08333, 48.11667] }, + "id": "12284", + "mass": "80000", + "name": "Kernouve", + "nametype": "Valid", + "recclass": "H6", + "reclat": "48.116670", + "reclong": "-3.083330", + "year": "1869-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [141.61667, 38.98333] }, + "id": "12286", + "mass": "135000", + "name": "Kesen", + "nametype": "Valid", + "recclass": "H4", + "reclat": "38.983330", + "reclong": "141.616670", + "year": "1850-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [72.3, 29.53333] }, + "id": "12288", + "mass": "13600", + "name": "Khairpur", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "29.533330", + "reclong": "72.300000", + "year": "1873-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.11667, 25.55] }, + "id": "12289", + "mass": "3698", + "name": "Khanpur", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "25.550000", + "reclong": "83.116670", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.075, 50.625] }, + "id": "12291", + "mass": "1500", + "name": "Kharkov", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.625000", + "reclong": "35.075000", + "year": "1787-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.88333, 26.95] }, + "id": "12294", + "mass": "450", + "name": "Kheragur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "26.950000", + "reclong": "77.883330", + "year": "1860-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.81667, 28.01667] }, + "id": "12296", + "mass": "100", + "name": "Khetri", + "nametype": "Valid", + "recclass": "H6", + "reclat": "28.016670", + "reclong": "75.816670", + "year": "1867-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.33333, 56.75] }, + "id": "12297", + "mass": "6109", + "name": "Khmelevka", + "nametype": "Valid", + "recclass": "L5", + "reclat": "56.750000", + "reclong": "75.333330", + "year": "1929-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81.53333, 25.1] }, + "id": "12298", + "mass": "9700", + "name": "Khohar", + "nametype": "Valid", + "recclass": "L3.6", + "reclat": "25.100000", + "reclong": "81.533330", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [36, 16] }, + "id": "12299", + "mass": "3200", + "name": "Khor Temiki", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "16.000000", + "reclong": "36.000000", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28, 14] }, + "id": "12300", + "mass": "100000", + "name": "Kidairat", + "nametype": "Valid", + "recclass": "H6", + "reclat": "14.000000", + "reclong": "28.000000", + "year": "1983-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.15, 54.4] }, + "id": "12301", + "mass": "737.6", + "name": "Kiel", + "nametype": "Valid", + "recclass": "L6", + "reclat": "54.400000", + "reclong": "10.150000", + "year": "1962-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-11.33333, 16.58333] }, + "id": "12303", + "mass": "1500", + "name": "Kiffa", + "nametype": "Valid", + "recclass": "H5", + "reclat": "16.583330", + "reclong": "-11.333330", + "year": "1970-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [138.38333, 36.85] }, + "id": "12305", + "mass": "331", + "name": "Kijima (1906)", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "36.850000", + "reclong": "138.383330", + "year": "1906-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [34, 55] }, + "id": "12306", + "mass": "195", + "name": "Kikino", + "nametype": "Valid", + "recclass": "H6", + "reclat": "55.000000", + "reclong": "34.000000", + "year": "1809-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.8, 12.76667] }, + "id": "12307", + "mass": "19000", + "name": "Kilabo", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "12.766670", + "reclong": "9.800000", + "year": "2002-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "41", + ":@computed_region_nnqa_25f4": "2971", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-89.6, 43.58333] }, + "id": "12308", + "mass": "772", + "name": "Kilbourn", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.583330", + "reclong": "-89.600000", + "year": "1911-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.66667, 54.66667] }, + "id": "12309", + "mass": "140", + "name": "Killeter", + "nametype": "Valid", + "recclass": "H6", + "reclat": "54.666670", + "reclong": "-7.666670", + "year": "1844-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [24.68333, 11.63333] }, + "id": "12316", + "mass": "67.400000000000006", + "name": "Kingai", + "nametype": "Valid", + "recclass": "H6", + "reclat": "11.633330", + "reclong": "24.683330", + "year": "1967-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "2018", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-95.95, 30.75] }, + "id": "12321", + "mass": "97.7", + "name": "Kirbyville", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "30.750000", + "reclong": "-95.950000", + "year": "1906-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.30833, 48.16667] }, + "id": "12325", + "mass": "1550", + "name": "KisvarsΓ‘ny", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.166670", + "reclong": "22.308330", + "year": "1914-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-80.38333, 43.38333] }, + "id": "12326", + "mass": "202.6", + "name": "Kitchener", + "nametype": "Valid", + "recclass": "L6", + "reclat": "43.383330", + "reclong": "-80.383330", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.8, 51.6] }, + "id": "12332", + "mass": "3250", + "name": "Klein-Wenden", + "nametype": "Valid", + "recclass": "H6", + "reclat": "51.600000", + "reclong": "10.800000", + "year": "1843-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.4, 48.9] }, + "id": "12335", + "mass": "500000", + "name": "Knyahinya", + "nametype": "Valid", + "recclass": "L/LL5", + "reclat": "48.900000", + "reclong": "22.400000", + "year": "1866-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [135.16667, 34.73333] }, + "id": "12336", + "mass": "136", + "name": "Kobe", + "nametype": "Valid", + "recclass": "CK4", + "reclat": "34.733330", + "reclong": "135.166670", + "year": "1999-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [133.95, 34.3] }, + "id": "12342", + "mass": "11510", + "name": "Kokubunji", + "nametype": "Valid", + "recclass": "L6", + "reclat": "34.300000", + "reclong": "133.950000", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [139.75, 35.73333] }, + "id": "12343", + "mass": "238", + "name": "Komagome", + "nametype": "Valid", + "recclass": "Iron", + "reclat": "35.733330", + "reclong": "139.750000", + "year": "1926-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.16667, 42.51667] }, + "id": "12344", + "mass": "90", + "name": "Konovo", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "42.516670", + "reclong": "26.166670", + "year": "1931-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.17633, 48.76367] }, + "id": "53810", + "mass": "4300", + "name": "KoΕ‘ice", + "nametype": "Valid", + "recclass": "H5", + "reclat": "48.763670", + "reclong": "21.176330", + "year": "2010-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.46472, 49.32694] }, + "id": "12353", + "mass": "16500", + "name": "KrΓ€henberg", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "49.326940", + "reclong": "7.464720", + "year": "1869-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [40.9, 54.03333] }, + "id": "12355", + "mass": "2440", + "name": "Krasnoi-Ugol", + "nametype": "Valid", + "recclass": "L6", + "reclat": "54.033330", + "reclong": "40.900000", + "year": "1829-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [56.08333, 54.33333] }, + "id": "12357", + "mass": "4000", + "name": "Krasnyi Klyuch", + "nametype": "Valid", + "recclass": "H5", + "reclat": "54.333330", + "reclong": "56.083330", + "year": "1946-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77, 56.8] }, + "id": "12363", + "mass": "845.2", + "name": "Krutikha", + "nametype": "Valid", + "recclass": "OC", + "reclat": "56.800000", + "reclong": "77.000000", + "year": "1906-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.76667, 47.83333] }, + "id": "12364", + "mass": "50000", + "name": "Krymka", + "nametype": "Valid", + "recclass": "LL3.2", + "reclat": "47.833330", + "reclong": "30.766670", + "year": "1946-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.7, 51.15] }, + "id": "12368", + "mass": "2250", + "name": "Kukschin", + "nametype": "Valid", + "recclass": "L6", + "reclat": "51.150000", + "reclong": "31.700000", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [66.80222, 30.73111] }, + "id": "12369", + "mass": "453.6", + "name": "Kulak", + "nametype": "Valid", + "recclass": "L5", + "reclat": "30.731110", + "reclong": "66.802220", + "year": "1961-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.5, 50.75] }, + "id": "12370", + "mass": "6000", + "name": "Kuleschovka", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.750000", + "reclong": "33.500000", + "year": "1811-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [45, 41.11667] }, + "id": "12373", + "mass": "3719", + "name": "Kulp", + "nametype": "Valid", + "recclass": "H6", + "reclat": "41.116670", + "reclong": "45.000000", + "year": "1906-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [61.36667, 55.78333] }, + "id": "12377", + "mass": "200000", + "name": "Kunashak", + "nametype": "Valid", + "recclass": "L6", + "reclat": "55.783330", + "reclong": "61.366670", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [59.2, 42.25] }, + "id": "12379", + "mass": "1100000", + "name": "Kunya-Urgench", + "nametype": "Valid", + "recclass": "H5", + "reclat": "42.250000", + "reclong": "59.200000", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [138.38333, 37.05] }, + "id": "12381", + "mass": "4460", + "name": "Kushiike", + "nametype": "Valid", + "recclass": "OC", + "reclat": "37.050000", + "reclong": "138.383330", + "year": "1920-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.38333, 29.68333] }, + "id": "12382", + "mass": "5", + "name": "Kusiali", + "nametype": "Valid", + "recclass": "L6", + "reclat": "29.683330", + "reclong": "78.383330", + "year": "1860-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [39.3, 44.51667] }, + "id": "12383", + "mass": "23", + "name": "Kutais", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.516670", + "reclong": "39.300000", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.03333, 10.83333] }, + "id": "12384", + "mass": "45000", + "name": "Kuttippuram", + "nametype": "Valid", + "recclass": "L6", + "reclat": "10.833330", + "reclong": "76.033330", + "year": "1914-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.33333, 55.2] }, + "id": "12385", + "mass": "4047", + "name": "Kuznetzovo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "55.200000", + "reclong": "75.333330", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [130.63333, 32.03333] }, + "id": "12390", + "mass": "45000", + "name": "Kyushu", + "nametype": "Valid", + "recclass": "L6", + "reclat": "32.033330", + "reclong": "130.633330", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.75, 47.08333] }, + "id": "12392", + "mass": "2800", + "name": "La BΓ©casse", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.083330", + "reclong": "1.750000", + "year": "1879-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-101.28333, 20.66667] }, + "id": "12394", + "mass": "399", + "name": "La Charca", + "nametype": "Valid", + "recclass": "OC", + "reclat": "20.666670", + "reclong": "-101.283330", + "year": "1878-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-61.53333, -37.33333] }, + "id": "12395", + "mass": "2000", + "name": "La Colina", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-37.333330", + "reclong": "-61.533330", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-58.16667, -31.23333] }, + "id": "12396", + "mass": "45000", + "name": "La Criolla", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-31.233330", + "reclong": "-58.166670", + "year": "1985-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.58333, 44.28333] }, + "id": "12408", + "mass": "3833", + "name": "Laborel", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.283330", + "reclong": "5.583330", + "year": "1871-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.71667, 26.78333] }, + "id": "12433", + "mass": "900", + "name": "Lahrauli", + "nametype": "Valid", + "recclass": "Ureilite", + "reclat": "26.783330", + "reclong": "82.716670", + "year": "1955-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.63333, 48.76667] }, + "id": "12434", + "mass": "37000", + "name": "L'Aigle", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.766670", + "reclong": "0.633330", + "year": "1803-01-01T00:00:00.000Z" + }, + { + "fall": "Found", + "id": "32531", + "mass": "9.6", + "name": "Cumulus Hills 04075", + "nametype": "Valid", + "recclass": "Pallasite", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.03333, 21.86667] }, + "id": "12435", + "mass": "212.5", + "name": "Lakangaon", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "21.866670", + "reclong": "76.033330", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.56667, 24.45] }, + "id": "12451", + "mass": "372", + "name": "Lalitpur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "24.450000", + "reclong": "78.566670", + "year": "1887-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.06667, 47.7] }, + "id": "12455", + "mass": "51700", + "name": "LancΓ©", + "nametype": "Valid", + "recclass": "CO3.5", + "reclat": "47.700000", + "reclong": "1.066670", + "year": "1872-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.11667, 43.75] }, + "id": "12456", + "mass": "7000", + "name": "Lancon", + "nametype": "Valid", + "recclass": "H6", + "reclat": "43.750000", + "reclong": "5.116670", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.73333, 58.85] }, + "id": "12461", + "mass": "2300", + "name": "LΓ₯nghalsen", + "nametype": "Valid", + "recclass": "L6", + "reclat": "58.850000", + "reclong": "16.733330", + "year": "1947-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [126.19611, 46.24167] }, + "id": "12464", + "mass": "1282", + "name": "Lanxi", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.241670", + "reclong": "126.196110", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.23333, 47.75] }, + "id": "12465", + "mass": "7000", + "name": "Lanzenkirchen", + "nametype": "Valid", + "recclass": "L4", + "reclat": "47.750000", + "reclong": "16.233330", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.16667, 33.13333] }, + "id": "12466", + "mass": "14250", + "name": "Laochenzhen", + "nametype": "Valid", + "recclass": "H5", + "reclat": "33.133330", + "reclong": "115.166670", + "year": "1987-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.11667, 51.9] }, + "id": "12740", + "mass": "1060", + "name": "Launton", + "nametype": "Valid", + "recclass": "L6", + "reclat": "51.900000", + "reclong": "-1.116670", + "year": "1830-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [51.56667, 52.45] }, + "id": "12743", + "mass": "800", + "name": "Lavrentievka", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.450000", + "reclong": "51.566670", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.43333, 47.16667] }, + "id": "12748", + "mass": "3000", + "name": "Le Pressoir", + "nametype": "Valid", + "recclass": "H5", + "reclat": "47.166670", + "reclong": "0.433330", + "year": "1845-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.86667, 48.53333] }, + "id": "12749", + "mass": "780", + "name": "Le Teilleul", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "48.533330", + "reclong": "-0.866670", + "year": "1845-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "20", + ":@computed_region_nnqa_25f4": "608", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.33333, 35.88333] }, + "id": "12755", + "mass": "51500", + "name": "Leedey", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.883330", + "reclong": "-99.333330", + "year": "1943-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28.36667, -25.66667] }, + "id": "12756", + "mass": "460", + "name": "Leeuwfontein", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-25.666670", + "reclong": "28.366670", + "year": "1912-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.96667, 52.66667] }, + "id": "12759", + "mass": "271.39999999999998", + "name": "Leighlinbridge", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.666670", + "reclong": "-6.966670", + "year": "1999-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "29", + ":@computed_region_nnqa_25f4": "1585", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87.5, 34.58333] }, + "id": "12760", + "mass": "877", + "name": "Leighton", + "nametype": "Valid", + "recclass": "H5", + "reclat": "34.583330", + "reclong": "-87.500000", + "year": "1907-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [32.85, 52.26667] }, + "id": "12765", + "mass": "700", + "name": "Leonovka", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.266670", + "reclong": "32.850000", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.25, 48.35] }, + "id": "12769", + "mass": "125", + "name": "Les Ormes", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.350000", + "reclong": "3.250000", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4.73333, 50.36667] }, + "id": "12772", + "mass": "2000", + "name": "Lesves", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.366670", + "reclong": "4.733330", + "year": "1896-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.18333, -26.15] }, + "id": "14646", + "mass": "4000", + "name": "Lichtenberg", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-26.150000", + "reclong": "26.183330", + "year": "1973-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.86667, 56.65] }, + "id": "14650", + "mass": "6862", + "name": "Lillaverke", + "nametype": "Valid", + "recclass": "H5", + "reclat": "56.650000", + "reclong": "15.866670", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8.78333, 52.56667] }, + "id": "14652", + "mass": "50000", + "name": "Limerick", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.566670", + "reclong": "-8.783330", + "year": "1813-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.9, 52.75] }, + "id": "14655", + "mass": "1862", + "name": "Linum", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.750000", + "reclong": "12.900000", + "year": "1854-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [118.98333, 31.63333] }, + "id": "14659", + "mass": "498", + "name": "Lishui", + "nametype": "Valid", + "recclass": "L5", + "reclat": "31.633330", + "reclong": "118.983330", + "year": "1978-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.85, 50.2] }, + "id": "14661", + "mass": "12800", + "name": "Lissa", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.200000", + "reclong": "14.850000", + "year": "1808-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "2171", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-92.08333, 37.91667] }, + "id": "14664", + "mass": "491", + "name": "Little Piney", + "nametype": "Valid", + "recclass": "L5", + "reclat": "37.916670", + "reclong": "-92.083330", + "year": "1839-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.43333, 56] }, + "id": "14670", + "mass": "5213", + "name": "Lixna", + "nametype": "Valid", + "recclass": "H4", + "reclat": "56.000000", + "reclong": "26.433330", + "year": "1820-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [71.8, 29.53333] }, + "id": "14675", + "mass": "1000", + "name": "Lodran", + "nametype": "Valid", + "recclass": "Lodranite", + "reclat": "29.533330", + "reclong": "71.800000", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [72.62667, 26.96556] }, + "id": "14678", + "mass": "40000", + "name": "Lohawat", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "26.965560", + "reclong": "72.626670", + "year": "1994-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "40", + ":@computed_region_nnqa_25f4": "2770", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-77.21163, 38.70066] }, + "id": "52843", + "mass": "329.7", + "name": "Lorton", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.700660", + "reclong": "-77.211630", + "year": "2010-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.83333, 38] }, + "id": "14708", + "mass": "25", + "name": "Los Martinez", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.000000", + "reclong": "-0.833330", + "year": "1894-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "20", + ":@computed_region_nnqa_25f4": "2711", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-95.15, 36.00833] }, + "id": "14711", + "mass": "17000", + "name": "Lost City", + "nametype": "Valid", + "recclass": "H5", + "reclat": "36.008330", + "reclong": "-95.150000", + "year": "1970-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "36", + ":@computed_region_nnqa_25f4": "1327", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-85.75, 38.25] }, + "id": "14716", + "mass": "1300", + "name": "Louisville", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.250000", + "reclong": "-85.750000", + "year": "1977-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [19.91667, 52] }, + "id": "14718", + "mass": "59000", + "name": "Łowicz", + "nametype": "Valid", + "recclass": "Mesosiderite-A3", + "reclat": "52.000000", + "reclong": "19.916670", + "year": "1935-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.15, 24.95] }, + "id": "14721", + "mass": "9241", + "name": "Lua", + "nametype": "Valid", + "recclass": "L5", + "reclat": "24.950000", + "reclong": "75.150000", + "year": "1926-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.48333, 47.85] }, + "id": "14724", + "mass": "3500", + "name": "LucΓ©", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.850000", + "reclong": "0.483330", + "year": "1768-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "31", + ":@computed_region_nnqa_25f4": "1567", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-84.76667, 32.03333] }, + "id": "14753", + "mass": "340", + "name": "Lumpkin", + "nametype": "Valid", + "recclass": "L6", + "reclat": "32.033330", + "reclong": "-84.766670", + "year": "1869-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [103.3, 24.8] }, + "id": "14754", + "mass": "2520", + "name": "Lunan", + "nametype": "Valid", + "recclass": "H6", + "reclat": "24.800000", + "reclong": "103.300000", + "year": "1980-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.03333, 56.21667] }, + "id": "14755", + "mass": "11000", + "name": "LundsgΓ₯rd", + "nametype": "Valid", + "recclass": "L6", + "reclat": "56.216670", + "reclong": "13.033330", + "year": "1889-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.7, 61.2] }, + "id": "14756", + "mass": "885", + "name": "Luotolax", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "61.200000", + "reclong": "27.700000", + "year": "1813-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5, 46.21667] }, + "id": "14757", + "mass": "14000", + "name": "Luponnas", + "nametype": "Valid", + "recclass": "H3-5", + "reclat": "46.216670", + "reclong": "5.000000", + "year": "1753-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.43333, -7.21667] }, + "id": "14759", + "name": "Lusaka", + "nametype": "Valid", + "recclass": "Unknown", + "reclat": "-7.216670", + "reclong": "29.433330", + "year": "1951-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [97, 19] }, + "id": "14764", + "mass": "540", + "name": "Mabwe-Khoywa", + "nametype": "Valid", + "recclass": "L5", + "reclat": "19.000000", + "reclong": "97.000000", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-36.66667, -5.2] }, + "id": "15370", + "mass": "1500", + "name": "Macau", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-5.200000", + "reclong": "-36.666670", + "year": "1836-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.24222, -15.21222] }, + "id": "15371", + "mass": "93200", + "name": "Machinga", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-15.212220", + "reclong": "35.242220", + "year": "1981-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.95, -28.83333] }, + "id": "15372", + "mass": "1995", + "name": "Macibini", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "-28.833330", + "reclong": "31.950000", + "year": "1936-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [86.36667, 25.91667] }, + "id": "15379", + "mass": "1000", + "name": "Madhipura", + "nametype": "Valid", + "recclass": "L", + "reclat": "25.916670", + "reclong": "86.366670", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.53333, -7.75] }, + "id": "15380", + "mass": "400", + "name": "Madiun", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-7.750000", + "reclong": "111.533330", + "year": "1935-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.71667, 40.41667] }, + "id": "15382", + "mass": "400", + "name": "Madrid", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.416670", + "reclong": "-3.716670", + "year": "1896-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-49.93333, -26.16667] }, + "id": "15383", + "mass": "600", + "name": "Mafra", + "nametype": "Valid", + "recclass": "L3-4", + "reclat": "-26.166670", + "reclong": "-49.933330", + "year": "1941-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.51667, 37.86667] }, + "id": "15386", + "mass": "5000", + "name": "Magnesia", + "nametype": "Valid", + "recclass": "Iron, IAB-sHL", + "reclat": "37.866670", + "reclong": "27.516670", + "year": "1899-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.65, -19.48333] }, + "id": "15387", + "mass": "666.6", + "name": "Magombedze", + "nametype": "Valid", + "recclass": "H3-5", + "reclat": "-19.483330", + "reclong": "31.650000", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [95.78333, 27.66667] }, + "id": "47361", + "mass": "70500", + "name": "Mahadevpur", + "nametype": "Valid", + "recclass": "H4/5", + "reclat": "27.666670", + "reclong": "95.783330", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.38333, 12.83333] }, + "id": "30751", + "mass": "4629", + "name": "Maigatari-Danduma", + "nametype": "Valid", + "recclass": "H5/6", + "reclat": "12.833330", + "reclong": "9.383330", + "year": "2004-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "11", + ":@computed_region_nnqa_25f4": "611", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-104, 32.21667] }, + "id": "15393", + "mass": "150", + "name": "Malaga", + "nametype": "Valid", + "recclass": "OC", + "reclat": "32.216670", + "reclong": "-104.000000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.75, 9.5] }, + "id": "15394", + "mass": "2000", + "name": "Malakal", + "nametype": "Valid", + "recclass": "L5", + "reclat": "9.500000", + "reclong": "31.750000", + "year": "1970-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.51667, -3.13333] }, + "id": "15395", + "mass": "470", + "name": "Malampaka", + "nametype": "Valid", + "recclass": "H", + "reclat": "-3.133330", + "reclong": "33.516670", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-63.23333, -28.93333] }, + "id": "15397", + "name": "Malotas", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-28.933330", + "reclong": "-63.233330", + "year": "1931-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.76667, -29.45] }, + "id": "15400", + "mass": "807", + "name": "Malvern", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "-29.450000", + "reclong": "26.766670", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [62.08333, 45.21667] }, + "id": "15401", + "mass": "1000", + "name": "Mamra Springs", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.216670", + "reclong": "62.083330", + "year": "1927-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [86.7, 23.05] }, + "id": "15402", + "mass": "1700", + "name": "Manbhoom", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "23.050000", + "reclong": "86.700000", + "year": "1863-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.1, 20.96667] }, + "id": "15403", + "mass": "50", + "name": "Manegaon", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "20.966670", + "reclong": "76.100000", + "year": "1843-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.6, -17.65] }, + "id": "15405", + "mass": "22300", + "name": "Mangwendi", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "-17.650000", + "reclong": "31.600000", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [44.63333, 45.81667] }, + "id": "15409", + "mass": "3555", + "name": "Manych", + "nametype": "Valid", + "recclass": "LL3.4", + "reclat": "45.816670", + "reclong": "44.633330", + "year": "1951-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [72.08333, 34.23333] }, + "id": "15414", + "mass": "4500", + "name": "Mardan", + "nametype": "Valid", + "recclass": "H5", + "reclat": "34.233330", + "reclong": "72.083330", + "year": "1948-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "15418", + "mass": "114", + "name": "Maria Linden", + "nametype": "Valid", + "recclass": "L4", + "year": "1925-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "19", + ":@computed_region_nnqa_25f4": "471", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.38333, 42.71667] }, + "id": "15419", + "mass": "340", + "name": "Mariaville", + "nametype": "Valid", + "recclass": "Iron", + "reclat": "42.716670", + "reclong": "-99.383330", + "year": "1898-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.46745, 54.76183] }, + "id": "48973", + "mass": "25.81", + "name": "Maribo", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "54.761830", + "reclong": "11.467450", + "year": "2009-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.25, 4.66667] }, + "id": "15421", + "mass": "3200", + "name": "Maridi", + "nametype": "Valid", + "recclass": "H6", + "reclat": "4.666670", + "reclong": "29.250000", + "year": "1941-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-49.93333, -22.25] }, + "id": "15422", + "mass": "2500", + "name": "Marilia", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-22.250000", + "reclong": "-49.933330", + "year": "1971-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "16", + ":@computed_region_nnqa_25f4": "287", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-91.6, 41.9] }, + "id": "15424", + "mass": "28400", + "name": "Marion (Iowa)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "41.900000", + "reclong": "-91.600000", + "year": "1847-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.5, 61.5] }, + "id": "15426", + "mass": "45000", + "name": "Marjalahti", + "nametype": "Valid", + "recclass": "Pallasite, PMG", + "reclat": "61.500000", + "reclong": "30.500000", + "year": "1902-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.15, 44.5] }, + "id": "15429", + "mass": "3000", + "name": "Marmande", + "nametype": "Valid", + "recclass": "L5", + "reclat": "44.500000", + "reclong": "0.150000", + "year": "1848-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [48.1, -14.2] }, + "id": "15430", + "mass": "6000", + "name": "Maromandia", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-14.200000", + "reclong": "48.100000", + "year": "2002-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "39", + ":@computed_region_nnqa_25f4": "2740", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-84.1, 35.8] }, + "id": "15436", + "mass": "1443", + "name": "Maryville", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.800000", + "reclong": "-84.100000", + "year": "1983-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.86667, 45.36667] }, + "id": "15438", + "mass": "1000", + "name": "Mascombes", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.366670", + "reclong": "1.866670", + "year": "1836-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0, 0] }, + "id": "53653", + "mass": "24.54", + "name": "Mason Gully", + "nametype": "Valid", + "recclass": "H5", + "reclat": "0.000000", + "reclong": "0.000000", + "year": "2010-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.61667, 48.13333] }, + "id": "15443", + "mass": "1600", + "name": "MΓ€ssing", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "48.133330", + "reclong": "12.616670", + "year": "1803-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.13333, 48.18333] }, + "id": "15446", + "mass": "19000", + "name": "Mauerkirchen", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.183330", + "reclong": "13.133330", + "year": "1768-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [57, -20] }, + "id": "15447", + "mass": "220", + "name": "Mauritius", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-20.000000", + "reclong": "57.000000", + "year": "1801-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.08333, 8.96667] }, + "id": "15451", + "mass": "4850", + "name": "Mayo Belwa", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "8.966670", + "reclong": "12.083330", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-101.68333, 24.68333] }, + "id": "15453", + "mass": "4000", + "name": "Mazapil", + "nametype": "Valid", + "recclass": "Iron, IAB-sLL", + "reclat": "24.683330", + "reclong": "-101.683330", + "year": "1885-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30, -1.21667] }, + "id": "15454", + "mass": "4975", + "name": "Maziba", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-1.216670", + "reclong": "30.000000", + "year": "1942-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [34.16667, 1.06667] }, + "id": "15455", + "mass": "150000", + "name": "Mbale", + "nametype": "Valid", + "recclass": "L5/6", + "reclat": "1.066670", + "reclong": "34.166670", + "year": "1992-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-67.5, -27.25] }, + "id": "15467", + "mass": "31", + "name": "Medanitos", + "nametype": "Valid", + "recclass": "Eucrite-cm", + "reclat": "-27.250000", + "reclong": "-67.500000", + "year": "1953-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.8, 29.01667] }, + "id": "15469", + "mass": "22", + "name": "Meerut", + "nametype": "Valid", + "recclass": "H5", + "reclat": "29.016670", + "reclong": "77.800000", + "year": "1861-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [106.88333, -6.23333] }, + "id": "15470", + "mass": "24750", + "name": "Meester-Cornelis", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-6.233330", + "reclong": "106.883330", + "year": "1915-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.15, 53.18333] }, + "id": "15485", + "mass": "10500", + "name": "Menow", + "nametype": "Valid", + "recclass": "H4", + "reclat": "53.183330", + "reclong": "13.150000", + "year": "1862-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.21817, 46.81867] }, + "id": "15486", + "mass": "28.9", + "name": "Menziswyl", + "nametype": "Valid", + "recclass": "L5", + "reclat": "46.818670", + "reclong": "7.218170", + "year": "1903-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.06667, 55.05] }, + "id": "15489", + "mass": "4000", + "name": "Mern", + "nametype": "Valid", + "recclass": "L6", + "reclat": "55.050000", + "reclong": "12.066670", + "year": "1878-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.66667, 0] }, + "id": "15491", + "mass": "6000", + "name": "Meru", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "0.000000", + "reclong": "37.666670", + "year": "1945-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [81.98333, 25.48333] }, + "id": "15492", + "mass": "71400", + "name": "Merua", + "nametype": "Valid", + "recclass": "H5", + "reclat": "25.483330", + "reclong": "81.983330", + "year": "1920-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.56667, 38.18333] }, + "id": "15495", + "mass": "2405", + "name": "Messina", + "nametype": "Valid", + "recclass": "L5", + "reclat": "38.183330", + "reclong": "15.566670", + "year": "1955-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.1, 50.58333] }, + "id": "16626", + "mass": "870", + "name": "Meuselbach", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.583330", + "reclong": "11.100000", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.25, 45.76667] }, + "id": "16627", + "mass": "1300", + "name": "Mezel", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.766670", + "reclong": "3.250000", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.73333, 46.5] }, + "id": "16628", + "mass": "22700", + "name": "MezΓΆ-Madaras", + "nametype": "Valid", + "recclass": "L3.7", + "reclat": "46.500000", + "reclong": "25.733330", + "year": "1852-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.61667, 25.9] }, + "id": "16629", + "mass": "350", + "name": "Mhow", + "nametype": "Valid", + "recclass": "L6", + "reclat": "25.900000", + "reclong": "83.616670", + "year": "1827-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.7, 34.8] }, + "id": "16631", + "mass": "1100", + "name": "Mianchi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "34.800000", + "reclong": "111.700000", + "year": "1980-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.16667, 54.56667] }, + "id": "16632", + "mass": "1600", + "name": "Middlesbrough", + "nametype": "Valid", + "recclass": "L6", + "reclat": "54.566670", + "reclong": "-1.166670", + "year": "1881-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "41", + ":@computed_region_nnqa_25f4": "2996", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-90.36556, 42.9075] }, + "id": "52090", + "mass": "3584", + "name": "Mifflin", + "nametype": "Valid", + "recclass": "L5", + "reclat": "42.907500", + "reclong": "-90.365560", + "year": "2010-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.96667, 48.06667] }, + "id": "16634", + "mass": "8000", + "name": "Mighei", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "48.066670", + "reclong": "30.966670", + "year": "1889-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [133.22, 35.56833] }, + "id": "16635", + "mass": "6380", + "name": "Mihonoseki", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.568330", + "reclong": "133.220000", + "year": "1992-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [17.53333, 46.23333] }, + "id": "16636", + "mass": "224.2", + "name": "Mike", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.233330", + "reclong": "17.533330", + "year": "1944-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.1, 46.18333] }, + "id": "16640", + "mass": "10000", + "name": "Milena", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.183330", + "reclong": "16.100000", + "year": "1842-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [120.36667, -26.45] }, + "id": "16643", + "mass": "330000", + "name": "Millbillillie", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "-26.450000", + "reclong": "120.366670", + "year": "1960-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "15", + ":@computed_region_nnqa_25f4": "11", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-92.05, 35.4] }, + "id": "16645", + "mass": "16700", + "name": "Miller (Arkansas)", + "nametype": "Valid", + "recclass": "H5", + "reclat": "35.400000", + "reclong": "-92.050000", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.93333, 35.07833] }, + "id": "16692", + "mass": "1040", + "name": "Minamino", + "nametype": "Valid", + "recclass": "L", + "reclat": "35.078330", + "reclong": "136.933330", + "year": "1632-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.7, 37.28333] }, + "id": "16696", + "mass": "42", + "name": "Mineo", + "nametype": "Valid", + "recclass": "Pallasite", + "reclat": "37.283330", + "reclong": "14.700000", + "year": "1826-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [120.66667, 32.33333] }, + "id": "16697", + "mass": "5500", + "name": "Min-Fan-Zhun", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "32.333330", + "reclong": "120.666670", + "year": "1952-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.6, 47.7] }, + "id": "16700", + "mass": "550", + "name": "Minnichhof", + "nametype": "Valid", + "recclass": "OC", + "reclat": "47.700000", + "reclong": "16.600000", + "year": "1905-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.25, 25.68333] }, + "id": "16701", + "mass": "8510", + "name": "Mirzapur", + "nametype": "Valid", + "recclass": "L5", + "reclat": "25.683330", + "reclong": "83.250000", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23, 56.66667] }, + "id": "16703", + "mass": "5800", + "name": "Misshof", + "nametype": "Valid", + "recclass": "H5", + "reclat": "56.666670", + "reclong": "23.000000", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.93333, 61.73333] }, + "id": "16707", + "mass": "100.7", + "name": "Mjelleim", + "nametype": "Valid", + "recclass": "H", + "reclat": "61.733330", + "reclong": "5.933330", + "year": "1898-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [24.03333, 46.8] }, + "id": "16709", + "mass": "300000", + "name": "Mocs", + "nametype": "Valid", + "recclass": "L5-6", + "reclat": "46.800000", + "reclong": "24.033330", + "year": "1882-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1290", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-101.1, 38.5] }, + "id": "16711", + "mass": "35000", + "name": "Modoc (1905)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.500000", + "reclong": "-101.100000", + "year": "1905-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [174.4, -39.63333] }, + "id": "16713", + "mass": "4500", + "name": "Mokoia", + "nametype": "Valid", + "recclass": "CV3", + "reclat": "-39.633330", + "reclong": "174.400000", + "year": "1908-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.16667, 38.11667] }, + "id": "16715", + "mass": "144000", + "name": "Molina", + "nametype": "Valid", + "recclass": "H5", + "reclat": "38.116670", + "reclong": "-1.166670", + "year": "1858-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.46667, -31.25] }, + "id": "16717", + "mass": "150", + "name": "Molteno", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "-31.250000", + "reclong": "26.466670", + "year": "1953-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "2957", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-102.85833, 31.60833] }, + "id": "16719", + "mass": "2587", + "name": "Monahans (1998)", + "nametype": "Valid", + "recclass": "H5", + "reclat": "31.608330", + "reclong": "-102.858330", + "year": "1998-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "636", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-80.5, 35.25] }, + "id": "16720", + "mass": "8600", + "name": "Monroe", + "nametype": "Valid", + "recclass": "H4", + "reclat": "35.250000", + "reclong": "-80.500000", + "year": "1849-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8.25, 38.01667] }, + "id": "16725", + "mass": "4885", + "name": "Monte das Fortes", + "nametype": "Valid", + "recclass": "L5", + "reclat": "38.016670", + "reclong": "-8.250000", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.35, 43.26667] }, + "id": "16726", + "mass": "3130", + "name": "Monte Milone", + "nametype": "Valid", + "recclass": "L5", + "reclat": "43.266670", + "reclong": "13.350000", + "year": "1846-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.9625, 43.39056] }, + "id": "16727", + "mass": "149000", + "name": "MontferrΓ©", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.390560", + "reclong": "1.962500", + "year": "1923-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.58333, 47.63333] }, + "id": "16729", + "mass": "500", + "name": "Montlivault", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.633330", + "reclong": "1.583330", + "year": "1838-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.35, -15.96667] }, + "id": "16733", + "name": "Monze", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-15.966670", + "reclong": "27.350000", + "year": "1950-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "2431", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-79.38333, 35.41667] }, + "id": "16736", + "mass": "1880", + "name": "Moore County", + "nametype": "Valid", + "recclass": "Eucrite-cm", + "reclat": "35.416670", + "reclong": "-79.383330", + "year": "1913-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8.33333, 52.45] }, + "id": "16737", + "mass": "3520", + "name": "Mooresfort", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.450000", + "reclong": "-8.333330", + "year": "1810-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [145.6, -40.975] }, + "id": "16738", + "mass": "8887.5", + "name": "Moorleah", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-40.975000", + "reclong": "145.600000", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.83333, 28.78333] }, + "id": "16740", + "mass": "70", + "name": "Moradabad", + "nametype": "Valid", + "recclass": "L6", + "reclat": "28.783330", + "reclong": "78.833330", + "year": "1808-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [18.53333, 49.6] }, + "id": "16742", + "mass": "633", + "name": "MorΓ‘vka", + "nametype": "Valid", + "recclass": "H5", + "reclat": "49.600000", + "reclong": "18.533330", + "year": "2000-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.13333, 44.6] }, + "id": "16747", + "mass": "1300", + "name": "Mornans", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.600000", + "reclong": "5.133330", + "year": "1875-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.7, 59.43333] }, + "id": "36592", + "mass": "3763", + "name": "Moss", + "nametype": "Valid", + "recclass": "CO3.6", + "reclat": "59.433330", + "reclong": "10.700000", + "year": "2006-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.33333, 26.83333] }, + "id": "16759", + "mass": "1500", + "name": "Moti-ka-nagla", + "nametype": "Valid", + "recclass": "H6", + "reclat": "26.833330", + "reclong": "77.333330", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.5, 45.2] }, + "id": "16762", + "mass": "9150", + "name": "Motta di Conti", + "nametype": "Valid", + "recclass": "H4", + "reclat": "45.200000", + "reclong": "8.500000", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [141.7, -29.8] }, + "id": "16766", + "mass": "11300", + "name": "Mount Browne", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-29.800000", + "reclong": "141.700000", + "year": "1902-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4.8, 18.7] }, + "id": "16804", + "mass": "110000", + "name": "Mount Tazerzait", + "nametype": "Valid", + "recclass": "L5", + "reclat": "18.700000", + "reclong": "4.800000", + "year": "1991-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.86667, 44.08333] }, + "id": "16805", + "mass": "17000", + "name": "Mount Vaisi", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "44.083330", + "reclong": "6.866670", + "year": "1637-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.5, -11.5] }, + "id": "16820", + "mass": "1100", + "name": "Mtola", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "-11.500000", + "reclong": "33.500000", + "year": "1944-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.01667, 12.63333] }, + "id": "16841", + "mass": "4400", + "name": "Muddoor", + "nametype": "Valid", + "recclass": "L5", + "reclat": "12.633330", + "reclong": "77.016670", + "year": "1865-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [80.83333, 9.33333] }, + "id": "16851", + "mass": "25.5", + "name": "Mulletiwu", + "nametype": "Valid", + "recclass": "L", + "reclat": "9.333330", + "reclong": "80.833330", + "year": "1795-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [90.21667, 24.5] }, + "id": "16874", + "mass": "4703", + "name": "Muraid", + "nametype": "Valid", + "recclass": "L6", + "reclat": "24.500000", + "reclong": "90.216670", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [145.2, -36.61667] }, + "id": "16875", + "mass": "100000", + "name": "Murchison", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "-36.616670", + "reclong": "145.200000", + "year": "1969-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "36", + ":@computed_region_nnqa_25f4": "237", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-88.1, 36.6] }, + "id": "16882", + "mass": "12600", + "name": "Murray", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "36.600000", + "reclong": "-88.100000", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [85.53333, 26.13333] }, + "id": "16885", + "mass": "1245", + "name": "Muzaffarpur", + "nametype": "Valid", + "recclass": "Iron, IAB-sHL", + "reclat": "26.133330", + "reclong": "85.533330", + "year": "1964-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [72.63333, 23.05] }, + "id": "16887", + "name": "Myhee Caunta", + "nametype": "Valid", + "recclass": "OC", + "reclat": "23.050000", + "reclong": "72.633330", + "year": "1842-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1, 12] }, + "id": "16889", + "mass": "8165", + "name": "Nadiabondi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "12.000000", + "reclong": "1.000000", + "year": "1956-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [140.06167, 38.12167] }, + "id": "16890", + "mass": "1810", + "name": "Nagai", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.121670", + "reclong": "140.061670", + "year": "1922-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.21667, 26.98333] }, + "id": "16892", + "mass": "20", + "name": "Nagaria", + "nametype": "Valid", + "recclass": "Eucrite-cm", + "reclat": "26.983330", + "reclong": "78.216670", + "year": "1875-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [19.5, 49.16667] }, + "id": "16893", + "mass": "6100", + "name": "Nagy-BorovΓ©", + "nametype": "Valid", + "recclass": "L5", + "reclat": "49.166670", + "reclong": "19.500000", + "year": "1895-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.35, 31.31667] }, + "id": "16898", + "mass": "10000", + "name": "Nakhla", + "nametype": "Valid", + "recclass": "Martian (nakhlite)", + "reclat": "31.316670", + "reclong": "30.350000", + "year": "1911-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [100.08333, 13.73333] }, + "id": "16899", + "mass": "23200", + "name": "Nakhon Pathom", + "nametype": "Valid", + "recclass": "L6", + "reclat": "13.733330", + "reclong": "100.083330", + "year": "1923-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [79.2, 12.28333] }, + "id": "16902", + "mass": "4500", + "name": "Nammianthal", + "nametype": "Valid", + "recclass": "H5", + "reclat": "12.283330", + "reclong": "79.200000", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [103.5, 35.66667] }, + "id": "16903", + "mass": "52900", + "name": "Nan Yang Pao", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.666670", + "reclong": "103.500000", + "year": "1917-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "45", + ":@computed_region_nnqa_25f4": "419", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-77.16667, 38.41667] }, + "id": "16904", + "mass": "7500", + "name": "Nanjemoy", + "nametype": "Valid", + "recclass": "H6", + "reclat": "38.416670", + "reclong": "-77.166670", + "year": "1825-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [121.8, 32.11667] }, + "id": "16907", + "mass": "529", + "name": "Nantong", + "nametype": "Valid", + "recclass": "H6", + "reclat": "32.116670", + "reclong": "121.800000", + "year": "1984-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77, 19.25] }, + "id": "16908", + "mass": "17000", + "name": "Naoki", + "nametype": "Valid", + "recclass": "H6", + "reclat": "19.250000", + "reclong": "77.000000", + "year": "1928-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [51.5, 33.75] }, + "id": "16909", + "mass": "2700", + "name": "Naragh", + "nametype": "Valid", + "recclass": "H6", + "reclat": "33.750000", + "reclong": "51.500000", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [150.68889, -34.05] }, + "id": "16912", + "mass": "367.5", + "name": "Narellan", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-34.050000", + "reclong": "150.688890", + "year": "1928-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.51667, 42.51667] }, + "id": "16914", + "name": "Narni", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "42.516670", + "reclong": "12.516670", + "year": "0921-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [165.9, -21.73333] }, + "id": "16922", + "mass": "347", + "name": "Nassirah", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-21.733330", + "reclong": "165.900000", + "year": "1936-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "16923", + "mass": "1.4", + "name": "Natal", + "nametype": "Valid", + "recclass": "Stone-uncl", + "year": "1973-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.66667, 21.25] }, + "id": "16927", + "mass": "105", + "name": "Nawapali", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "21.250000", + "reclong": "83.666670", + "year": "1890-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.46528, 36.44917] }, + "id": "16934", + "mass": "420", + "name": "Neagari", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.449170", + "reclong": "136.465280", + "year": "1995-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [83.48333, 18.68333] }, + "id": "16935", + "mass": "4500", + "name": "Nedagolla", + "nametype": "Valid", + "recclass": "Iron, ungrouped", + "reclat": "18.683330", + "reclong": "83.483330", + "year": "1870-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.33333, 9.5] }, + "id": "16941", + "mass": "2450", + "name": "Nejo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "9.500000", + "reclong": "35.333330", + "year": "1970-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.5, 56.5] }, + "id": "16945", + "mass": "10250", + "name": "Nerft", + "nametype": "Valid", + "recclass": "L6", + "reclat": "56.500000", + "reclong": "21.500000", + "year": "1864-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.80833, 47.525] }, + "id": "16950", + "mass": "6189", + "name": "Neuschwanstein", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "47.525000", + "reclong": "10.808330", + "year": "2002-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "38", + ":@computed_region_nnqa_25f4": "2615", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-81.76667, 40] }, + "id": "16953", + "mass": "230000", + "name": "New Concord", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.000000", + "reclong": "-81.766670", + "year": "1860-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.68333, 15.36667] }, + "id": "16954", + "mass": "12000", + "name": "New Halfa", + "nametype": "Valid", + "recclass": "L4", + "reclat": "15.366670", + "reclong": "35.683330", + "year": "1994-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "22", + ":@computed_region_nnqa_25f4": "1667", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-90.10976, 29.94718] }, + "id": "16960", + "mass": "19256", + "name": "New Orleans", + "nametype": "Valid", + "recclass": "H5", + "reclat": "29.947180", + "reclong": "-90.109760", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.41667, -7.45] }, + "id": "16966", + "mass": "1393", + "name": "Ngawi", + "nametype": "Valid", + "recclass": "LL3.6", + "reclat": "-7.450000", + "reclong": "111.416670", + "year": "1883-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-4.38333, 13.85] }, + "id": "16968", + "mass": "37500", + "name": "N'Goureyma", + "nametype": "Valid", + "recclass": "Iron, ungrouped", + "reclat": "13.850000", + "reclong": "-4.383330", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.43333, 49.03333] }, + "id": "16970", + "name": "Nicorps", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "49.033330", + "reclong": "-1.433330", + "year": "1750-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "16974", + "mass": "3.3", + "name": "Niger (L6)", + "nametype": "Valid", + "recclass": "L6", + "year": "1967-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "16975", + "mass": "3.3", + "name": "Niger (LL6)", + "nametype": "Valid", + "recclass": "LL6", + "year": "1967-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.63333, 52.45] }, + "id": "16976", + "mass": "3996", + "name": "Nikolaevka", + "nametype": "Valid", + "recclass": "H4", + "reclat": "52.450000", + "reclong": "78.633330", + "year": "1935-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.33333, 56.11667] }, + "id": "16977", + "mass": "6000", + "name": "Nikolskoe", + "nametype": "Valid", + "recclass": "L4", + "reclat": "56.116670", + "reclong": "37.333330", + "year": "1954-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [121.48333, 29.86667] }, + "id": "16980", + "mass": "14250", + "name": "Ningbo", + "nametype": "Valid", + "recclass": "Iron, IVA", + "reclat": "29.866670", + "reclong": "121.483330", + "year": "1975-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [105.90667, 32.925] }, + "id": "16981", + "mass": "4610", + "name": "Ningqiang", + "nametype": "Valid", + "recclass": "C3-ung", + "reclat": "32.925000", + "reclong": "105.906670", + "year": "1983-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [131.56667, 34.2] }, + "id": "16982", + "mass": "467", + "name": "Nio", + "nametype": "Valid", + "recclass": "H3-4", + "reclat": "34.200000", + "reclong": "131.566670", + "year": "1897-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [30.7, -28.56667] }, + "id": "16983", + "mass": "17200", + "name": "N'Kandhla", + "nametype": "Valid", + "recclass": "Iron, IID", + "reclat": "-28.566670", + "reclong": "30.700000", + "year": "1912-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "49", + ":@computed_region_nnqa_25f4": "1683", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-69.48333, 44.08333] }, + "id": "16984", + "mass": "2300", + "name": "Nobleborough", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "44.083330", + "reclong": "-69.483330", + "year": "1823-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "35", + ":@computed_region_nnqa_25f4": "2238", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.055, 40.08528] }, + "id": "16985", + "mass": "483.7", + "name": "Noblesville", + "nametype": "Valid", + "recclass": "H4-6", + "reclat": "40.085280", + "reclong": "-86.055000", + "year": "1991-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [130.75, 33.725] }, + "id": "16988", + "mass": "472", + "name": "Nogata", + "nametype": "Valid", + "recclass": "L6", + "reclat": "33.725000", + "reclong": "130.750000", + "year": "0861-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-59.83333, -32.36667] }, + "id": "16989", + "mass": "4000", + "name": "Nogoya", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "-32.366670", + "reclong": "-59.833330", + "year": "1879-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "15", + ":@computed_region_nnqa_25f4": "10", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-92.26667, 36.21667] }, + "id": "16994", + "mass": "1050", + "name": "Norfork", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "36.216670", + "reclong": "-92.266670", + "year": "1918-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1252", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.86667, 39.68333] }, + "id": "17922", + "mass": "1100000", + "name": "Norton County", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "39.683330", + "reclong": "-99.866670", + "year": "1948-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.52722, 45.29167] }, + "id": "17930", + "mass": "177", + "name": "Noventa Vicentina", + "nametype": "Valid", + "recclass": "H4", + "reclat": "45.291670", + "reclong": "11.527220", + "year": "1971-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [46, 54.81667] }, + "id": "17933", + "mass": "1900", + "name": "Novo-Urei", + "nametype": "Valid", + "recclass": "Ureilite", + "reclat": "54.816670", + "reclong": "46.000000", + "year": "1886-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [31.33333, 58.55] }, + "id": "17934", + "name": "Novy-Ergi", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "58.550000", + "reclong": "31.333330", + "year": "1662-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22, 56] }, + "id": "17935", + "mass": "1001", + "name": "Novy-Projekt", + "nametype": "Valid", + "recclass": "OC", + "reclat": "56.000000", + "reclong": "22.000000", + "year": "1908-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [102.46667, 42.91667] }, + "id": "17936", + "mass": "250", + "name": "Noyan-Bogdo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "42.916670", + "reclong": "102.466670", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-102.13333, 24.3] }, + "id": "17938", + "mass": "50000", + "name": "Nuevo Mercurio", + "nametype": "Valid", + "recclass": "H5", + "reclat": "24.300000", + "reclong": "-102.133330", + "year": "1978-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.75, 41.63333] }, + "id": "17959", + "mass": "5000", + "name": "Nulles", + "nametype": "Valid", + "recclass": "H6", + "reclat": "41.633330", + "reclong": "0.750000", + "year": "1851-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [141.86667, 43.33333] }, + "id": "17960", + "mass": "363", + "name": "Numakai", + "nametype": "Valid", + "recclass": "H4", + "reclat": "43.333330", + "reclong": "141.866670", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [94.91667, 21.20833] }, + "id": "17969", + "mass": "737.6", + "name": "Nyaung", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "21.208330", + "reclong": "94.916670", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.025, 47.55] }, + "id": "17970", + "mass": "1100", + "name": "NyirΓ‘brany", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "47.550000", + "reclong": "22.025000", + "year": "1914-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [55.26667, 57.78333] }, + "id": "17979", + "mass": "500000", + "name": "Ochansk", + "nametype": "Valid", + "recclass": "H4", + "reclat": "57.783330", + "reclong": "55.266670", + "year": "1887-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.05, 52.28333] }, + "id": "17988", + "mass": "1400", + "name": "Oesede", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.283330", + "reclong": "8.050000", + "year": "1927-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23, 58.5] }, + "id": "17989", + "mass": "6000", + "name": "Oesel", + "nametype": "Valid", + "recclass": "L6", + "reclat": "58.500000", + "reclong": "23.000000", + "year": "1855-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.03333, 47.88333] }, + "id": "17990", + "mass": "3750", + "name": "OfehΓ©rtΓ³", + "nametype": "Valid", + "recclass": "L6", + "reclat": "47.883330", + "reclong": "22.033330", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [130.2, 33.28333] }, + "id": "17994", + "mass": "14360", + "name": "Ogi", + "nametype": "Valid", + "recclass": "H6", + "reclat": "33.283330", + "reclong": "130.200000", + "year": "1741-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23.58333, 46.06667] }, + "id": "17995", + "mass": "16250", + "name": "Ohaba", + "nametype": "Valid", + "recclass": "H5", + "reclat": "46.066670", + "reclong": "23.583330", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.5, 6.75] }, + "id": "17996", + "mass": "7700", + "name": "Ohuma", + "nametype": "Valid", + "recclass": "L5", + "reclat": "6.750000", + "reclong": "8.500000", + "year": "1963-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-5.4, 38.18333] }, + "id": "17997", + "mass": "5850", + "name": "Ojuelos Altos", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.183330", + "reclong": "-5.400000", + "year": "1926-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [139.21667, 36.18333] }, + "id": "17998", + "mass": "194", + "name": "Okabe", + "nametype": "Valid", + "recclass": "H5", + "reclat": "36.183330", + "reclong": "139.216670", + "year": "1958-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [135.2, 35.08333] }, + "id": "18000", + "mass": "4742", + "name": "Okano", + "nametype": "Valid", + "recclass": "Iron, IIAB", + "reclat": "35.083330", + "reclong": "135.200000", + "year": "1904-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.5, 50.83333] }, + "id": "18002", + "mass": "12000", + "name": "Okniny", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "50.833330", + "reclong": "25.500000", + "year": "1834-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8.16667, 52.95] }, + "id": "18009", + "mass": "16570", + "name": "Oldenburg (1930)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.950000", + "reclong": "8.166670", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.03333, 39] }, + "id": "18012", + "name": "Oliva-Gandia", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "39.000000", + "reclong": "-0.033330", + "year": "1520-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.06667, 38.71667] }, + "id": "18013", + "mass": "150000", + "name": "Olivenza", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "38.716670", + "reclong": "-7.066670", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-2.1, 39.56667] }, + "id": "18015", + "mass": "40000", + "name": "Olmedilla de AlarcΓ³n", + "nametype": "Valid", + "recclass": "H5", + "reclat": "39.566670", + "reclong": "-2.100000", + "year": "1929-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [161.80833, 64.02] }, + "id": "18019", + "mass": "250000", + "name": "Omolon", + "nametype": "Valid", + "recclass": "Pallasite, PMG", + "reclat": "64.020000", + "reclong": "161.808330", + "year": "1981-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.38333, 43.88333] }, + "id": "18026", + "mass": "14000", + "name": "Orgueil", + "nametype": "Valid", + "recclass": "CI1", + "reclat": "43.883330", + "reclong": "1.383330", + "year": "1864-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "30", + ":@computed_region_nnqa_25f4": "1078", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-81.36222, 28.5475] }, + "id": "34489", + "mass": "180", + "name": "Orlando", + "nametype": "Valid", + "recclass": "Eucrite", + "reclat": "28.547500", + "reclong": "-81.362220", + "year": "2004-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.15, 47.11667] }, + "id": "18030", + "mass": "6000", + "name": "Ornans", + "nametype": "Valid", + "recclass": "CO3.4", + "reclat": "47.116670", + "reclong": "6.150000", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [8, 48.5] }, + "id": "18033", + "mass": "4500", + "name": "Ortenau", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "48.500000", + "reclong": "8.000000", + "year": "1671-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.93333, 42.13333] }, + "id": "18034", + "mass": "3400", + "name": "Orvinio", + "nametype": "Valid", + "recclass": "H6", + "reclat": "42.133330", + "reclong": "12.933330", + "year": "1872-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.4, 58.88333] }, + "id": "18042", + "mass": "246", + "name": "OterΓΈy", + "nametype": "Valid", + "recclass": "L6", + "reclat": "58.883330", + "reclong": "9.400000", + "year": "1928-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [140.35, 38.4] }, + "id": "18045", + "mass": "6510", + "name": "Otomi", + "nametype": "Valid", + "recclass": "H", + "reclat": "38.400000", + "reclong": "140.350000", + "year": "1867-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1947", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-95.21667, 38.6] }, + "id": "18046", + "mass": "840", + "name": "Ottawa", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "38.600000", + "reclong": "-95.216670", + "year": "1896-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.08, 12.9] }, + "id": "56729", + "mass": "4440", + "name": "Ouadangou", + "nametype": "Valid", + "recclass": "L5", + "reclat": "12.900000", + "reclong": "0.080000", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.57717, 30.18] }, + "id": "18050", + "mass": "1215.5", + "name": "Oued el Hadjar", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "30.180000", + "reclong": "-6.577170", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-13.1, 24.3] }, + "id": "31282", + "mass": "17000", + "name": "Oum Dreyga", + "nametype": "Valid", + "recclass": "H3-5", + "reclat": "24.300000", + "reclong": "-13.100000", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8.28, 37.60833] }, + "id": "18052", + "mass": "20000", + "name": "Ourique", + "nametype": "Valid", + "recclass": "H4", + "reclat": "37.608330", + "reclong": "-8.280000", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16, -18] }, + "id": "18055", + "mass": "121.5", + "name": "Ovambo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-18.000000", + "reclong": "16.000000", + "year": "1900-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-5.86667, 43.4] }, + "id": "18058", + "mass": "205", + "name": "Oviedo", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.400000", + "reclong": "-5.866670", + "year": "1856-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28.83333, 51.33333] }, + "id": "18062", + "name": "Owrucz", + "nametype": "Valid", + "recclass": "OC", + "reclat": "51.333330", + "reclong": "28.833330", + "year": "1775-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.3, 21.05] }, + "id": "18068", + "mass": "3400", + "name": "Pacula", + "nametype": "Valid", + "recclass": "L6", + "reclat": "21.050000", + "reclong": "-99.300000", + "year": "1881-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25, 55.66667] }, + "id": "18069", + "mass": "3858", + "name": "Padvarninkai", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "55.666670", + "reclong": "25.000000", + "year": "1929-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [120.45583, 17.74333] }, + "id": "18072", + "mass": "515", + "name": "Paitan", + "nametype": "Valid", + "recclass": "H6", + "reclat": "17.743330", + "reclong": "120.455830", + "year": "1910-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "32", + ":@computed_region_nnqa_25f4": "503", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-89.71667, 32.31667] }, + "id": "18073", + "name": "Palahatchie", + "nametype": "Valid", + "recclass": "OC", + "reclat": "32.316670", + "reclong": "-89.716670", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-65.1, -23.11667] }, + "id": "18074", + "mass": "1430", + "name": "Palca de Aparzo", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-23.116670", + "reclong": "-65.100000", + "year": "1988-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [118.61667, 43.48333] }, + "id": "18077", + "mass": "18000", + "name": "Palinshih", + "nametype": "Valid", + "recclass": "Iron", + "reclat": "43.483330", + "reclong": "118.616670", + "year": "1914-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "2122", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-91.5, 39.8] }, + "id": "18079", + "mass": "135", + "name": "Palmyra", + "nametype": "Valid", + "recclass": "L3", + "reclat": "39.800000", + "reclong": "-91.500000", + "year": "1926-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "4", + ":@computed_region_nnqa_25f4": "1657", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-157.78333, 21.3] }, + "id": "18082", + "mass": "682", + "name": "Palolo Valley", + "nametype": "Valid", + "recclass": "H5", + "reclat": "21.300000", + "reclong": "-157.783330", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Found", + "id": "32591", + "mass": "69.5", + "name": "Dominion Range 03239", + "nametype": "Valid", + "recclass": "L6", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [120.7, 15.08333] }, + "id": "18093", + "mass": "10500", + "name": "Pampanga", + "nametype": "Valid", + "recclass": "L5", + "reclat": "15.083330", + "reclong": "120.700000", + "year": "1859-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [124.28333, 8.06667] }, + "id": "18098", + "mass": "2130", + "name": "Pantar", + "nametype": "Valid", + "recclass": "H5", + "reclat": "8.066670", + "reclong": "124.283330", + "year": "1938-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "15", + ":@computed_region_nnqa_25f4": "1023", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-90.5, 36.06667] }, + "id": "18101", + "mass": "408000", + "name": "Paragould", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "36.066670", + "reclong": "-90.500000", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-40.7, -6.23333] }, + "id": "18102", + "mass": "2000", + "name": "Parambu", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "-6.233330", + "reclong": "-40.700000", + "year": "1967-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-51.66667, -19.13333] }, + "id": "18103", + "mass": "100000", + "name": "Paranaiba", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-19.133330", + "reclong": "-51.666670", + "year": "1956-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "34", + ":@computed_region_nnqa_25f4": "1863", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-87.67917, 41.48472] }, + "id": "18106", + "mass": "18000", + "name": "Park Forest", + "nametype": "Valid", + "recclass": "L5", + "reclat": "41.484720", + "reclong": "-87.679170", + "year": "2003-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.35, 9.23333] }, + "id": "18108", + "mass": "77600", + "name": "Parnallee", + "nametype": "Valid", + "recclass": "LL3.6", + "reclat": "9.233330", + "reclong": "78.350000", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [85.4, 26.2] }, + "id": "18109", + "mass": "800", + "name": "Parsa", + "nametype": "Valid", + "recclass": "EH3", + "reclat": "26.200000", + "reclong": "85.400000", + "year": "1942-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "11", + ":@computed_region_nnqa_25f4": "1994", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.4, 36.21667] }, + "id": "18110", + "mass": "5100", + "name": "Pasamonte", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "36.216670", + "reclong": "-103.400000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.05, 20.93694] }, + "id": "18112", + "mass": "4375", + "name": "Patora", + "nametype": "Valid", + "recclass": "H6", + "reclat": "20.936940", + "reclong": "82.050000", + "year": "1969-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-48.56667, -19.53333] }, + "id": "18116", + "mass": "2121", + "name": "Patrimonio", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-19.533330", + "reclong": "-48.566670", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.96667, 38.13333] }, + "id": "18118", + "mass": "12", + "name": "Patti", + "nametype": "Valid", + "recclass": "Iron", + "reclat": "38.133330", + "reclong": "14.966670", + "year": "1922-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [91.18333, 23.15] }, + "id": "18171", + "mass": "37350", + "name": "Patwar", + "nametype": "Valid", + "recclass": "Mesosiderite-A1", + "reclat": "23.150000", + "reclong": "91.183330", + "year": "1935-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.51667, 43.46667] }, + "id": "18173", + "mass": "2968", + "name": "Pavel", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.466670", + "reclong": "25.516670", + "year": "1966-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [77.03333, 52.3] }, + "id": "18175", + "mass": "142.5", + "name": "Pavlodar (stone)", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.300000", + "reclong": "77.033330", + "year": "1938-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.98333, 48.53333] }, + "id": "18176", + "mass": "40000", + "name": "Pavlograd", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.533330", + "reclong": "35.983330", + "year": "1826-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [43, 52.03333] }, + "id": "18177", + "mass": "2000", + "name": "Pavlovka", + "nametype": "Valid", + "recclass": "Howardite", + "reclat": "52.033330", + "reclong": "43.000000", + "year": "1882-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.54217, 11.33367] }, + "id": "18179", + "name": "PΓͺ", + "nametype": "Valid", + "recclass": "L6", + "reclat": "11.333670", + "reclong": "-3.542170", + "year": "1989-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-117.93333, 56.13333] }, + "id": "18180", + "mass": "45760", + "name": "Peace River", + "nametype": "Valid", + "recclass": "L6", + "reclat": "56.133330", + "reclong": "-117.933330", + "year": "1963-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.25, 51.66667] }, + "id": "18181", + "mass": "117.8", + "name": "Peckelsheim", + "nametype": "Valid", + "recclass": "Diogenite-pm", + "reclat": "51.666670", + "reclong": "9.250000", + "year": "1953-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "47", + ":@computed_region_nnqa_25f4": "2185", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-73.91667, 41.28333] }, + "id": "18782", + "mass": "12570", + "name": "Peekskill", + "nametype": "Valid", + "recclass": "H6", + "reclat": "41.283330", + "reclong": "-73.916670", + "year": "1992-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "3062", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.11667, 30.125] }, + "id": "18786", + "mass": "70000", + "name": "PeΓ±a Blanca Spring", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "30.125000", + "reclong": "-103.116670", + "year": "1946-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.5, -10.66667] }, + "id": "18792", + "mass": "165", + "name": "Peramiho", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "-10.666670", + "reclong": "35.500000", + "year": "1899-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [91, 23.325] }, + "id": "18793", + "mass": "23474", + "name": "Perpeti", + "nametype": "Valid", + "recclass": "L6", + "reclat": "23.325000", + "reclong": "91.000000", + "year": "1935-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.43333, 56.4] }, + "id": "18797", + "mass": "2", + "name": "Perth", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "56.400000", + "reclong": "-3.433330", + "year": "1830-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [39.43333, 56.63333] }, + "id": "18798", + "mass": "66000", + "name": "Pervomaisky", + "nametype": "Valid", + "recclass": "L6", + "reclat": "56.633330", + "reclong": "39.433330", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [66.08333, 55.5] }, + "id": "18799", + "mass": "3393", + "name": "Pesyanoe", + "nametype": "Valid", + "recclass": "Aubrite", + "reclat": "55.500000", + "reclong": "66.083330", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.42, 14.052] }, + "id": "18800", + "mass": "189", + "name": "PΓ©tΓ¨lkolΓ©", + "nametype": "Valid", + "recclass": "H5", + "reclat": "14.052000", + "reclong": "0.420000", + "year": "1995-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "39", + ":@computed_region_nnqa_25f4": "2017", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.63333, 35.3] }, + "id": "18801", + "mass": "1800", + "name": "Petersburg", + "nametype": "Valid", + "recclass": "Eucrite-pmict", + "reclat": "35.300000", + "reclong": "-86.633330", + "year": "1855-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.33333, 53.53333] }, + "id": "18804", + "name": "Pettiswood", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "53.533330", + "reclong": "-7.333330", + "year": "1779-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "17", + ":@computed_region_nnqa_25f4": "1255", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.25, 40] }, + "id": "18808", + "mass": "57900", + "name": "Phillips County (stone)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "40.000000", + "reclong": "-99.250000", + "year": "1901-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [108.58333, 11.25] }, + "id": "18809", + "mass": "500", + "name": "Phu Hong", + "nametype": "Valid", + "recclass": "H4", + "reclat": "11.250000", + "reclong": "108.583330", + "year": "1887-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [105.48333, 12] }, + "id": "18811", + "mass": "7800", + "name": "Phum Sambo", + "nametype": "Valid", + "recclass": "H4", + "reclat": "12.000000", + "reclong": "105.483330", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [108.1, 15.71667] }, + "id": "18812", + "mass": "11000", + "name": "Phuoc-Binh", + "nametype": "Valid", + "recclass": "L5", + "reclat": "15.716670", + "reclong": "108.100000", + "year": "1941-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.50222, 44.24417] }, + "id": "18813", + "mass": "13.1", + "name": "Piancaldoli", + "nametype": "Valid", + "recclass": "LL3.4", + "reclat": "44.244170", + "reclong": "11.502220", + "year": "1968-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6.23333, 41.36667] }, + "id": "18816", + "name": "Picote", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "41.366670", + "reclong": "-6.233330", + "year": "1843-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [25.73333, 58.66667] }, + "id": "18822", + "mass": "23250", + "name": "Pillistfer", + "nametype": "Valid", + "recclass": "EL6", + "reclat": "58.666670", + "reclong": "25.733330", + "year": "1863-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [73.94167, 26.03472] }, + "id": "18831", + "mass": "42000", + "name": "Piplia Kalan", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "26.034720", + "reclong": "73.941670", + "year": "1996-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [18.71667, -32.86667] }, + "id": "18832", + "mass": "37", + "name": "Piquetberg", + "nametype": "Valid", + "recclass": "H", + "reclat": "-32.866670", + "reclong": "18.716670", + "year": "1881-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [88.45, 25.8] }, + "id": "18834", + "mass": "842", + "name": "Pirgunje", + "nametype": "Valid", + "recclass": "L6", + "reclat": "25.800000", + "reclong": "88.450000", + "year": "1882-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76, 29.58333] }, + "id": "18835", + "mass": "1161", + "name": "Pirthalla", + "nametype": "Valid", + "recclass": "H6", + "reclat": "29.583330", + "reclong": "76.000000", + "year": "1884-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "31", + ":@computed_region_nnqa_25f4": "207", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-83.51667, 31.95] }, + "id": "18837", + "mass": "3760", + "name": "Pitts", + "nametype": "Valid", + "recclass": "Iron, IAB-ung", + "reclat": "31.950000", + "reclong": "-83.516670", + "year": "1921-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "2018", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-96.11667, 30.7] }, + "id": "18846", + "mass": "2085", + "name": "Plantersville", + "nametype": "Valid", + "recclass": "H6", + "reclat": "30.700000", + "reclong": "-96.116670", + "year": "1930-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.70972, 45.275] }, + "id": "51706", + "mass": "6913", + "name": "Pleşcoi", + "nametype": "Valid", + "recclass": "L5-6", + "reclat": "45.275000", + "reclong": "26.709720", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.11667, 50.53333] }, + "id": "18849", + "mass": "39", + "name": "Ploschkovitz", + "nametype": "Valid", + "recclass": "L5", + "reclat": "50.533330", + "reclong": "14.116670", + "year": "1723-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [104.91667, 11.58333] }, + "id": "18851", + "mass": "96", + "name": "Pnompehn", + "nametype": "Valid", + "recclass": "L6", + "reclat": "11.583330", + "reclong": "104.916670", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Found", + "id": "32592", + "mass": "290.89999999999998", + "name": "Dominion Range 03240", + "nametype": "Valid", + "recclass": "LL5", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [12.13333, 50.93333] }, + "id": "18853", + "mass": "3000", + "name": "Pohlitz", + "nametype": "Valid", + "recclass": "L5", + "reclat": "50.933330", + "reclong": "12.133330", + "year": "1819-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.66667, 26.71667] }, + "id": "18858", + "mass": "350", + "name": "Pokhra", + "nametype": "Valid", + "recclass": "H5", + "reclat": "26.716670", + "reclong": "82.666670", + "year": "1866-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.015, 66.34833] }, + "id": "18860", + "mass": "253.6", + "name": "Pollen", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "66.348330", + "reclong": "14.015000", + "year": "1942-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-4.31944, 53.03639] }, + "id": "18865", + "mass": "157", + "name": "Pontlyfni", + "nametype": "Valid", + "recclass": "Winonaite", + "reclat": "53.036390", + "reclong": "-4.319440", + "year": "1931-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "11", + ":@computed_region_nnqa_25f4": "1987", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.295, 34.175] }, + "id": "18874", + "mass": "71400", + "name": "Portales Valley", + "nametype": "Valid", + "recclass": "H6", + "reclat": "34.175000", + "reclong": "-103.295000", + "year": "1998-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-8, 38.5] }, + "id": "18876", + "mass": "4500", + "name": "Portugal", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "38.500000", + "reclong": "-8.000000", + "year": "1796-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [118.5, 31.41667] }, + "id": "18879", + "mass": "665", + "name": "Po-wang Chen", + "nametype": "Valid", + "recclass": "LL", + "reclat": "31.416670", + "reclong": "118.500000", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13.94083, 48.3025] }, + "id": "18883", + "mass": "2125", + "name": "Prambachkirchen", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.302500", + "reclong": "13.940830", + "year": "1932-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.03333, 49.66667] }, + "id": "18887", + "mass": "5555", + "name": "Pribram", + "nametype": "Valid", + "recclass": "H5", + "reclat": "49.666670", + "reclong": "14.033330", + "year": "1959-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "38", + ":@computed_region_nnqa_25f4": "2566", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-83.85, 39.11667] }, + "id": "18888", + "mass": "900", + "name": "Pricetown", + "nametype": "Valid", + "recclass": "L6", + "reclat": "39.116670", + "reclong": "-83.850000", + "year": "1893-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.51667, 39.35] }, + "id": "45984", + "mass": "500", + "name": "Puerto LΓ‘pice", + "nametype": "Valid", + "recclass": "Eucrite-br", + "reclat": "39.350000", + "reclong": "-3.516670", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [75.18333, 23.36667] }, + "id": "18899", + "mass": "560", + "name": "Pulsora", + "nametype": "Valid", + "recclass": "H5", + "reclat": "23.366670", + "reclong": "75.183330", + "year": "1863-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.26667, 52.76667] }, + "id": "18901", + "mass": "250000", + "name": "Pultusk", + "nametype": "Valid", + "recclass": "H5", + "reclat": "52.766670", + "reclong": "21.266670", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.95, 13.33333] }, + "id": "18902", + "mass": "100", + "name": "Punganaru", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "13.333330", + "reclong": "78.950000", + "year": "1811-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-53.05, -29.03333] }, + "id": "18905", + "mass": "300000", + "name": "Putinga", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-29.033330", + "reclong": "-53.050000", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [121.5, 32.08333] }, + "id": "18907", + "mass": "1275", + "name": "Qidong", + "nametype": "Valid", + "recclass": "L/LL5", + "reclat": "32.083330", + "reclong": "121.500000", + "year": "1982-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [106.46667, 26.53333] }, + "id": "18908", + "mass": "2600", + "name": "Qingzhen", + "nametype": "Valid", + "recclass": "EH3", + "reclat": "26.533330", + "reclong": "106.466670", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [28.7, -30.11667] }, + "id": "22357", + "mass": "7000", + "name": "Queen's Mercy", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-30.116670", + "reclong": "28.700000", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [95.18333, 17.76667] }, + "id": "22358", + "mass": "6045", + "name": "Quenggouk", + "nametype": "Valid", + "recclass": "H4", + "reclat": "17.766670", + "reclong": "95.183330", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.66667, 39] }, + "id": "22360", + "mass": "10750", + "name": "Quesa", + "nametype": "Valid", + "recclass": "Iron, IAB-ung", + "reclat": "39.000000", + "reclong": "-0.666670", + "year": "1898-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [126.13333, 44.61667] }, + "id": "22361", + "mass": "17450", + "name": "Quija", + "nametype": "Valid", + "recclass": "H", + "reclat": "44.616670", + "reclong": "126.133330", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.25, 46.6] }, + "id": "22363", + "mass": "65", + "name": "Quincay", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.600000", + "reclong": "0.250000", + "year": "1851-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-65.45, -26.66667] }, + "id": "22368", + "mass": "5000", + "name": "Raco", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-26.666670", + "reclong": "-65.450000", + "year": "1957-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.465, 27.72528] }, + "id": "22371", + "mass": "10200", + "name": "Raghunathpura", + "nametype": "Valid", + "recclass": "Iron, IIAB", + "reclat": "27.725280", + "reclong": "76.465000", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [70.2, 28.225] }, + "id": "31302", + "mass": "67225", + "name": "Rahimyar Khan", + "nametype": "Valid", + "recclass": "L5", + "reclat": "28.225000", + "reclong": "70.200000", + "year": "1983-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.03333, 52.98333] }, + "id": "22376", + "mass": "9000", + "name": "Rakovka", + "nametype": "Valid", + "recclass": "L6", + "reclat": "52.983330", + "reclong": "37.033330", + "year": "1878-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.9, 26.45] }, + "id": "22384", + "mass": "3766", + "name": "Ramnagar", + "nametype": "Valid", + "recclass": "L6", + "reclat": "26.450000", + "reclong": "82.900000", + "year": "1940-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [87.76667, 24.16667] }, + "id": "22385", + "mass": "100", + "name": "Rampurhat", + "nametype": "Valid", + "recclass": "LL", + "reclat": "24.166670", + "reclong": "87.766670", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [6.93333, 51.88333] }, + "id": "22386", + "mass": "4682", + "name": "Ramsdorf", + "nametype": "Valid", + "recclass": "L6", + "reclat": "51.883330", + "reclong": "6.933330", + "year": "1958-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [87.08333, 23.98333] }, + "id": "22387", + "mass": "290.39999999999998", + "name": "Ranchapur", + "nametype": "Valid", + "recclass": "H4", + "reclat": "23.983330", + "reclong": "87.083330", + "year": "1917-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-100.81667, 19.86667] }, + "id": "22390", + "mass": "300", + "name": "Rancho de la Presa", + "nametype": "Valid", + "recclass": "H5", + "reclat": "19.866670", + "reclong": "-100.816670", + "year": "1899-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [72.01667, 25.38333] }, + "id": "22392", + "mass": "3224.5", + "name": "Rangala", + "nametype": "Valid", + "recclass": "L6", + "reclat": "25.383330", + "reclong": "72.016670", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [115.7, 38.2] }, + "id": "22394", + "mass": "4910", + "name": "Raoyang", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.200000", + "reclong": "115.700000", + "year": "1919-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [50.15, 26.66667] }, + "id": "22395", + "mass": "6.1", + "name": "Ras Tanura", + "nametype": "Valid", + "recclass": "H6", + "reclat": "26.666670", + "reclong": "50.150000", + "year": "1961-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.53333, 43.5] }, + "id": "22396", + "mass": "24700", + "name": "Rasgrad", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "43.500000", + "reclong": "26.533330", + "year": "1740-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [17.98333, 52.2] }, + "id": "22398", + "mass": "910", + "name": "Ratyn", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "52.200000", + "reclong": "17.983330", + "year": "1880-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "8", + ":@computed_region_nnqa_25f4": "1391", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-119.75812, 38.13742] }, + "id": "53502", + "mass": "18.41", + "name": "Red Canyon Lake", + "nametype": "Valid", + "recclass": "H5", + "reclat": "38.137420", + "reclong": "-119.758120", + "year": "2007-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-5.33333, 42.475] }, + "id": "22584", + "mass": "17300", + "name": "Reliegos", + "nametype": "Valid", + "recclass": "L5", + "reclat": "42.475000", + "reclong": "-5.333330", + "year": "1947-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.36667, -6.73333] }, + "id": "22585", + "mass": "10000", + "name": "Rembang", + "nametype": "Valid", + "recclass": "Iron, IVA", + "reclat": "-6.733330", + "reclong": "111.366670", + "year": "1919-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.28333, 44.76667] }, + "id": "22586", + "mass": "1000", + "name": "Renazzo", + "nametype": "Valid", + "recclass": "CR2", + "reclat": "44.766670", + "reclong": "11.283330", + "year": "1824-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-65.28333, -32.75] }, + "id": "22587", + "mass": "300", + "name": "Renca", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-32.750000", + "reclong": "-65.283330", + "year": "1925-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [116.13333, 38.66667] }, + "id": "22589", + "mass": "355", + "name": "Renqiu", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.666670", + "reclong": "116.133330", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [45.66667, 48.6] }, + "id": "22590", + "mass": "7000", + "name": "Repeev Khutor", + "nametype": "Valid", + "recclass": "Iron, IIF", + "reclat": "48.600000", + "reclong": "45.666670", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-118.95, 51.33333] }, + "id": "22592", + "mass": "1", + "name": "Revelstoke", + "nametype": "Valid", + "recclass": "CI1", + "reclat": "51.333330", + "reclong": "-118.950000", + "year": "1965-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [76.66667, 28.2] }, + "id": "22593", + "mass": "3332", + "name": "Rewari", + "nametype": "Valid", + "recclass": "L6", + "reclat": "28.200000", + "reclong": "76.666670", + "year": "1929-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "37", + ":@computed_region_nnqa_25f4": "2388", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-83.03333, 35.03333] }, + "id": "22597", + "mass": "668", + "name": "Rich Mountain", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.033330", + "reclong": "-83.033330", + "year": "1903-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-66.15, -44.11667] }, + "id": "24140", + "mass": "20000", + "name": "Uzcudun", + "nametype": "Valid", + "recclass": "L", + "reclat": "-44.116670", + "reclong": "-66.150000", + "year": "1948-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "3", + ":@computed_region_nnqa_25f4": "569", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-102.31667, 46.88333] }, + "id": "22599", + "mass": "90000", + "name": "Richardton", + "nametype": "Valid", + "recclass": "H5", + "reclat": "46.883330", + "reclong": "-102.316670", + "year": "1918-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "23", + ":@computed_region_nnqa_25f4": "2885", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.03333, 31.25] }, + "id": "22602", + "mass": "1900", + "name": "Richland Springs", + "nametype": "Valid", + "recclass": "OC", + "reclat": "31.250000", + "reclong": "-99.033330", + "year": "1980-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "40", + ":@computed_region_nnqa_25f4": "2764", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-77.5, 37.46667] }, + "id": "22603", + "mass": "1800", + "name": "Richmond", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "37.466670", + "reclong": "-77.500000", + "year": "1828-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-49.8, -26.1] }, + "id": "22611", + "mass": "1310", + "name": "Rio Negro", + "nametype": "Valid", + "recclass": "L4", + "reclat": "-26.100000", + "reclong": "-49.800000", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.51667, 45.48333] }, + "id": "22614", + "mass": "103.3", + "name": "Rivolta de Bassi", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "45.483330", + "reclong": "9.516670", + "year": "1491-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "35", + ":@computed_region_nnqa_25f4": "150", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.28333, 41.08333] }, + "id": "22637", + "mass": "340", + "name": "Rochester", + "nametype": "Valid", + "recclass": "H6", + "reclat": "41.083330", + "reclong": "-86.283330", + "year": "1876-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [150.51667, -23.38333] }, + "id": "22640", + "mass": "1641", + "name": "Rockhampton", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "-23.383330", + "reclong": "150.516670", + "year": "1895-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.55, 42.3] }, + "id": "22641", + "mass": "400", + "name": "Roda", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "42.300000", + "reclong": "0.550000", + "year": "1871-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.8, 50.35] }, + "id": "22642", + "mass": "2900", + "name": "Rodach", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "50.350000", + "reclong": "10.800000", + "year": "1775-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "50", + ":@computed_region_nnqa_25f4": "361", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-83.95, 44.51667] }, + "id": "22766", + "mass": "10600", + "name": "Rose City", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.516670", + "reclong": "-83.950000", + "year": "1921-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-2.51667, 52.76667] }, + "id": "22773", + "mass": "3500", + "name": "Rowton", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "52.766670", + "reclong": "-2.516670", + "year": "1876-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.83333, -1.45] }, + "id": "22780", + "mass": "465.5", + "name": "Ruhobobo", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-1.450000", + "reclong": "29.833330", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [36.53333, 0.26667] }, + "id": "22782", + "mass": "67", + "name": "Rumuruti", + "nametype": "Valid", + "recclass": "R3.8-6", + "reclat": "0.266670", + "reclong": "36.533330", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [38.76667, -10.26667] }, + "id": "22783", + "mass": "6000", + "name": "Rupota", + "nametype": "Valid", + "recclass": "L4-6", + "reclat": "-10.266670", + "reclong": "38.766670", + "year": "1949-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [34.5, 51.13333] }, + "id": "22791", + "mass": "13000", + "name": "Ryechki", + "nametype": "Valid", + "recclass": "L5", + "reclat": "51.133330", + "reclong": "34.500000", + "year": "1914-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.08333, 27.43333] }, + "id": "22792", + "mass": "1250", + "name": "Sabetmahet", + "nametype": "Valid", + "recclass": "H5", + "reclat": "27.433330", + "reclong": "82.083330", + "year": "1855-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [91.66667, 23.08333] }, + "id": "22793", + "mass": "478", + "name": "Sabrum", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "23.083330", + "reclong": "91.666670", + "year": "1999-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.88333, 51.53333] }, + "id": "22796", + "name": "Sagan", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "51.533330", + "reclong": "14.883330", + "year": "1636-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.38333, 43.73333] }, + "id": "23101", + "mass": "14000", + "name": "Saint-Sauveur", + "nametype": "Valid", + "recclass": "EH5", + "reclat": "43.733330", + "reclong": "1.383330", + "year": "1914-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.23333, 45.3] }, + "id": "23102", + "mass": "271000", + "name": "Saint-SΓ©verin", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "45.300000", + "reclong": "0.233330", + "year": "1966-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.3, 35.66667] }, + "id": "23103", + "mass": "4180", + "name": "Sakauchi", + "nametype": "Valid", + "recclass": "Iron", + "reclat": "35.666670", + "reclong": "136.300000", + "year": "1913-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "12", + ":@computed_region_nnqa_25f4": "2409", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-122.96944, 44.97917] }, + "id": "23107", + "mass": "61.4", + "name": "Salem", + "nametype": "Valid", + "recclass": "L6", + "reclat": "44.979170", + "reclong": "-122.969440", + "year": "1981-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4.63333, 46.05] }, + "id": "23111", + "mass": "9000", + "name": "Salles", + "nametype": "Valid", + "recclass": "L5", + "reclat": "46.050000", + "reclong": "4.633330", + "year": "1798-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.05, 52.75] }, + "id": "23114", + "mass": "43", + "name": "Salzwedel", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "52.750000", + "reclong": "11.050000", + "year": "1985-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [74.86667, 25.66667] }, + "id": "23115", + "mass": "2462", + "name": "Samelia", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "25.666670", + "reclong": "74.866670", + "year": "1921-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "8", + ":@computed_region_nnqa_25f4": "1174", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-117.6625, 33.48472] }, + "id": "23128", + "mass": "56", + "name": "San Juan Capistrano", + "nametype": "Valid", + "recclass": "H6", + "reclat": "33.484720", + "reclong": "-117.662500", + "year": "1973-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [13, 43.66667] }, + "id": "31315", + "mass": "237", + "name": "San Michele", + "nametype": "Valid", + "recclass": "L6", + "reclat": "43.666670", + "reclong": "13.000000", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-71.4, -31.01667] }, + "id": "23130", + "mass": "282", + "name": "San Pedro de Quiles", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-31.016670", + "reclong": "-71.400000", + "year": "1956-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-100.65, 19.76667] }, + "id": "34063", + "mass": "460", + "name": "San Pedro Jacuaro", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "19.766670", + "reclong": "-100.650000", + "year": "1968-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-51.86667, -29.2] }, + "id": "23161", + "mass": "400", + "name": "Santa Barbara", + "nametype": "Valid", + "recclass": "L4", + "reclat": "-29.200000", + "reclong": "-51.866670", + "year": "1873-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-99.33333, 24.16667] }, + "id": "23164", + "mass": "60", + "name": "Santa Cruz", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "24.166670", + "reclong": "-99.333330", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-61.7, -33.9] }, + "id": "23165", + "mass": "5500", + "name": "Santa Isabel", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-33.900000", + "reclong": "-61.700000", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-68.489444, -31.535556] }, + "id": "50909", + "mass": "4000", + "name": "Santa Lucia (2008)", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-31.535556", + "reclong": "-68.489444", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-49.38056, -20.81] }, + "id": "23171", + "mass": "927", + "name": "SΓ£o Jose do Rio Preto", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-20.810000", + "reclong": "-49.380560", + "year": "1962-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [46.55, 52.55] }, + "id": "23176", + "mass": "200000", + "name": "Saratov", + "nametype": "Valid", + "recclass": "L4", + "reclat": "52.550000", + "reclong": "46.550000", + "year": "1918-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [137.78333, 34.71667] }, + "id": "23187", + "mass": "695", + "name": "Sasagase", + "nametype": "Valid", + "recclass": "H", + "reclat": "34.716670", + "reclong": "137.783330", + "year": "1688-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.85, 43.15] }, + "id": "23188", + "mass": "4000", + "name": "Sauguis", + "nametype": "Valid", + "recclass": "L6", + "reclat": "43.150000", + "reclong": "-0.850000", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [29.86667, 47.21667] }, + "id": "23190", + "mass": "2500", + "name": "Savtschenskoje", + "nametype": "Valid", + "recclass": "LL4", + "reclat": "47.216670", + "reclong": "29.866670", + "year": "1894-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [139.4, 35.86667] }, + "id": "23192", + "mass": "430", + "name": "Sayama", + "nametype": "Valid", + "recclass": "CM2", + "reclat": "35.866670", + "reclong": "139.400000", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [17.56667, 49.23333] }, + "id": "23455", + "mass": "412", + "name": "Sazovice", + "nametype": "Valid", + "recclass": "L5", + "reclat": "49.233330", + "reclong": "17.566670", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.05, 53.35] }, + "id": "23457", + "mass": "7000", + "name": "Schellin", + "nametype": "Valid", + "recclass": "L", + "reclat": "53.350000", + "reclong": "15.050000", + "year": "1715-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "47", + ":@computed_region_nnqa_25f4": "2142", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-73.95028, 42.86083] }, + "id": "23458", + "mass": "283.3", + "name": "Schenectady", + "nametype": "Valid", + "recclass": "H5", + "reclat": "42.860830", + "reclong": "-73.950280", + "year": "1968-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.46667, 48.11667] }, + "id": "23460", + "mass": "8000", + "name": "SchΓΆnenberg", + "nametype": "Valid", + "recclass": "L6", + "reclat": "48.116670", + "reclong": "10.466670", + "year": "1846-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "49", + ":@computed_region_nnqa_25f4": "1727", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-69.2, 44.36667] }, + "id": "23472", + "mass": "5400", + "name": "Searsmont", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.366670", + "reclong": "-69.200000", + "year": "1871-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.13333, 38.3] }, + "id": "23473", + "mass": "240", + "name": "SedikΓΆy", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.300000", + "reclong": "27.133330", + "year": "1917-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.78333, 26.75] }, + "id": "23476", + "mass": "6930", + "name": "Segowlie", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "26.750000", + "reclong": "84.783330", + "year": "1853-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [107.33333, -7.23333] }, + "id": "23481", + "mass": "1590", + "name": "Selakopi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "-7.233330", + "reclong": "107.333330", + "year": "1939-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [4.98333, 22.83333] }, + "id": "23483", + "mass": "150", + "name": "Seldebourak", + "nametype": "Valid", + "recclass": "H5", + "reclat": "22.833330", + "reclong": "4.983330", + "year": "1947-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [79, 22.25] }, + "id": "23487", + "mass": "691", + "name": "Semarkona", + "nametype": "Valid", + "recclass": "LL3.00", + "reclat": "22.250000", + "reclong": "79.000000", + "year": "1940-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-0.05, 41.71667] }, + "id": "23495", + "mass": "4000", + "name": "Sena", + "nametype": "Valid", + "recclass": "H4", + "reclat": "41.716670", + "reclong": "-0.050000", + "year": "1773-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [140.51167, 39.43833] }, + "id": "23496", + "mass": "866", + "name": "Senboku", + "nametype": "Valid", + "recclass": "H6", + "reclat": "39.438330", + "reclong": "140.511670", + "year": "1993-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [79.50083, 21.68389] }, + "id": "23500", + "mass": "20000", + "name": "Seoni", + "nametype": "Valid", + "recclass": "H6", + "reclat": "21.683890", + "reclong": "79.500830", + "year": "1966-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23.56667, 41.05] }, + "id": "23501", + "mass": "8500", + "name": "Seres", + "nametype": "Valid", + "recclass": "H4", + "reclat": "41.050000", + "reclong": "23.566670", + "year": "1818-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-36.76667, -8.38333] }, + "id": "23502", + "mass": "1800", + "name": "Serra de MagΓ©", + "nametype": "Valid", + "recclass": "Eucrite-cm", + "reclat": "-8.383330", + "reclong": "-36.766670", + "year": "1923-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-44.21667, -19.46667] }, + "id": "23504", + "mass": "350", + "name": "Sete Lagoas", + "nametype": "Valid", + "recclass": "H4", + "reclat": "-19.466670", + "reclong": "-44.216670", + "year": "1908-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-6, 37.41667] }, + "id": "23508", + "mass": "180", + "name": "Sevilla", + "nametype": "Valid", + "recclass": "LL4", + "reclat": "37.416670", + "reclong": "-6.000000", + "year": "1862-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [36.6, 50.61667] }, + "id": "23509", + "mass": "101000", + "name": "Sevrukovo", + "nametype": "Valid", + "recclass": "L5", + "reclat": "50.616670", + "reclong": "36.600000", + "year": "1874-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.71667, 34.75] }, + "id": "23512", + "mass": "7000", + "name": "Sfax", + "nametype": "Valid", + "recclass": "L6", + "reclat": "34.750000", + "reclong": "10.716670", + "year": "1989-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [87.3, 23.1] }, + "id": "23521", + "mass": "4000", + "name": "Shalka", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "23.100000", + "reclong": "87.300000", + "year": "1850-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "40", + ":@computed_region_nnqa_25f4": "921", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-76.7, 37.83333] }, + "id": "23525", + "mass": "1265", + "name": "Sharps", + "nametype": "Valid", + "recclass": "H3.4", + "reclat": "37.833330", + "reclong": "-76.700000", + "year": "1921-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-80.16667, 44.05] }, + "id": "23529", + "mass": "18600", + "name": "Shelburne", + "nametype": "Valid", + "recclass": "L5", + "reclat": "44.050000", + "reclong": "-80.166670", + "year": "1904-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.83333, 24.55] }, + "id": "23530", + "mass": "5000", + "name": "Shergotty", + "nametype": "Valid", + "recclass": "Martian (shergottite)", + "reclat": "24.550000", + "reclong": "84.833330", + "year": "1865-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [120.06667, 33.65] }, + "id": "23531", + "mass": "605", + "name": "Sheyang", + "nametype": "Valid", + "recclass": "L6", + "reclat": "33.650000", + "reclong": "120.066670", + "year": "1976-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [87.5775, 25.85] }, + "id": "23534", + "mass": "3679.7", + "name": "Shikarpur", + "nametype": "Valid", + "recclass": "L6", + "reclat": "25.850000", + "reclong": "87.577500", + "year": "1921-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [125.66667, 43.5] }, + "id": "23582", + "mass": "3900", + "name": "Shuangyang", + "nametype": "Valid", + "recclass": "H5", + "reclat": "43.500000", + "reclong": "125.666670", + "year": "1971-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [74.83333, 33.71667] }, + "id": "23583", + "mass": "5000", + "name": "Shupiyan", + "nametype": "Valid", + "recclass": "H6", + "reclat": "33.716670", + "reclong": "74.833330", + "year": "1912-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [90.16667, 24.33333] }, + "id": "23584", + "mass": "3200", + "name": "Shytal", + "nametype": "Valid", + "recclass": "L6", + "reclat": "24.333330", + "reclong": "90.166670", + "year": "1863-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [11.6, 43.11667] }, + "id": "23586", + "mass": "3700", + "name": "Siena", + "nametype": "Valid", + "recclass": "LL5", + "reclat": "43.116670", + "reclong": "11.600000", + "year": "1794-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [134.65333, 46.16] }, + "id": "23593", + "mass": "23000000", + "name": "Sikhote-Alin", + "nametype": "Valid", + "recclass": "Iron, IIAB", + "reclat": "46.160000", + "reclong": "134.653330", + "year": "1947-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-101.38333, 20.93333] }, + "id": "23594", + "mass": "1710", + "name": "Silao", + "nametype": "Valid", + "recclass": "H5", + "reclat": "20.933330", + "reclong": "-101.383330", + "year": "1995-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.26667, 44.11667] }, + "id": "55584", + "mass": "0.15", + "name": "Silistra", + "nametype": "Valid", + "recclass": "Achondrite-ung", + "reclat": "44.116670", + "reclong": "27.266670", + "year": "1917-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [7.53333, 49.98333] }, + "id": "23603", + "mass": "1222", + "name": "Simmern", + "nametype": "Valid", + "recclass": "H5", + "reclat": "49.983330", + "reclong": "7.533330", + "year": "1920-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [32.48333, 30.9] }, + "id": "23606", + "mass": "1455", + "name": "Sinai", + "nametype": "Valid", + "recclass": "L6", + "reclat": "30.900000", + "reclong": "32.483330", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [69.55, 26.21667] }, + "id": "23611", + "mass": "8400", + "name": "Sindhri", + "nametype": "Valid", + "recclass": "H5", + "reclat": "26.216670", + "reclong": "69.550000", + "year": "1901-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.2, 39.3] }, + "id": "23613", + "mass": "2000", + "name": "Sinnai", + "nametype": "Valid", + "recclass": "H6", + "reclat": "39.300000", + "reclong": "9.200000", + "year": "1956-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "19", + ":@computed_region_nnqa_25f4": "2351", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-103.66667, 42.58333] }, + "id": "23614", + "mass": "4100", + "name": "Sioux County", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "42.583330", + "reclong": "-103.666670", + "year": "1933-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [82.58333, 20.91667] }, + "id": "23616", + "mass": "1600", + "name": "Sitathali", + "nametype": "Valid", + "recclass": "H5", + "reclat": "20.916670", + "reclong": "82.583330", + "year": "1875-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [36.13583, 39.82467] }, + "id": "23617", + "mass": "40000", + "name": "Sivas", + "nametype": "Valid", + "recclass": "H6", + "reclat": "39.824670", + "reclong": "36.135830", + "year": "1989-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [119.86667, 32.43333] }, + "id": "23619", + "mass": "630", + "name": "Sixiangkou", + "nametype": "Valid", + "recclass": "L5", + "reclat": "32.433330", + "reclong": "119.866670", + "year": "1989-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.86667, 59.73333] }, + "id": "23621", + "mass": "850", + "name": "Ski", + "nametype": "Valid", + "recclass": "L6", + "reclat": "59.733330", + "reclong": "10.866670", + "year": "1848-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.6, 45.68333] }, + "id": "23626", + "mass": "1708", + "name": "Slavetic", + "nametype": "Valid", + "recclass": "H5", + "reclat": "45.683330", + "reclong": "15.600000", + "year": "1868-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35, 55] }, + "id": "23645", + "mass": "2750", + "name": "Slobodka", + "nametype": "Valid", + "recclass": "L4", + "reclat": "55.000000", + "reclong": "35.000000", + "year": "1818-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.06667, 27.13333] }, + "id": "23660", + "mass": "72.900000000000006", + "name": "Soheria", + "nametype": "Valid", + "recclass": "OC", + "reclat": "27.133330", + "reclong": "84.066670", + "year": "1960-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [21.86667, 43.66667] }, + "id": "23661", + "mass": "80000", + "name": "Soko-Banja", + "nametype": "Valid", + "recclass": "LL4", + "reclat": "43.666670", + "reclong": "21.866670", + "year": "1877-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.73333, 47.36667] }, + "id": "23663", + "mass": "54", + "name": "Sologne", + "nametype": "Valid", + "recclass": "H5", + "reclat": "47.366670", + "reclong": "1.733330", + "year": "1860-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [22.005, 54.00883] }, + "id": "53829", + "mass": "1066", + "name": "SoΕ‚tmany", + "nametype": "Valid", + "recclass": "L6", + "reclat": "54.008830", + "reclong": "22.005000", + "year": "2011-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [135.33333, 35.16667] }, + "id": "23667", + "mass": "17100", + "name": "Sone", + "nametype": "Valid", + "recclass": "H5", + "reclat": "35.166670", + "reclong": "135.333330", + "year": "1866-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [125, 45.25] }, + "id": "23668", + "mass": "36900", + "name": "Songyuan", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.250000", + "reclong": "125.000000", + "year": "1993-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23.5, 44.41667] }, + "id": "23670", + "mass": "958", + "name": "Sopot", + "nametype": "Valid", + "recclass": "OC", + "reclat": "44.416670", + "reclong": "23.500000", + "year": "1927-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [33.63333, 1.7] }, + "id": "23671", + "mass": "2050", + "name": "Soroti", + "nametype": "Valid", + "recclass": "Iron, ungrouped", + "reclat": "1.700000", + "reclong": "33.633330", + "year": "1945-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [0.05, 44.75] }, + "id": "23081", + "mass": "360", + "name": "St. Caprais-de-Quinsac", + "nametype": "Valid", + "recclass": "L6", + "reclat": "44.750000", + "reclong": "0.050000", + "year": "1883-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.5, 46.95] }, + "id": "23082", + "mass": "5500", + "name": "St. Christophe-la-Chartreuse", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.950000", + "reclong": "-1.500000", + "year": "1841-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.75, 51.05] }, + "id": "23083", + "mass": "700", + "name": "St. Denis Westrem", + "nametype": "Valid", + "recclass": "L6", + "reclat": "51.050000", + "reclong": "3.750000", + "year": "1855-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-1.15, 48.01667] }, + "id": "23087", + "mass": "4000", + "name": "St. Germain-du-Pinel", + "nametype": "Valid", + "recclass": "H6", + "reclat": "48.016670", + "reclong": "-1.150000", + "year": "1890-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "18", + ":@computed_region_nnqa_25f4": "2223", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-90.23333, 38.7] }, + "id": "23089", + "mass": "1000", + "name": "St. Louis", + "nametype": "Valid", + "recclass": "H4", + "reclat": "38.700000", + "reclong": "-90.233330", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.41667, -32.01667] }, + "id": "23090", + "mass": "13780", + "name": "St. Mark's", + "nametype": "Valid", + "recclass": "EH5", + "reclat": "-32.016670", + "reclong": "27.416670", + "year": "1903-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "45", + ":@computed_region_nnqa_25f4": "424", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-76.38333, 38.16667] }, + "id": "23091", + "mass": "24.3", + "name": "St. Mary's County", + "nametype": "Valid", + "recclass": "LL3.3", + "reclat": "38.166670", + "reclong": "-76.383330", + "year": "1919-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3.93333, 48.45] }, + "id": "23092", + "mass": "8300", + "name": "St. Mesmin", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "48.450000", + "reclong": "3.933330", + "year": "1866-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.2, 61.65] }, + "id": "23093", + "mass": "17000", + "name": "St. Michel", + "nametype": "Valid", + "recclass": "L6", + "reclat": "61.650000", + "reclong": "27.200000", + "year": "1910-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [2.95, 43.43333] }, + "id": "23097", + "mass": "134.30000000000001", + "name": "St.-Chinian", + "nametype": "Valid", + "recclass": "L6", + "reclat": "43.433330", + "reclong": "2.950000", + "year": "1959-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.95, 59.93333] }, + "id": "23712", + "mass": "34000", + "name": "StΓ€lldalen", + "nametype": "Valid", + "recclass": "H5", + "reclat": "59.933330", + "reclong": "14.950000", + "year": "1876-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [15.56667, 49.28333] }, + "id": "23713", + "mass": "52000", + "name": "Stannern", + "nametype": "Valid", + "recclass": "Eucrite-mmict", + "reclat": "49.283330", + "reclong": "15.566670", + "year": "1808-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [41.98333, 45.05] }, + "id": "23717", + "mass": "1500", + "name": "Stavropol", + "nametype": "Valid", + "recclass": "L6", + "reclat": "45.050000", + "reclong": "41.983330", + "year": "1857-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [3, 50.76667] }, + "id": "23099", + "mass": "4960", + "name": "Ste. Marguerite", + "nametype": "Valid", + "recclass": "H4", + "reclat": "50.766670", + "reclong": "3.000000", + "year": "1962-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [55.98333, 53.66667] }, + "id": "23724", + "mass": "325000", + "name": "Sterlitamak", + "nametype": "Valid", + "recclass": "Iron, IIIAB", + "reclat": "53.666670", + "reclong": "55.983330", + "year": "1990-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [9.05, 52.53333] }, + "id": "23726", + "name": "Stolzenau", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "52.533330", + "reclong": "9.050000", + "year": "1647-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "24", + ":@computed_region_nnqa_25f4": "1040", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-73.13333, 41.2] }, + "id": "23728", + "mass": "50", + "name": "Stratford", + "nametype": "Valid", + "recclass": "L6", + "reclat": "41.200000", + "reclong": "-73.133330", + "year": "1974-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.25, 56.58333] }, + "id": "23729", + "mass": "13400", + "name": "Strathmore", + "nametype": "Valid", + "recclass": "L6", + "reclat": "56.583330", + "reclong": "-3.250000", + "year": "1917-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-3.95, 50.38333] }, + "id": "23732", + "mass": "10400", + "name": "Stretchleigh", + "nametype": "Valid", + "recclass": "Stone-uncl", + "reclat": "50.383330", + "reclong": "-3.950000", + "year": "1623-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-72.97806, 45.96861] }, + "id": "23733", + "mass": "25400", + "name": "St-Robert", + "nametype": "Valid", + "recclass": "H5", + "reclat": "45.968610", + "reclong": "-72.978060", + "year": "1994-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "15", + ":@computed_region_nnqa_25f4": "955", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-90.66667, 36.48333] }, + "id": "23736", + "mass": "3500", + "name": "Success", + "nametype": "Valid", + "recclass": "L6", + "reclat": "36.483330", + "reclong": "-90.666670", + "year": "1924-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [16.26333, 50.53806] }, + "id": "23737", + "mass": "815.3", + "name": "Suchy Dul", + "nametype": "Valid", + "recclass": "L6", + "reclat": "50.538060", + "reclong": "16.263330", + "year": "1969-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [113.46667, 31.61667] }, + "id": "23738", + "mass": "260000", + "name": "Suizhou", + "nametype": "Valid", + "recclass": "L6", + "reclat": "31.616670", + "reclong": "113.466670", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [78.03333, 12.66667] }, + "id": "48951", + "mass": "110000", + "name": "Sulagiri", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "12.666670", + "reclong": "78.033330", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.28333, 25.93333] }, + "id": "23741", + "mass": "1710.5", + "name": "Sultanpur", + "nametype": "Valid", + "recclass": "L/LL6", + "reclat": "25.933330", + "reclong": "84.283330", + "year": "1916-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [133.16667, 44.86667] }, + "id": "23745", + "mass": "637", + "name": "Sungach", + "nametype": "Valid", + "recclass": "H5", + "reclat": "44.866670", + "reclong": "133.166670", + "year": "1935-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [84.21667, 26.71667] }, + "id": "23760", + "mass": "7235", + "name": "Supuhee", + "nametype": "Valid", + "recclass": "H6", + "reclat": "26.716670", + "reclong": "84.216670", + "year": "1865-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "8", + ":@computed_region_nnqa_25f4": "1187", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-120.90806, 38.80389] }, + "id": "55529", + "mass": "992.5", + "name": "Sutter's Mill", + "nametype": "Valid", + "recclass": "C", + "reclat": "38.803890", + "reclong": "-120.908060", + "year": "2012-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "29", + ":@computed_region_nnqa_25f4": "1637", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-86.2945, 33.18836] }, + "id": "23773", + "mass": "5560", + "name": "Sylacauga", + "nametype": "Valid", + "recclass": "H4", + "reclat": "33.188360", + "reclong": "-86.294500", + "year": "1954-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [14.65, 49.4] }, + "id": "23776", + "mass": "7540", + "name": "Tabor", + "nametype": "Valid", + "recclass": "H5", + "reclat": "49.400000", + "reclong": "14.650000", + "year": "1753-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [5.41667, 36.18333] }, + "id": "23778", + "mass": "9000", + "name": "Tadjera", + "nametype": "Valid", + "recclass": "L5", + "reclat": "36.183330", + "reclong": "5.416670", + "year": "1867-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-134.20139, 59.70444] }, + "id": "23782", + "mass": "10000", + "name": "Tagish Lake", + "nametype": "Valid", + "recclass": "C2-ung", + "reclat": "59.704440", + "reclong": "-134.201390", + "year": "2000-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [137.305, 34.72] }, + "id": "23784", + "mass": "1000", + "name": "Tahara", + "nametype": "Valid", + "recclass": "H4/5", + "reclat": "34.720000", + "reclong": "137.305000", + "year": "1991-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [134.9, 35.38333] }, + "id": "23789", + "mass": "720", + "name": "Takenouchi", + "nametype": "Valid", + "recclass": "H5", + "reclat": "35.383330", + "reclong": "134.900000", + "year": "1880-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "id": "23791", + "mass": "1421", + "name": "Talampaya", + "nametype": "Valid", + "recclass": "Eucrite-cm", + "year": "1995-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [112.76667, -7.75] }, + "id": "23795", + "mass": "10500", + "name": "Tambakwatu", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-7.750000", + "reclong": "112.766670", + "year": "1975-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.015, 31.16333] }, + "id": "48691", + "mass": "100000", + "name": "Tamdakht", + "nametype": "Valid", + "recclass": "H5", + "reclat": "31.163330", + "reclong": "-7.015000", + "year": "2008-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [136.23333, 35.43333] }, + "id": "23801", + "mass": "905", + "name": "TanΓ©", + "nametype": "Valid", + "recclass": "L5", + "reclat": "35.433330", + "reclong": "136.233330", + "year": "1918-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [122.9, 45.4] }, + "id": "23873", + "mass": "3850", + "name": "Taonan", + "nametype": "Valid", + "recclass": "L5", + "reclat": "45.400000", + "reclong": "122.900000", + "year": "1965-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [10.41667, 32.95] }, + "id": "23884", + "mass": "12000", + "name": "Tatahouine", + "nametype": "Valid", + "recclass": "Diogenite", + "reclat": "32.950000", + "reclong": "10.416670", + "year": "1931-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [43.73333, 19.38333] }, + "id": "23885", + "mass": "2500", + "name": "Tathlith", + "nametype": "Valid", + "recclass": "L6", + "reclat": "19.383330", + "reclong": "43.733330", + "year": "1967-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [44.45, 35.13333] }, + "id": "23887", + "mass": "6000", + "name": "Tauk", + "nametype": "Valid", + "recclass": "L6", + "reclat": "35.133330", + "reclong": "44.450000", + "year": "1929-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [23.5, 46.71667] }, + "id": "23888", + "mass": "21000", + "name": "Tauti", + "nametype": "Valid", + "recclass": "L6", + "reclat": "46.716670", + "reclong": "23.500000", + "year": "1937-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [142.95, -25.73333] }, + "id": "23897", + "mass": "160000", + "name": "Tenham", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-25.733330", + "reclong": "142.950000", + "year": "1879-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [26.95, 58.03333] }, + "id": "23898", + "mass": "28500", + "name": "Tennasilm", + "nametype": "Valid", + "recclass": "L4", + "reclat": "58.033330", + "reclong": "26.950000", + "year": "1872-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [70.6, 33.4] }, + "id": "23908", + "mass": "342", + "name": "Thal", + "nametype": "Valid", + "recclass": "H6", + "reclat": "33.400000", + "reclong": "70.600000", + "year": "1950-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [37.15028, -1.00278] }, + "id": "54493", + "mass": "14200", + "name": "Thika", + "nametype": "Valid", + "recclass": "L6", + "reclat": "-1.002780", + "reclong": "37.150280", + "year": "2011-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [27.58333, -29.33333] }, + "id": "23976", + "mass": "45300", + "name": "Thuathe", + "nametype": "Valid", + "recclass": "H4/5", + "reclat": "-29.333330", + "reclong": "27.583330", + "year": "2002-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [118.99, 32.94667] }, + "id": "23984", + "mass": "2232", + "name": "Tianzhang", + "nametype": "Valid", + "recclass": "H5", + "reclat": "32.946670", + "reclong": "118.990000", + "year": "1986-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [17.11667, 49.6] }, + "id": "23989", + "mass": "28000", + "name": "Tieschitz", + "nametype": "Valid", + "recclass": "H/L3.6", + "reclat": "49.600000", + "reclong": "17.116670", + "year": "1878-01-01T00:00:00.000Z" + }, + { + ":@computed_region_cbhk_fwbd": "34", + ":@computed_region_nnqa_25f4": "1762", + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-89.68333, 38.2] }, + "id": "23998", + "mass": "74800", + "name": "Tilden", + "nametype": "Valid", + "recclass": "L6", + "reclat": "38.200000", + "reclong": "-89.683330", + "year": "1927-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [1.53333, 14.25] }, + "id": "23999", + "mass": "3000", + "name": "Tillaberi", + "nametype": "Valid", + "recclass": "L6", + "reclat": "14.250000", + "reclong": "1.533330", + "year": "1970-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [35.2, 54.5] }, + "id": "24004", + "mass": "65500", + "name": "Timochin", + "nametype": "Valid", + "recclass": "H5", + "reclat": "54.500000", + "reclong": "35.200000", + "year": "1807-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [79.41667, 13.63333] }, + "id": "24009", + "mass": "230", + "name": "Tirupati", + "nametype": "Valid", + "recclass": "H6", + "reclat": "13.633330", + "reclong": "79.416670", + "year": "1934-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [-7.61123, 29.48195] }, + "id": "54823", + "mass": "7000", + "name": "Tissint", + "nametype": "Valid", + "recclass": "Martian (shergottite)", + "reclat": "29.481950", + "reclong": "-7.611230", + "year": "2011-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [111.53333, -7.08333] }, + "id": "24011", + "mass": "20000", + "name": "Tjabe", + "nametype": "Valid", + "recclass": "H6", + "reclat": "-7.083330", + "reclong": "111.533330", + "year": "1869-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [106.58333, -6.66667] }, + "id": "24012", + "mass": "16500", + "name": "Tjerebon", + "nametype": "Valid", + "recclass": "L5", + "reclat": "-6.666670", + "reclong": "106.583330", + "year": "1922-01-01T00:00:00.000Z" + }, + { + "fall": "Fell", + "geolocation": { "type": "Point", "coordinates": [34.76667, 47.85] }, + "id": "24019", + "mass": "600", + "name": "Tomakovka", + "nametype": "Valid", + "recclass": "LL6", + "reclat": "47.850000", + "reclong": "34.766670", + "year": "1905-01-01T00:00:00.000Z" + } +] diff --git a/test/inputs/json/misc/d23d5.json b/test/inputs/json/misc/d23d5.json index f1a1cc748..a29416c8b 100644 --- a/test/inputs/json/misc/d23d5.json +++ b/test/inputs/json/misc/d23d5.json @@ -1 +1,410 @@ -{"count": 49140, "facets": {}, "results": [{"name": "Mr Giampiero Reggidori", "acronym": null, "created_at": "2016-08-10T02:08:59.817023", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffff4d12eef74252b51812e9ce1713de", "updated_at": "2016-08-10T02:08:59.815655", "id": "ffff4d12eef74252b51812e9ce1713de"}, {"name": "Istituto Diplomatico Internazionale", "acronym": "I D I", "created_at": "2015-04-24T01:57:50.571116", "uri": "http://api.lobbyfacts.eu/api/1/entity/fffe798a051d4b228ae612b431ca064a", "updated_at": "2015-04-24T01:57:50.570385", "id": "fffe798a051d4b228ae612b431ca064a"}, {"name": "Ms Dragica Pilipovic Chaffey", "acronym": null, "created_at": "2016-02-03T02:50:46.244113", "uri": "http://api.lobbyfacts.eu/api/1/entity/fffd45719a79476c8ef0366685e99a74", "updated_at": "2016-02-03T02:50:46.242658", "id": "fffd45719a79476c8ef0366685e99a74"}, {"name": "Mr Alex Gorsky", "acronym": null, "created_at": "2015-04-24T01:48:58.565673", "uri": "http://api.lobbyfacts.eu/api/1/entity/fffcf9db4c424ba38fd5e812dd8aeaac", "updated_at": "2015-04-24T01:48:58.564945", "id": "fffcf9db4c424ba38fd5e812dd8aeaac"}, {"name": "Mr Gregory Francis ", "acronym": null, "created_at": "2015-04-24T02:23:58.791310", "uri": "http://api.lobbyfacts.eu/api/1/entity/fffce2ef05014cfdaf322f13ee3d9db0", "updated_at": "2015-04-24T02:23:58.790188", "id": "fffce2ef05014cfdaf322f13ee3d9db0"}, {"name": "Ms Larisa Pircalabelu", "acronym": null, "created_at": "2016-07-21T01:23:59.142183", "uri": "http://api.lobbyfacts.eu/api/1/entity/fffc8702608445c9a8793517f4534fb1", "updated_at": "2016-07-21T01:23:59.141433", "id": "fffc8702608445c9a8793517f4534fb1"}, {"name": "Mr Alexander Kneepkens", "acronym": null, "created_at": "2015-05-07T21:34:40.869573", "uri": "http://api.lobbyfacts.eu/api/1/entity/fff720deb12f4b1fb0f149469d15b5e5", "updated_at": "2015-05-07T21:34:40.868283", "id": "fff720deb12f4b1fb0f149469d15b5e5"}, {"name": "Mr Marco Digioia", "acronym": null, "created_at": "2015-04-24T01:53:59.129907", "uri": "http://api.lobbyfacts.eu/api/1/entity/fff48726498240688ff6db5c7611a70c", "updated_at": "2015-04-24T01:53:59.129280", "id": "fff48726498240688ff6db5c7611a70c"}, {"name": "Ms Adela BRUSOVA", "acronym": null, "created_at": "2015-04-24T02:03:33.932156", "uri": "http://api.lobbyfacts.eu/api/1/entity/fff1decf9c744ea09e540504ad514763", "updated_at": "2015-04-24T02:03:33.931445", "id": "fff1decf9c744ea09e540504ad514763"}, {"name": "Ms Anja Ingenrieth", "acronym": null, "created_at": "2015-05-07T21:14:28.711779", "uri": "http://api.lobbyfacts.eu/api/1/entity/fff1538c8ea349d18866a8f98c862ff8", "updated_at": "2015-05-07T21:14:28.710327", "id": "fff1538c8ea349d18866a8f98c862ff8"}, {"name": "Mr Dimitrios Lyridis", "acronym": null, "created_at": "2016-05-08T01:49:49.437857", "uri": "http://api.lobbyfacts.eu/api/1/entity/fff11d63c1334292bf8a4780e68c8cfe", "updated_at": "2016-05-08T01:49:49.436442", "id": "fff11d63c1334292bf8a4780e68c8cfe"}, {"name": "Ms Rosanna Lewis", "acronym": null, "created_at": "2016-03-18T01:36:59.675522", "uri": "http://api.lobbyfacts.eu/api/1/entity/fff0a5c1b9494f989e85ef7c2b9f5ac5", "updated_at": "2016-03-18T01:36:59.673429", "id": "fff0a5c1b9494f989e85ef7c2b9f5ac5"}, {"name": "Mr Pascal Montredon", "acronym": null, "created_at": "2016-05-05T01:19:54.860443", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffee3e4971634c929b8b61b24fb2f08a", "updated_at": "2016-05-05T01:19:54.859001", "id": "ffee3e4971634c929b8b61b24fb2f08a"}, {"name": "Mr Jelmen HAAZE", "acronym": null, "created_at": "2015-10-30T00:39:35.770055", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffeba603bb3947c7a43a4c086031b3aa", "updated_at": "2015-10-30T00:39:35.768633", "id": "ffeba603bb3947c7a43a4c086031b3aa"}, {"name": "Mr Flavio BURLIZZI", "acronym": null, "created_at": "2015-08-04T22:57:51.011270", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffeae77f2b894a33b881ec2b79e29117", "updated_at": "2015-08-04T22:57:51.009831", "id": "ffeae77f2b894a33b881ec2b79e29117"}, {"name": "Ms Tomoyo Sekiguchi ", "acronym": null, "created_at": "2016-03-09T02:38:11.880805", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe968703bb44040b61bce6494c59a97", "updated_at": "2016-03-09T02:38:11.878442", "id": "ffe968703bb44040b61bce6494c59a97"}, {"name": "Conseil G\u00e9n\u00e9ral du Gard", "acronym": null, "created_at": "2016-03-17T03:00:04.766562", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe8919709ac4830ad71b625294b7382", "updated_at": "2016-03-17T03:00:04.765137", "id": "ffe8919709ac4830ad71b625294b7382"}, {"name": "EUROPEAN FEDERATION OF BUILDING AND WOODWORKERS", "acronym": "EFBWW", "created_at": "2015-05-07T21:26:53.280572", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe7eff4d34b4d7b97239846b8964fbe", "updated_at": "2015-05-07T21:26:53.279783", "id": "ffe7eff4d34b4d7b97239846b8964fbe"}, {"name": "Think Tank EUROPA", "acronym": "TTE", "created_at": "2015-04-24T02:24:58.732688", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe6fffd4f1e4dbf8ff26ffa80f132c6", "updated_at": "2015-04-24T02:24:58.731979", "id": "ffe6fffd4f1e4dbf8ff26ffa80f132c6"}, {"name": "Ms Willig Caren", "acronym": null, "created_at": "2015-12-10T02:00:11.666098", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe54c713fc04c03bf8aca713f9ad2e8", "updated_at": "2015-12-10T02:00:11.665101", "id": "ffe54c713fc04c03bf8aca713f9ad2e8"}, {"name": "Solum", "acronym": null, "created_at": "2015-05-07T21:30:52.601629", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe3e1c97a4f445ab1dd1e4c60bc18cf", "updated_at": "2015-05-07T21:30:52.600789", "id": "ffe3e1c97a4f445ab1dd1e4c60bc18cf"}, {"name": "EUBrasil", "acronym": null, "created_at": "2015-04-24T02:06:02.774935", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe37e4dd46042a0bf0654695f0ad0ae", "updated_at": "2015-04-24T02:06:02.773344", "id": "ffe37e4dd46042a0bf0654695f0ad0ae"}, {"name": "Mr Thorsten Dr. Diercks", "acronym": null, "created_at": "2015-05-07T21:21:26.956745", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe3548dcf8c48a9b4fa39d530a9fd0e", "updated_at": "2015-05-07T21:21:26.955469", "id": "ffe3548dcf8c48a9b4fa39d530a9fd0e"}, {"name": "Airbus Aeronautics", "acronym": null, "created_at": "2016-04-05T00:12:27.592570", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe23c57f5d34e55b63580fa92eef387", "updated_at": "2016-04-05T00:12:27.590570", "id": "ffe23c57f5d34e55b63580fa92eef387"}, {"name": "Ms Elisa Briga", "acronym": null, "created_at": "2015-04-24T01:57:23.904841", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe18d1d8713464bbbf7c1e81887c68b", "updated_at": "2015-04-24T01:57:23.904057", "id": "ffe18d1d8713464bbbf7c1e81887c68b"}, {"name": "Ms Roza Maria Strevinioti", "acronym": null, "created_at": "2015-04-24T02:00:42.086250", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe06b4f2f2c4b6faebdf361bb9b4ac1", "updated_at": "2015-04-24T02:00:42.084916", "id": "ffe06b4f2f2c4b6faebdf361bb9b4ac1"}, {"name": "Association for the International Collective Management of Audiovisual Works", "acronym": "AGICOA", "created_at": "2015-11-14T02:02:49.268803", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffddc42b48c641b2b9781be1123df0e5", "updated_at": "2015-11-14T02:02:49.267949", "id": "ffddc42b48c641b2b9781be1123df0e5"}, {"name": "Mr Joachim BERNEY", "acronym": null, "created_at": "2015-08-04T23:44:49.425906", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdda474c46e47698baa4d5afbc99977", "updated_at": "2015-08-04T23:44:49.424473", "id": "ffdda474c46e47698baa4d5afbc99977"}, {"name": "Mr John Barradell", "acronym": null, "created_at": "2015-10-15T00:50:12.091403", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdd6e406d494529821a8bdee1be4b33", "updated_at": "2015-10-15T00:50:12.089971", "id": "ffdd6e406d494529821a8bdee1be4b33"}, {"name": "Osterreichische Post AG", "acronym": null, "created_at": "2016-04-21T01:17:40.241168", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdcb1ae5ba74431aa24fa630b339e18", "updated_at": "2016-04-21T01:17:40.240405", "id": "ffdcb1ae5ba74431aa24fa630b339e18"}, {"name": "Mr Tom Nysted", "acronym": null, "created_at": "2015-04-24T02:15:04.802512", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdb8caab0284102b7177dd75d4922a8", "updated_at": "2015-04-24T02:15:04.801810", "id": "ffdb8caab0284102b7177dd75d4922a8"}, {"name": "Mr Jaime BERNIS", "acronym": null, "created_at": "2015-09-16T23:38:29.717737", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffda5015f466463aad395c55eb98d234", "updated_at": "2015-09-16T23:38:29.716938", "id": "ffda5015f466463aad395c55eb98d234"}, {"name": "Mr David McKenna", "acronym": null, "created_at": "2015-04-24T02:02:52.877702", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd990efd8c341b78aa0101b67b9477f", "updated_at": "2015-04-24T02:02:52.876918", "id": "ffd990efd8c341b78aa0101b67b9477f"}, {"name": "Instituto para la Producci\u00f3n Sostenible", "acronym": null, "created_at": "2015-05-07T21:39:59.552249", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd783eb6a9a4e43883b05dc4f211e01", "updated_at": "2015-05-07T21:39:59.551454", "id": "ffd783eb6a9a4e43883b05dc4f211e01"}, {"name": "Associazione Nazionale Consorzi Gestione e Tutela del Territorio e Acque irrigue", "acronym": "ANBI", "created_at": "2016-07-06T02:05:14.587863", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd67dd940974fff8dc870ddc0839205", "updated_at": "2016-07-06T02:05:14.586583", "id": "ffd67dd940974fff8dc870ddc0839205"}, {"name": "Open Internet Project", "acronym": "OIP", "created_at": "2015-04-24T02:30:51.174761", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd5e14900b64b1a9dd4a79748b1221e", "updated_at": "2015-04-24T02:30:51.173582", "id": "ffd5e14900b64b1a9dd4a79748b1221e"}, {"name": "MEADOW VALE FOODS LIMITED", "acronym": null, "created_at": "2016-05-07T01:57:58.384964", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd33a5c282d4b59b962b08b9383c823", "updated_at": "2016-05-07T01:57:58.383522", "id": "ffd33a5c282d4b59b962b08b9383c823"}, {"name": "Ms Costanza BUFALINI", "acronym": null, "created_at": "2015-05-07T21:17:08.207441", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcf912c4bf349bc8777cdd382dbeb77", "updated_at": "2015-05-07T21:17:08.206097", "id": "ffcf912c4bf349bc8777cdd382dbeb77"}, {"name": "Ms VILLARINO PILAR", "acronym": null, "created_at": "2016-05-18T01:55:35.885694", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcf6d726f9d4f2a865d4f9fffb80747", "updated_at": "2016-05-18T01:55:35.884374", "id": "ffcf6d726f9d4f2a865d4f9fffb80747"}, {"name": "Ms Claire Wilson-Leary", "acronym": null, "created_at": "2016-08-24T01:09:24.395536", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcbde4c9fff4951b1fd532ea5c3761d", "updated_at": "2016-08-24T01:09:24.394197", "id": "ffcbde4c9fff4951b1fd532ea5c3761d"}, {"name": "BlackBerry", "acronym": "BlackBerry", "created_at": "2015-04-24T02:07:17.565441", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcbcdf1eec342ed9287cfc9dc5ed71d", "updated_at": "2015-04-24T02:07:17.564649", "id": "ffcbcdf1eec342ed9287cfc9dc5ed71d"}, {"name": "Hewlett-Packard Company", "acronym": null, "created_at": "2015-04-24T01:48:14.159850", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcb47bb0ee44ac0a3597ba822be1d36", "updated_at": "2015-04-24T01:48:14.158413", "id": "ffcb47bb0ee44ac0a3597ba822be1d36"}, {"name": "Slovensk\u00e1 po\u0161ta, a. s.", "acronym": null, "created_at": "2016-04-21T01:17:40.762874", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffca0afa625f4d3bb5c87eb4c6d7e9af", "updated_at": "2016-04-21T01:17:40.762126", "id": "ffca0afa625f4d3bb5c87eb4c6d7e9af"}, {"name": "ADAS UK Limited", "acronym": null, "created_at": "2015-04-24T02:27:26.106588", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc8242abb324f3ba18bbf76fefb6284", "updated_at": "2015-04-24T02:27:26.105885", "id": "ffc8242abb324f3ba18bbf76fefb6284"}, {"name": "Ms Sandrell SULTANA", "acronym": null, "created_at": "2015-08-04T22:33:54.008095", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc7e169388b47c2bf38ba17931f77e6", "updated_at": "2015-08-04T22:33:54.006715", "id": "ffc7e169388b47c2bf38ba17931f77e6"}, {"name": "Europ\u00e4ischer Kartellverband christlicher Studentenverb\u00e4nde", "acronym": "EKV", "created_at": "2015-05-07T21:30:10.558170", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc781ee1d4041a1a6dc391f7f93b8b4", "updated_at": "2015-05-07T21:30:10.556740", "id": "ffc781ee1d4041a1a6dc391f7f93b8b4"}, {"name": "Mr Zden\u011bk Vermouzek", "acronym": null, "created_at": "2016-09-04T02:09:52.477933", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc654bd22e34ef0a77c5fbb0f6aec17", "updated_at": "2016-09-04T02:09:52.475693", "id": "ffc654bd22e34ef0a77c5fbb0f6aec17"}, {"name": "Ms Ana MINGO", "acronym": null, "created_at": "2015-08-04T23:30:45.426863", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc636f187cc4601b14f19d857092fc5", "updated_at": "2015-08-04T23:30:45.425384", "id": "ffc636f187cc4601b14f19d857092fc5"}, {"name": "Mr Carlton DEAL", "acronym": null, "created_at": "2015-08-04T22:55:14.129970", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc5d109563948389eadfd45ddf17112", "updated_at": "2015-08-04T22:55:14.128531", "id": "ffc5d109563948389eadfd45ddf17112"}, {"name": "Ms Diana Popa", "acronym": null, "created_at": "2015-04-24T02:09:48.888939", "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc4b62de478477d8b25f1d593e99467", "updated_at": "2015-04-24T02:09:48.888213", "id": "ffc4b62de478477d8b25f1d593e99467"}], "next": "http://api.lobbyfacts.eu/api/1/entity?limit=50&offset=50", "limit": 50, "offset": 0, "previous": false} \ No newline at end of file +{ + "count": 49140, + "facets": {}, + "results": [ + { + "name": "Mr Giampiero Reggidori", + "acronym": null, + "created_at": "2016-08-10T02:08:59.817023Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffff4d12eef74252b51812e9ce1713de", + "updated_at": "2016-08-10T02:08:59.815655Z", + "id": "ffff4d12eef74252b51812e9ce1713de" + }, + { + "name": "Istituto Diplomatico Internazionale", + "acronym": "I D I", + "created_at": "2015-04-24T01:57:50.571116Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fffe798a051d4b228ae612b431ca064a", + "updated_at": "2015-04-24T01:57:50.570385Z", + "id": "fffe798a051d4b228ae612b431ca064a" + }, + { + "name": "Ms Dragica Pilipovic Chaffey", + "acronym": null, + "created_at": "2016-02-03T02:50:46.244113Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fffd45719a79476c8ef0366685e99a74", + "updated_at": "2016-02-03T02:50:46.242658Z", + "id": "fffd45719a79476c8ef0366685e99a74" + }, + { + "name": "Mr Alex Gorsky", + "acronym": null, + "created_at": "2015-04-24T01:48:58.565673Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fffcf9db4c424ba38fd5e812dd8aeaac", + "updated_at": "2015-04-24T01:48:58.564945Z", + "id": "fffcf9db4c424ba38fd5e812dd8aeaac" + }, + { + "name": "Mr Gregory Francis ", + "acronym": null, + "created_at": "2015-04-24T02:23:58.791310Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fffce2ef05014cfdaf322f13ee3d9db0", + "updated_at": "2015-04-24T02:23:58.790188Z", + "id": "fffce2ef05014cfdaf322f13ee3d9db0" + }, + { + "name": "Ms Larisa Pircalabelu", + "acronym": null, + "created_at": "2016-07-21T01:23:59.142183Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fffc8702608445c9a8793517f4534fb1", + "updated_at": "2016-07-21T01:23:59.141433Z", + "id": "fffc8702608445c9a8793517f4534fb1" + }, + { + "name": "Mr Alexander Kneepkens", + "acronym": null, + "created_at": "2015-05-07T21:34:40.869573Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fff720deb12f4b1fb0f149469d15b5e5", + "updated_at": "2015-05-07T21:34:40.868283Z", + "id": "fff720deb12f4b1fb0f149469d15b5e5" + }, + { + "name": "Mr Marco Digioia", + "acronym": null, + "created_at": "2015-04-24T01:53:59.129907Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fff48726498240688ff6db5c7611a70c", + "updated_at": "2015-04-24T01:53:59.129280Z", + "id": "fff48726498240688ff6db5c7611a70c" + }, + { + "name": "Ms Adela BRUSOVA", + "acronym": null, + "created_at": "2015-04-24T02:03:33.932156Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fff1decf9c744ea09e540504ad514763", + "updated_at": "2015-04-24T02:03:33.931445Z", + "id": "fff1decf9c744ea09e540504ad514763" + }, + { + "name": "Ms Anja Ingenrieth", + "acronym": null, + "created_at": "2015-05-07T21:14:28.711779Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fff1538c8ea349d18866a8f98c862ff8", + "updated_at": "2015-05-07T21:14:28.710327Z", + "id": "fff1538c8ea349d18866a8f98c862ff8" + }, + { + "name": "Mr Dimitrios Lyridis", + "acronym": null, + "created_at": "2016-05-08T01:49:49.437857Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fff11d63c1334292bf8a4780e68c8cfe", + "updated_at": "2016-05-08T01:49:49.436442Z", + "id": "fff11d63c1334292bf8a4780e68c8cfe" + }, + { + "name": "Ms Rosanna Lewis", + "acronym": null, + "created_at": "2016-03-18T01:36:59.675522Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/fff0a5c1b9494f989e85ef7c2b9f5ac5", + "updated_at": "2016-03-18T01:36:59.673429Z", + "id": "fff0a5c1b9494f989e85ef7c2b9f5ac5" + }, + { + "name": "Mr Pascal Montredon", + "acronym": null, + "created_at": "2016-05-05T01:19:54.860443Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffee3e4971634c929b8b61b24fb2f08a", + "updated_at": "2016-05-05T01:19:54.859001Z", + "id": "ffee3e4971634c929b8b61b24fb2f08a" + }, + { + "name": "Mr Jelmen HAAZE", + "acronym": null, + "created_at": "2015-10-30T00:39:35.770055Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffeba603bb3947c7a43a4c086031b3aa", + "updated_at": "2015-10-30T00:39:35.768633Z", + "id": "ffeba603bb3947c7a43a4c086031b3aa" + }, + { + "name": "Mr Flavio BURLIZZI", + "acronym": null, + "created_at": "2015-08-04T22:57:51.011270Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffeae77f2b894a33b881ec2b79e29117", + "updated_at": "2015-08-04T22:57:51.009831Z", + "id": "ffeae77f2b894a33b881ec2b79e29117" + }, + { + "name": "Ms Tomoyo Sekiguchi ", + "acronym": null, + "created_at": "2016-03-09T02:38:11.880805Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe968703bb44040b61bce6494c59a97", + "updated_at": "2016-03-09T02:38:11.878442Z", + "id": "ffe968703bb44040b61bce6494c59a97" + }, + { + "name": "Conseil G\u00e9n\u00e9ral du Gard", + "acronym": null, + "created_at": "2016-03-17T03:00:04.766562Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe8919709ac4830ad71b625294b7382", + "updated_at": "2016-03-17T03:00:04.765137Z", + "id": "ffe8919709ac4830ad71b625294b7382" + }, + { + "name": "EUROPEAN FEDERATION OF BUILDING AND WOODWORKERS", + "acronym": "EFBWW", + "created_at": "2015-05-07T21:26:53.280572Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe7eff4d34b4d7b97239846b8964fbe", + "updated_at": "2015-05-07T21:26:53.279783Z", + "id": "ffe7eff4d34b4d7b97239846b8964fbe" + }, + { + "name": "Think Tank EUROPA", + "acronym": "TTE", + "created_at": "2015-04-24T02:24:58.732688Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe6fffd4f1e4dbf8ff26ffa80f132c6", + "updated_at": "2015-04-24T02:24:58.731979Z", + "id": "ffe6fffd4f1e4dbf8ff26ffa80f132c6" + }, + { + "name": "Ms Willig Caren", + "acronym": null, + "created_at": "2015-12-10T02:00:11.666098Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe54c713fc04c03bf8aca713f9ad2e8", + "updated_at": "2015-12-10T02:00:11.665101Z", + "id": "ffe54c713fc04c03bf8aca713f9ad2e8" + }, + { + "name": "Solum", + "acronym": null, + "created_at": "2015-05-07T21:30:52.601629Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe3e1c97a4f445ab1dd1e4c60bc18cf", + "updated_at": "2015-05-07T21:30:52.600789Z", + "id": "ffe3e1c97a4f445ab1dd1e4c60bc18cf" + }, + { + "name": "EUBrasil", + "acronym": null, + "created_at": "2015-04-24T02:06:02.774935Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe37e4dd46042a0bf0654695f0ad0ae", + "updated_at": "2015-04-24T02:06:02.773344Z", + "id": "ffe37e4dd46042a0bf0654695f0ad0ae" + }, + { + "name": "Mr Thorsten Dr. Diercks", + "acronym": null, + "created_at": "2015-05-07T21:21:26.956745Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe3548dcf8c48a9b4fa39d530a9fd0e", + "updated_at": "2015-05-07T21:21:26.955469Z", + "id": "ffe3548dcf8c48a9b4fa39d530a9fd0e" + }, + { + "name": "Airbus Aeronautics", + "acronym": null, + "created_at": "2016-04-05T00:12:27.592570Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe23c57f5d34e55b63580fa92eef387", + "updated_at": "2016-04-05T00:12:27.590570Z", + "id": "ffe23c57f5d34e55b63580fa92eef387" + }, + { + "name": "Ms Elisa Briga", + "acronym": null, + "created_at": "2015-04-24T01:57:23.904841Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe18d1d8713464bbbf7c1e81887c68b", + "updated_at": "2015-04-24T01:57:23.904057Z", + "id": "ffe18d1d8713464bbbf7c1e81887c68b" + }, + { + "name": "Ms Roza Maria Strevinioti", + "acronym": null, + "created_at": "2015-04-24T02:00:42.086250Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffe06b4f2f2c4b6faebdf361bb9b4ac1", + "updated_at": "2015-04-24T02:00:42.084916Z", + "id": "ffe06b4f2f2c4b6faebdf361bb9b4ac1" + }, + { + "name": "Association for the International Collective Management of Audiovisual Works", + "acronym": "AGICOA", + "created_at": "2015-11-14T02:02:49.268803Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffddc42b48c641b2b9781be1123df0e5", + "updated_at": "2015-11-14T02:02:49.267949Z", + "id": "ffddc42b48c641b2b9781be1123df0e5" + }, + { + "name": "Mr Joachim BERNEY", + "acronym": null, + "created_at": "2015-08-04T23:44:49.425906Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdda474c46e47698baa4d5afbc99977", + "updated_at": "2015-08-04T23:44:49.424473Z", + "id": "ffdda474c46e47698baa4d5afbc99977" + }, + { + "name": "Mr John Barradell", + "acronym": null, + "created_at": "2015-10-15T00:50:12.091403Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdd6e406d494529821a8bdee1be4b33", + "updated_at": "2015-10-15T00:50:12.089971Z", + "id": "ffdd6e406d494529821a8bdee1be4b33" + }, + { + "name": "Osterreichische Post AG", + "acronym": null, + "created_at": "2016-04-21T01:17:40.241168Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdcb1ae5ba74431aa24fa630b339e18", + "updated_at": "2016-04-21T01:17:40.240405Z", + "id": "ffdcb1ae5ba74431aa24fa630b339e18" + }, + { + "name": "Mr Tom Nysted", + "acronym": null, + "created_at": "2015-04-24T02:15:04.802512Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffdb8caab0284102b7177dd75d4922a8", + "updated_at": "2015-04-24T02:15:04.801810Z", + "id": "ffdb8caab0284102b7177dd75d4922a8" + }, + { + "name": "Mr Jaime BERNIS", + "acronym": null, + "created_at": "2015-09-16T23:38:29.717737Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffda5015f466463aad395c55eb98d234", + "updated_at": "2015-09-16T23:38:29.716938Z", + "id": "ffda5015f466463aad395c55eb98d234" + }, + { + "name": "Mr David McKenna", + "acronym": null, + "created_at": "2015-04-24T02:02:52.877702Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd990efd8c341b78aa0101b67b9477f", + "updated_at": "2015-04-24T02:02:52.876918Z", + "id": "ffd990efd8c341b78aa0101b67b9477f" + }, + { + "name": "Instituto para la Producci\u00f3n Sostenible", + "acronym": null, + "created_at": "2015-05-07T21:39:59.552249Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd783eb6a9a4e43883b05dc4f211e01", + "updated_at": "2015-05-07T21:39:59.551454Z", + "id": "ffd783eb6a9a4e43883b05dc4f211e01" + }, + { + "name": "Associazione Nazionale Consorzi Gestione e Tutela del Territorio e Acque irrigue", + "acronym": "ANBI", + "created_at": "2016-07-06T02:05:14.587863Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd67dd940974fff8dc870ddc0839205", + "updated_at": "2016-07-06T02:05:14.586583Z", + "id": "ffd67dd940974fff8dc870ddc0839205" + }, + { + "name": "Open Internet Project", + "acronym": "OIP", + "created_at": "2015-04-24T02:30:51.174761Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd5e14900b64b1a9dd4a79748b1221e", + "updated_at": "2015-04-24T02:30:51.173582Z", + "id": "ffd5e14900b64b1a9dd4a79748b1221e" + }, + { + "name": "MEADOW VALE FOODS LIMITED", + "acronym": null, + "created_at": "2016-05-07T01:57:58.384964Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffd33a5c282d4b59b962b08b9383c823", + "updated_at": "2016-05-07T01:57:58.383522Z", + "id": "ffd33a5c282d4b59b962b08b9383c823" + }, + { + "name": "Ms Costanza BUFALINI", + "acronym": null, + "created_at": "2015-05-07T21:17:08.207441Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcf912c4bf349bc8777cdd382dbeb77", + "updated_at": "2015-05-07T21:17:08.206097Z", + "id": "ffcf912c4bf349bc8777cdd382dbeb77" + }, + { + "name": "Ms VILLARINO PILAR", + "acronym": null, + "created_at": "2016-05-18T01:55:35.885694Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcf6d726f9d4f2a865d4f9fffb80747", + "updated_at": "2016-05-18T01:55:35.884374Z", + "id": "ffcf6d726f9d4f2a865d4f9fffb80747" + }, + { + "name": "Ms Claire Wilson-Leary", + "acronym": null, + "created_at": "2016-08-24T01:09:24.395536Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcbde4c9fff4951b1fd532ea5c3761d", + "updated_at": "2016-08-24T01:09:24.394197Z", + "id": "ffcbde4c9fff4951b1fd532ea5c3761d" + }, + { + "name": "BlackBerry", + "acronym": "BlackBerry", + "created_at": "2015-04-24T02:07:17.565441Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcbcdf1eec342ed9287cfc9dc5ed71d", + "updated_at": "2015-04-24T02:07:17.564649Z", + "id": "ffcbcdf1eec342ed9287cfc9dc5ed71d" + }, + { + "name": "Hewlett-Packard Company", + "acronym": null, + "created_at": "2015-04-24T01:48:14.159850Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffcb47bb0ee44ac0a3597ba822be1d36", + "updated_at": "2015-04-24T01:48:14.158413Z", + "id": "ffcb47bb0ee44ac0a3597ba822be1d36" + }, + { + "name": "Slovensk\u00e1 po\u0161ta, a. s.", + "acronym": null, + "created_at": "2016-04-21T01:17:40.762874Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffca0afa625f4d3bb5c87eb4c6d7e9af", + "updated_at": "2016-04-21T01:17:40.762126Z", + "id": "ffca0afa625f4d3bb5c87eb4c6d7e9af" + }, + { + "name": "ADAS UK Limited", + "acronym": null, + "created_at": "2015-04-24T02:27:26.106588Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc8242abb324f3ba18bbf76fefb6284", + "updated_at": "2015-04-24T02:27:26.105885Z", + "id": "ffc8242abb324f3ba18bbf76fefb6284" + }, + { + "name": "Ms Sandrell SULTANA", + "acronym": null, + "created_at": "2015-08-04T22:33:54.008095Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc7e169388b47c2bf38ba17931f77e6", + "updated_at": "2015-08-04T22:33:54.006715Z", + "id": "ffc7e169388b47c2bf38ba17931f77e6" + }, + { + "name": "Europ\u00e4ischer Kartellverband christlicher Studentenverb\u00e4nde", + "acronym": "EKV", + "created_at": "2015-05-07T21:30:10.558170Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc781ee1d4041a1a6dc391f7f93b8b4", + "updated_at": "2015-05-07T21:30:10.556740Z", + "id": "ffc781ee1d4041a1a6dc391f7f93b8b4" + }, + { + "name": "Mr Zden\u011bk Vermouzek", + "acronym": null, + "created_at": "2016-09-04T02:09:52.477933Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc654bd22e34ef0a77c5fbb0f6aec17", + "updated_at": "2016-09-04T02:09:52.475693Z", + "id": "ffc654bd22e34ef0a77c5fbb0f6aec17" + }, + { + "name": "Ms Ana MINGO", + "acronym": null, + "created_at": "2015-08-04T23:30:45.426863Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc636f187cc4601b14f19d857092fc5", + "updated_at": "2015-08-04T23:30:45.425384Z", + "id": "ffc636f187cc4601b14f19d857092fc5" + }, + { + "name": "Mr Carlton DEAL", + "acronym": null, + "created_at": "2015-08-04T22:55:14.129970Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc5d109563948389eadfd45ddf17112", + "updated_at": "2015-08-04T22:55:14.128531Z", + "id": "ffc5d109563948389eadfd45ddf17112" + }, + { + "name": "Ms Diana Popa", + "acronym": null, + "created_at": "2015-04-24T02:09:48.888939Z", + "uri": "http://api.lobbyfacts.eu/api/1/entity/ffc4b62de478477d8b25f1d593e99467", + "updated_at": "2015-04-24T02:09:48.888213Z", + "id": "ffc4b62de478477d8b25f1d593e99467" + } + ], + "next": "http://api.lobbyfacts.eu/api/1/entity?limit=50&offset=50", + "limit": 50, + "offset": 0, + "previous": false +} diff --git a/test/inputs/json/samples/null-safe.json b/test/inputs/json/samples/null-safe.json index 2151c10a7..77ba06a39 100644 --- a/test/inputs/json/samples/null-safe.json +++ b/test/inputs/json/samples/null-safe.json @@ -8,7 +8,7 @@ "city": "ζ±Ÿθ‹θ‹ε·ž", "country": "δΈ­ε›½" }, - "created_at": "2015-04-24T01:46:50.459583" + "created_at": "2015-04-24T01:46:50.459583Z" }, { "name": "David", diff --git a/test/inputs/schema/date-time.1.json b/test/inputs/schema/date-time.1.json index e4e95c99e..14551f9c6 100644 --- a/test/inputs/schema/date-time.1.json +++ b/test/inputs/schema/date-time.1.json @@ -1,7 +1,7 @@ { - "date": "1985-04-12", - "time": "23:20:50.52Z", - "date-time": "2018-08-13T21:31:01+00:00", - "union-array": ["1985-04-12", "23:20:50.52Z"], - "complex-union-array": ["2018-08-13T21:31:01+00:00", "foo", 123] + "date": "1985-04-12", + "time": "23:20:50.52Z", + "date-time": "2018-08-13T21:31:01+01:00", + "union-array": ["1985-04-12", "23:20:50.52Z"], + "complex-union-array": ["2018-08-13T21:31:01+00:10", "foo", 123] } diff --git a/test/inputs/schema/top-level-primitive.schema b/test/inputs/schema/top-level-primitive.schema new file mode 100644 index 000000000..64c1c8cab --- /dev/null +++ b/test/inputs/schema/top-level-primitive.schema @@ -0,0 +1,6 @@ +{ + "id": "http://json-schema.org/geo", + "$schema": "http://json-schema.org/draft-06/schema#", + "description": "Top level primitive", + "type": "number" +} diff --git a/test/languages.ts b/test/languages.ts index 222559d18..9573f3e57 100644 --- a/test/languages.ts +++ b/test/languages.ts @@ -1,8 +1,15 @@ +import type { LanguageName } from "quicktype-core"; + import * as process from "process"; // @ts-ignore -import { RendererOptions } from "../dist/quicktype-core/Run"; +import type { RendererOptions } from "../dist/quicktype-core/Run"; -const easySampleJSONs = ["bitcoin-block.json", "pokedex.json", "simple-object.json", "getting-started.json"]; +const easySampleJSONs = [ + "bitcoin-block.json", + "pokedex.json", + "simple-object.json", + "getting-started.json", +]; export type LanguageFeature = | "enum" @@ -18,7 +25,7 @@ export type LanguageFeature = | "pattern"; export interface Language { - name: string; + name: LanguageName; base: string; setupCommand?: string; compileCommand?: string; @@ -50,17 +57,26 @@ export const CSharpLanguage: Language = { diffViaSchema: true, skipDiffViaSchema: ["34702.json", "437e7.json"], allowMissingNull: false, - features: ["enum", "union", "no-defaults", "strict-optional", "date-time", "integer-string", "bool-string", "uuid"], + features: [ + "enum", + "union", + "no-defaults", + "strict-optional", + "date-time", + "integer-string", + "bool-string", + "uuid", + ], output: "QuickType.cs", topLevel: "TopLevel", skipJSON: [ "nbl-stats.json", // See issue #823 "empty-enum.json", // https://github.com/JamesNK/Newtonsoft.Json/issues/1687 - "31189.json" // JSON.NET doesn't accept year 0000 as 1BC, though it should + "31189.json", // JSON.NET doesn't accept year 0000 as 1BC, though it should ], skipMiscJSON: false, skipSchema: [ - "top-level-enum.schema" // The code we generate for top-level enums is incompatible with the driver + "top-level-enum.schema", // The code we generate for top-level enums is incompatible with the driver ], rendererOptions: { "check-required": "true" }, quickTestRendererOptions: [ @@ -68,9 +84,9 @@ export const CSharpLanguage: Language = { { "csharp-version": "5" }, { density: "dense" }, { "number-type": "decimal" }, - { "any-type": "dynamic" } + { "any-type": "dynamic" }, ], - sourceFiles: ["src/language/CSharp.ts"] + sourceFiles: ["src/language/CSharp/index.ts"], }; export const CSharpLanguageSystemTextJson: Language = { @@ -84,15 +100,24 @@ export const CSharpLanguageSystemTextJson: Language = { diffViaSchema: true, skipDiffViaSchema: ["34702.json", "437e7.json"], allowMissingNull: false, - features: ["enum", "union", "no-defaults", "strict-optional", "date-time", "integer-string", "bool-string", "uuid"], + features: [ + "enum", + "union", + "no-defaults", + "strict-optional", + "date-time", + "integer-string", + "bool-string", + "uuid", + ], output: "QuickType.cs", topLevel: "TopLevel", skipJSON: [ - "31189.json" // .NET doesn't accept year 0000 as 1BC, though it should + "31189.json", // .NET doesn't accept year 0000 as 1BC, though it should ], skipMiscJSON: false, skipSchema: [ - "top-level-enum.schema" // The code we generate for top-level enums is incompatible with the driver + "top-level-enum.schema", // The code we generate for top-level enums is incompatible with the driver ], rendererOptions: { "check-required": "true", framework: "SystemTextJson" }, quickTestRendererOptions: [ @@ -100,9 +125,9 @@ export const CSharpLanguageSystemTextJson: Language = { { "csharp-version": "6" }, { density: "dense" }, { "number-type": "decimal" }, - { "any-type": "dynamic" } + { "any-type": "dynamic" }, ], - sourceFiles: ["src/language/CSharp.ts"] + sourceFiles: ["src/language/CSharp/index.ts"], }; export const JavaLanguage: Language = { @@ -120,34 +145,38 @@ export const JavaLanguage: Language = { features: ["enum", "union", "uuid"], output: "src/main/java/io/quicktype/TopLevel.java", topLevel: "TopLevel", - skipJSON: ["identifiers.json", "simple-identifiers.json", "nst-test-suite.json"], + skipJSON: [ + "identifiers.json", + "simple-identifiers.json", + "nst-test-suite.json", + ], skipMiscJSON: false, skipSchema: ["keyword-unions.schema"], // generates classes with names that are case-insensitively equal rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/Java.ts"] + sourceFiles: ["src/language/Java/index.ts"], }; export const JavaLanguageWithLegacyDateTime: Language = { ...JavaLanguage, skipSchema: [ ...JavaLanguage.skipSchema, - "date-time.schema" // Expects less strict serialization. + "date-time.schema", // Expects less strict serialization. ], skipJSON: [ ...(JavaLanguage.skipJSON !== undefined ? JavaLanguage.skipJSON : []), "0a358.json", // Expects less strict serialization (optional milliseconds). - "337ed.json" // Expects less strict serialization (optional milliseconds). + "337ed.json", // Expects less strict serialization (optional milliseconds). ], skipMiscJSON: true, // Handles edge cases differently and does not allow optional milliseconds. rendererOptions: { "datetime-provider": "legacy" }, - quickTestRendererOptions: [{ "array-type": "list" }] + quickTestRendererOptions: [{ "array-type": "list" }], }; export const JavaLanguageWithLombok: Language = { ...JavaLanguage, base: "test/fixtures/java-lombok", - quickTestRendererOptions: [{ "array-type": "list", lombok: "true" }] + quickTestRendererOptions: [{ "array-type": "list", lombok: "true" }], }; export const PythonLanguage: Language = { @@ -167,22 +196,30 @@ export const PythonLanguage: Language = { "7681c.json", "c3303.json", "e8b04.json", - "f6a65.json" + "f6a65.json", ], allowMissingNull: true, - features: ["enum", "union", "no-defaults", "date-time", "integer-string", "bool-string", "uuid"], + features: [ + "enum", + "union", + "no-defaults", + "date-time", + "integer-string", + "bool-string", + "uuid", + ], output: "quicktype.py", topLevel: "TopLevel", skipJSON: [ - "31189.json" // year 0 is out of range + "31189.json", // year 0 is out of range ], skipMiscJSON: false, skipSchema: [ - "keyword-unions.schema" // Requires more than 255 arguments + "keyword-unions.schema", // Requires more than 255 arguments ], rendererOptions: {}, quickTestRendererOptions: [{ "python-version": "3.5" }], - sourceFiles: ["src/language/Python.ts"] + sourceFiles: ["src/language/Python/index.ts"], }; export const RustLanguage: Language = { @@ -208,7 +245,7 @@ export const RustLanguage: Language = { "af2d1.json", "c3303.json", "e8b04.json", - "f6a65.json" + "f6a65.json", ], allowMissingNull: false, features: ["enum", "union", "no-defaults"], @@ -222,9 +259,9 @@ export const RustLanguage: Language = { { density: "dense" }, { visibility: "crate" }, { visibility: "private" }, - { visibility: "public" } + { visibility: "public" }, ], - sourceFiles: ["src/language/Rust.ts"] + sourceFiles: ["src/language/Rust/index.ts"], }; export const CrystalLanguage: Language = { @@ -251,19 +288,19 @@ export const CrystalLanguage: Language = { "4961a.json", "32431.json", "68c30.json", - "e8b04.json" + "e8b04.json", ], skipSchema: [ // Crystal does not handle enum mapping "enum.schema", // Crystal does not support top-level primitives "top-level-enum.schema", - "keyword-unions.schema" + "keyword-unions.schema", ], skipMiscJSON: false, rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/language/Crystal.ts"] + sourceFiles: ["src/language/Crystal/index.ts"], }; export const RubyLanguage: Language = { @@ -325,7 +362,7 @@ export const RubyLanguage: Language = { "e53b5.json", "f22f5.json", "f3139.json", - "e8b04.json" + "e8b04.json", ], allowMissingNull: true, features: ["enum", "union", "no-defaults"], @@ -346,16 +383,16 @@ export const RubyLanguage: Language = { "union-constructor-clash.json", "unions.json", "nbl-stats.json", - "kitchen-sink.json" + "kitchen-sink.json", ], skipSchema: [ // We don't generate a convenience method for top-level enums - "top-level-enum.schema" + "top-level-enum.schema", ], skipMiscJSON: false, rendererOptions: {}, quickTestRendererOptions: [["pokedex.json", { namespace: "QuickType" }]], - sourceFiles: ["src/language/ruby/index.ts"] + sourceFiles: ["src/language/ruby/index.ts"], }; export const GoLanguage: Language = { @@ -373,7 +410,7 @@ export const GoLanguage: Language = { "337ed.json", "34702.json", "7eb30.json", - "e8b04.json" + "e8b04.json", ], allowMissingNull: false, features: ["union"], @@ -386,17 +423,26 @@ export const GoLanguage: Language = { "nst-test-suite.json", // can't differenciate empty array and nothing for optional empty array // (omitempty). - "github-events.json" + "github-events.json", + // files contains datetime filed with contain non rfc3339 format value + "f6a65.json", + "e0ac7.json", + "c3303.json", + "7681c.json", + "437e7.json", + "127a1.json", + "26b49.json", + "0cffa.json", ], skipMiscJSON: false, skipSchema: [ // can't differenciate empty array and nothing for optional empty array // (omitempty). - "postman-collection.schema" + "postman-collection.schema", ], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/language/Golang.ts"] + sourceFiles: ["src/language/Golang/index.ts"], }; export const CJSONLanguage: Language = { @@ -404,7 +450,8 @@ export const CJSONLanguage: Language = { base: "test/fixtures/cjson", setupCommand: "curl -o cJSON.c https://raw.githubusercontent.com/DaveGamble/cJSON/v1.7.15/cJSON.c && curl -o cJSON.h https://raw.githubusercontent.com/DaveGamble/cJSON/v1.7.15/cJSON.h && curl -o list.h https://raw.githubusercontent.com/joelguittet/c-list/master/include/list.h && curl -o list.c https://raw.githubusercontent.com/joelguittet/c-list/master/src/list.c && curl -o hashtable.h https://raw.githubusercontent.com/joelguittet/c-hashtable/master/include/hashtable.h && curl -o hashtable.c https://raw.githubusercontent.com/joelguittet/c-hashtable/master/src/hashtable.c", - compileCommand: "gcc -O0 -o quicktype -I. cJSON.c hashtable.c list.c main.c -lpthread", + compileCommand: + "gcc -O0 -o quicktype -I. cJSON.c hashtable.c list.c main.c -lpthread", runCommand(sample: string) { return `valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --error-exitcode=1 ./quicktype "${sample}"`; }, @@ -419,10 +466,17 @@ export const CJSONLanguage: Language = { "fcca3.json", "bug427.json", "github-events.json", - "keywords.json" + "keywords.json", ], allowMissingNull: false, - features: ["minmax", "minmaxlength", "pattern", "enum", "union", "no-defaults"], + features: [ + "minmax", + "minmaxlength", + "pattern", + "enum", + "union", + "no-defaults", + ], output: "TopLevel.h", topLevel: "TopLevel", skipJSON: [ @@ -439,7 +493,7 @@ export const CJSONLanguage: Language = { /* Map in Array in TopLevel is not supported (for the current implementation, can be added later, need recursivity) */ "combinations2.json", /* Array in Array in Union is not supported (for the current implementation, can be added later, need recursivity) */ - "combinations4.json" + "combinations4.json", ], skipMiscJSON: false, skipSchema: [ @@ -470,11 +524,11 @@ export const CJSONLanguage: Language = { "optional-any.schema", "required-non-properties.schema", /* Other cases not supported */ - "implicit-class-array-union.schema" + "implicit-class-array-union.schema", ], rendererOptions: {}, quickTestRendererOptions: [{ "source-style": "single-source" }], - sourceFiles: ["src/language/CJSON.ts"] + sourceFiles: ["src/language/CJSON/index.ts"], }; export const CPlusPlusLanguage: Language = { @@ -501,10 +555,17 @@ export const CPlusPlusLanguage: Language = { "c3303.json", "e8b04.json", "f6a65.json", - "fcca3.json" + "fcca3.json", ], allowMissingNull: false, - features: ["minmax", "minmaxlength", "pattern", "enum", "union", "no-defaults"], + features: [ + "minmax", + "minmaxlength", + "pattern", + "enum", + "union", + "no-defaults", + ], output: "TopLevel.hpp", topLevel: "TopLevel", skipJSON: [ @@ -517,12 +578,12 @@ export const CPlusPlusLanguage: Language = { "combinations1.json", "combinations2.json", "combinations3.json", - "combinations4.json" + "combinations4.json", ], skipMiscJSON: false, skipSchema: [ // uses too much memory - "keyword-unions.schema" + "keyword-unions.schema", ], rendererOptions: {}, quickTestRendererOptions: [ @@ -531,9 +592,9 @@ export const CPlusPlusLanguage: Language = { { "code-format": "with-struct" }, { wstring: "use-wstring" }, { "const-style": "east-const" }, - { boost: "false" } + { boost: "false" }, ], - sourceFiles: ["src/language/CPlusPlus.ts"] + sourceFiles: ["src/language/CPlusPlus/index.ts"], }; export const ElmLanguage: Language = { @@ -573,7 +634,7 @@ export const ElmLanguage: Language = { "be234.json", "c3303.json", "e8b04.json", - "f6a65.json" + "f6a65.json", ], allowMissingNull: false, features: ["enum", "union", "no-defaults"], @@ -589,7 +650,7 @@ export const ElmLanguage: Language = { "bug790.json", "list.json", "nst-test-suite.json", - "keywords.json" // stack overflow + "keywords.json", // stack overflow ], skipMiscJSON: false, skipSchema: [ @@ -601,11 +662,11 @@ export const ElmLanguage: Language = { "postman-collection.schema", // recursion "vega-lite.schema", // recursion "simple-ref.schema", // recursion - "keyword-unions.schema" // can't handle "hasOwnProperty" for some reason + "keyword-unions.schema", // can't handle "hasOwnProperty" for some reason ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/Elm.ts"] + sourceFiles: ["src/language/Elm/index.ts"], }; export const SwiftLanguage: Language = { @@ -650,7 +711,7 @@ export const SwiftLanguage: Language = { "f6a65.json", // date-time issues "fcca3.json", "f82d9.json", - "bug863.json" // Unable to resolve reserved keyword use, "description" + "bug863.json", // Unable to resolve reserved keyword use, "description" ], allowMissingNull: true, features: ["enum", "union", "no-defaults", "date-time"], @@ -663,7 +724,7 @@ export const SwiftLanguage: Language = { "blns-object.json", // Doesn't seem to work on Linux, works on MacOS "nst-test-suite.json", - "null-safe.json" + "null-safe.json", ], skipMiscJSON: false, skipSchema: [ @@ -679,7 +740,8 @@ export const SwiftLanguage: Language = { "date-time.schema", "class-with-additional.schema", "class-map-union.schema", - "vega-lite.schema" + "vega-lite.schema", + "top-level-primitive.schema", ], rendererOptions: { "support-linux": "true" }, quickTestRendererOptions: [ @@ -690,9 +752,9 @@ export const SwiftLanguage: Language = { { "access-level": "internal" }, { "access-level": "public" }, { protocol: "equatable" }, - ["simple-object.json", { protocol: "hashable" }] + ["simple-object.json", { protocol: "hashable" }], ], - sourceFiles: ["src/language/Swift.ts"] + sourceFiles: ["src/language/Swift/index.ts"], }; export const ObjectiveCLanguage: Language = { @@ -724,13 +786,13 @@ export const ObjectiveCLanguage: Language = { // Could not convert JSON to model: Error Domain=JSONSerialization Code=-1 "(null)" UserInfo={exception=-[NSNull countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x7fff807b6ea0} "combinations2.json", "combinations3.json", - "combinations4.json" + "combinations4.json", ], skipMiscJSON: false, skipSchema: [], rendererOptions: { functions: "true" }, quickTestRendererOptions: [], - sourceFiles: ["src/language/Objective-C.ts"] + sourceFiles: ["src/language/Objective-C/index.ts"], }; export const TypeScriptLanguage: Language = { @@ -756,14 +818,14 @@ export const TypeScriptLanguage: Language = { "c8c7e.json", "cda6c.json", "e53b5.json", - "e8b04.json" + "e8b04.json", ], allowMissingNull: false, features: ["enum", "union", "no-defaults", "strict-optional", "date-time"], output: "TopLevel.ts", topLevel: "TopLevel", skipJSON: [ - "7681c.json" // year 0 is out of range + "7681c.json", // year 0 is out of range ], skipMiscJSON: false, skipSchema: ["keyword-unions.schema"], // can't handle "constructor" property @@ -775,9 +837,10 @@ export const TypeScriptLanguage: Language = { { "declare-unions": "true" }, ["pokedex.json", { "prefer-types": "true" }], { "acronym-style": "pascal" }, - { converters: "all-objects" } + { converters: "all-objects" }, + { readonly: "true" }, ], - sourceFiles: ["src/language/TypeScript.ts"] + sourceFiles: ["src/language/TypeScript/index.ts"], }; export const JavaScriptLanguage: Language = { @@ -794,7 +857,7 @@ export const JavaScriptLanguage: Language = { output: "TopLevel.js", topLevel: "TopLevel", skipJSON: [ - "7681c.json" // year 0 is out of range + "7681c.json", // year 0 is out of range ], skipMiscJSON: false, skipSchema: ["keyword-unions.schema"], // can't handle "constructor" property @@ -802,9 +865,9 @@ export const JavaScriptLanguage: Language = { quickTestRendererOptions: [ { "runtime-typecheck": "false" }, { "runtime-typecheck-ignore-unknown-properties": "true" }, - { converters: "top-level" } + { converters: "top-level" }, ], - sourceFiles: ["src/language/JavaScript.ts"] + sourceFiles: ["src/language/JavaScript/index.ts"], }; export const JavaScriptPropTypesLanguage: Language = { @@ -826,7 +889,7 @@ export const JavaScriptPropTypesLanguage: Language = { "bug790.json", // renderer does not support recursion "recursive.json", // renderer does not support recursion "spotify-album.json", // renderer does not support recursion - "76ae1.json" // renderer does not support recursion + "76ae1.json", // renderer does not support recursion ], skipSchema: [], skipMiscJSON: false, @@ -834,9 +897,9 @@ export const JavaScriptPropTypesLanguage: Language = { quickTestRendererOptions: [ { "runtime-typecheck": "false" }, { "runtime-typecheck-ignore-unknown-properties": "true" }, - { converters: "top-level" } + { converters: "top-level" }, ], - sourceFiles: ["src/Language/JavaScriptPropTypes.ts"] + sourceFiles: ["src/language/JavaScriptPropTypes/index.ts"], }; export const FlowLanguage: Language = { @@ -852,20 +915,20 @@ export const FlowLanguage: Language = { output: "TopLevel.js", topLevel: "TopLevel", skipJSON: [ - "7681c.json" // year 0 is out of range + "7681c.json", // year 0 is out of range ], skipMiscJSON: false, skipSchema: [ - "keyword-unions.schema" // can't handle "constructor" property + "keyword-unions.schema", // can't handle "constructor" property ], rendererOptions: { "explicit-unions": "yes" }, quickTestRendererOptions: [ { "runtime-typecheck": "false" }, { "runtime-typecheck-ignore-unknown-properties": "true" }, { "nice-property-names": "true" }, - { "declare-unions": "true" } + { "declare-unions": "true" }, ], - sourceFiles: ["src/language/Flow.ts"] + sourceFiles: ["src/language/Flow/index.ts"], }; export const Scala3Language: Language = { @@ -925,7 +988,7 @@ I havea no idea how to encode these tests correctly. "combinations3.json", "combinations4.json", "unions.json", - "nst-test-suite.json" + "nst-test-suite.json", ], skipSchema: [ // 12 skips @@ -940,12 +1003,12 @@ I havea no idea how to encode these tests correctly. "enum.schema", "class-with-additional.schema", "class-map-union.schema", - "keyword-unions.schema" + "keyword-unions.schema", ], skipMiscJSON: false, rendererOptions: { framework: "circe" }, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Scala3.ts"] + sourceFiles: ["src/language/Scala3/index.ts"], }; export const Smithy4sLanguage: Language = { @@ -1005,13 +1068,13 @@ I havea no idea how to encode these tests correctly. "combinations3.json", "combinations4.json", "unions.json", - "nst-test-suite.json" + "nst-test-suite.json", ], skipSchema: [], skipMiscJSON: false, rendererOptions: { framework: "just-types" }, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Smithy4s.ts"] + sourceFiles: ["src/language/Smithy4s/index.ts"], }; export const KotlinLanguage: Language = { @@ -1027,7 +1090,7 @@ export const KotlinLanguage: Language = { "keywords.json", // TODO Investigate these "34702.json", - "76ae1.json" + "76ae1.json", ], allowMissingNull: true, features: ["enum", "union", "no-defaults"], @@ -1065,7 +1128,7 @@ export const KotlinLanguage: Language = { // TODO Investigate these "af2d1.json", "32431.json", - "bug427.json" + "bug427.json", ], skipSchema: [ // Very weird - the types are correct, but it can (de)serialize the string, @@ -1090,12 +1153,13 @@ export const KotlinLanguage: Language = { "keyword-enum.schema", "keyword-unions.schema", // Klaxon does not support top-level primitives - "top-level-enum.schema" + "top-level-enum.schema", + "top-level-primitive.schema", ], skipMiscJSON: false, rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Kotlin.ts"] + sourceFiles: ["src/language/Kotlin/index.ts"], }; export const KotlinJacksonLanguage: Language = { @@ -1111,7 +1175,7 @@ export const KotlinJacksonLanguage: Language = { "keywords.json", // TODO Investigate these "34702.json", - "76ae1.json" + "76ae1.json", ], allowMissingNull: true, features: ["enum", "union", "no-defaults"], @@ -1148,7 +1212,7 @@ export const KotlinJacksonLanguage: Language = { // TODO Investigate these "af2d1.json", "32431.json", - "bug427.json" + "bug427.json", ], skipSchema: [ // Very weird - the types are correct, but it can (de)serialize the string, @@ -1173,12 +1237,13 @@ export const KotlinJacksonLanguage: Language = { "keyword-enum.schema", "keyword-unions.schema", // Klaxon does not support top-level primitives - "top-level-enum.schema" + "top-level-enum.schema", + "top-level-primitive.schema", ], skipMiscJSON: false, rendererOptions: { framework: "jackson" }, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Kotlin.ts"] + sourceFiles: ["src/language/Kotlin/index.ts"], }; export const DartLanguage: Language = { @@ -1208,7 +1273,7 @@ export const DartLanguage: Language = { "us-senators.json", "0a91a.json", "github-events.json", - "keywords.json" + "keywords.json", ], skipSchema: [ "enum-with-null.schema", @@ -1223,12 +1288,12 @@ export const DartLanguage: Language = { "simple-ref.schema", "keyword-unions.schema", "ref-remote.schema", - "uuid.schema" + "uuid.schema", ], skipMiscJSON: true, rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Dart.ts"] + sourceFiles: ["src/language/Dart/index.ts"], }; export const PikeLanguage: Language = { @@ -1264,7 +1329,7 @@ export const PikeLanguage: Language = { "d23d5.json", "dc44f.json", "dec3a.json", - "f22f5.json" + "f22f5.json", ], skipMiscJSON: false, skipSchema: [ @@ -1277,11 +1342,11 @@ export const PikeLanguage: Language = { "class-with-additional.schema", "multi-type-enum.schema", "class-map-union.schema", - "implicit-class-array-union.schema" + "implicit-class-array-union.schema", ], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Pike.ts"] + sourceFiles: ["src/language/Pike/index.ts"], }; export const HaskellLanguage: Language = { @@ -1308,7 +1373,7 @@ export const HaskellLanguage: Language = { "76ae1.json", "af2d1.json", "be234.json", - "e8b04.json" + "e8b04.json", ], allowMissingNull: false, features: ["enum", "union", "no-defaults"], @@ -1351,7 +1416,7 @@ export const HaskellLanguage: Language = { "recursive.json", "bug427.json", "nst-test-suite.json", - "keywords.json" + "keywords.json", ], skipMiscJSON: false, skipSchema: [ @@ -1366,17 +1431,17 @@ export const HaskellLanguage: Language = { "keyword-unions.schema", "optional-any.schema", "required.schema", - "required-non-properties.schema" + "required-non-properties.schema", ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/Haskell.ts"] + sourceFiles: ["src/language/Haskell/index.ts"], }; export const PHPLanguage: Language = { name: "php", base: "test/fixtures/php", - runCommand: sample => `php main.php \"${sample}\"`, + runCommand: (sample) => `php main.php \"${sample}\"`, diffViaSchema: false, skipDiffViaSchema: [], allowMissingNull: true, @@ -1388,7 +1453,7 @@ export const PHPLanguage: Language = { skipSchema: [], rendererOptions: {}, quickTestRendererOptions: [], - sourceFiles: ["src/Language/Php.ts"] + sourceFiles: ["src/language/Php/index.ts"], }; export const TypeScriptZodLanguage: Language = { @@ -1422,7 +1487,7 @@ export const TypeScriptZodLanguage: Language = { "76ae1.json", "af2d1.json", "be234.json", - "e8b04.json" + "e8b04.json", ], allowMissingNull: false, features: ["enum", "union", "no-defaults", "date-time"], @@ -1487,7 +1552,7 @@ export const TypeScriptZodLanguage: Language = { "keywords.json", "ed095.json", "7681c.json", - "32d5c.json" + "32d5c.json", ], skipMiscJSON: false, skipSchema: [ @@ -1502,11 +1567,11 @@ export const TypeScriptZodLanguage: Language = { "keyword-unions.schema", "optional-any.schema", "required.schema", - "required-non-properties.schema" + "required-non-properties.schema", ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/TypeScriptZod.ts"] + sourceFiles: ["src/language/TypeScriptZod/index.ts"], }; export const TypeScriptEffectSchemaLanguage: Language = { @@ -1540,7 +1605,7 @@ export const TypeScriptEffectSchemaLanguage: Language = { "76ae1.json", "af2d1.json", "be234.json", - "e8b04.json" + "e8b04.json", ], allowMissingNull: false, features: ["enum", "union", "no-defaults"], @@ -1603,7 +1668,7 @@ export const TypeScriptEffectSchemaLanguage: Language = { "bug427.json", "nst-test-suite.json", "keywords.json", - "ed095.json" + "ed095.json", ], skipMiscJSON: false, skipSchema: [ @@ -1618,9 +1683,70 @@ export const TypeScriptEffectSchemaLanguage: Language = { "keyword-unions.schema", "optional-any.schema", "required.schema", - "required-non-properties.schema" + "required-non-properties.schema", ], rendererOptions: {}, quickTestRendererOptions: [{ "array-type": "list" }], - sourceFiles: ["src/language/TypeScriptEffectSchema.ts"] + sourceFiles: ["src/language/TypeScriptEffectSchema/index.ts"], +}; + +export const ElixirLanguage: Language = { + name: "elixir", + base: "test/fixtures/elixir", + setupCommand: "mix deps.get", + compileCommand: "mix compile", + runCommand(sample: string) { + return `mix run main.exs "${sample}"`; + }, + diffViaSchema: true, + skipDiffViaSchema: [ + "e53b5.json", + "cda6c.json", + "f22f5.json", + "e8b04.json", + "c8c7e.json", + "be234.json", + "ae7f0.json", + "8592b.json", + "7fbfb.json", + "76ae1.json", + "6de06.json", + "4d6fb.json", + "34702.json", + "2df80.json", + "29f47.json", + "27332.json", + "00c36.json", + "bug863.json", + "bug427.json", + "keywords.json", + "kitchen-sink.json", + "reddit.json", + ], + allowMissingNull: false, + features: ["enum", "no-defaults", "strict-optional"], + output: "QuickType.ex", + topLevel: "TopLevel", + skipJSON: [ + // Some field names are too long to be expressed as atoms and some contain invalid characters. + "blns-object.json", + ], + skipMiscJSON: false, + skipSchema: [ + // The error occurs because a guard clause that references TopLevel is compiled before TopLevel itself. To fix this, put + // TopLevel before Bar, but this doesn't address the actual problem if for example a pattern match to Bar was in TopLevel. + "mutually-recursive.schema", + + // Struct keys cannot be enforced at runtime in Elixir and their values will just be set to null. + "strict-optional.schema", + "required.schema", + "intersection.schema", + + // The test incorrectly succeeds due to the emitter being permissive for unions that contain only primitives. A future enhancement + // for the Elixir emitter could be a user-controlled 'strict' mode that pattern matches even on unions of only primitive types. + "go-schema-pattern-properties.schema", + ], + rendererOptions: {}, + quickTestRendererOptions: [], + sourceFiles: ["src/language/Elixir/index.ts"], }; diff --git a/test/lib/deepEquals.ts b/test/lib/deepEquals.ts index 0561b76bf..eaeb1209a 100644 --- a/test/lib/deepEquals.ts +++ b/test/lib/deepEquals.ts @@ -1,6 +1,6 @@ import moment from "moment"; -import { Moment } from "moment"; -import { ComparisonRelaxations } from "../utils"; +import type { Moment } from "moment"; +import type { ComparisonRelaxations } from "../utils"; function pathToString(path: string[]): string { return "." + path.join("."); @@ -37,7 +37,7 @@ export default function deepEquals( y: any, assumeStringsEqual: boolean, relax: ComparisonRelaxations, - path: string[] = [] + path: string[] = [], ): boolean { // remember that NaN === NaN returns false // and isNaN(undefined) returns true @@ -64,23 +64,35 @@ export default function deepEquals( if (assumeStringsEqual || x === y) return true; const [xMoment, isTime] = tryParseMoment(x); const [yMoment] = tryParseMoment(y); - if (xMoment !== undefined && yMoment !== undefined && momentsEqual(xMoment, yMoment, isTime)) { + if ( + xMoment !== undefined && + yMoment !== undefined && + momentsEqual(xMoment, yMoment, isTime) + ) { return true; } console.error( - `Strings not equal at path ${pathToString(path)}: ${JSON.stringify(x)} !== ${JSON.stringify(y)}.` + `Strings not equal at path ${pathToString(path)}: ${JSON.stringify(x)} !== ${JSON.stringify(y)}.`, ); return false; } - if (!!relax.allowStringifiedIntegers && typeof x === "string" && typeof y === "number") { + if ( + !!relax.allowStringifiedIntegers && + typeof x === "string" && + typeof y === "number" + ) { if (x === y.toString()) return true; - console.error(`String and number not equal at path ${pathToString(path)}.`); + console.error( + `String and number not equal at path ${pathToString(path)}.`, + ); return false; } if (x instanceof String && y instanceof String) { if (x.toString() === y.toString()) return true; - console.error(`Number or string not equal at path ${pathToString(path)}.`); + console.error( + `Number or string not equal at path ${pathToString(path)}.`, + ); return false; } @@ -96,7 +108,7 @@ export default function deepEquals( console.error( `Not the same constructor at path ${pathToString(path)}: should be ${x.constructor} but is ${ y.constructor - }.` + }.`, ); return false; } @@ -108,7 +120,9 @@ export default function deepEquals( if (Array.isArray(x)) { if (x.length !== y.length) { - console.error(`Arrays don't have the same length at path ${pathToString(path)}.`); + console.error( + `Arrays don't have the same length at path ${pathToString(path)}.`, + ); return false; } for (let i = 0; i < x.length; i++) { @@ -131,7 +145,9 @@ export default function deepEquals( // so long as they're null. if (xKeys.indexOf(p) < 0) { if (y[p] !== null) { - console.error(`Non-null property ${p} is not expected at path ${pathToString(path)}.`); + console.error( + `Non-null property ${p} is not expected at path ${pathToString(path)}.`, + ); return false; } } @@ -142,7 +158,9 @@ export default function deepEquals( if (!!relax.allowMissingNull && x[p] === null) { continue; } - console.error(`Expected property ${p} not found at path ${pathToString(path)}.`); + console.error( + `Expected property ${p} not found at path ${pathToString(path)}.`, + ); return false; } diff --git a/test/lib/multicore.ts b/test/lib/multicore.ts index 78fe2de60..117f28010 100644 --- a/test/lib/multicore.ts +++ b/test/lib/multicore.ts @@ -19,21 +19,23 @@ function randomPick(arr: T[]): T { function guys(n: number): string { return _.range(n) - .map(_i => randomPick(WORKERS)) + .map((_i) => randomPick(WORKERS)) .join(" "); } -export async function inParallel(args: ParallelArgs) { - let { queue } = args; - let items = queue.map((item, i) => { +export async function inParallel( + args: ParallelArgs, +) { + const { queue } = args; + const items = queue.map((item, i) => { return { item, i }; }); if (cluster.isPrimary) { - let { setup, workers, map } = args; + const { setup, workers, map } = args; await setup(); - cluster.on("message", worker => { + cluster.on("message", (worker) => { const msg = items.pop(); if (msg !== undefined) { worker.send(msg); @@ -57,30 +59,30 @@ export async function inParallel(args: ParallelArgs + _.range(workers).forEach((i) => cluster.fork({ worker: i, // https://github.com/TypeStrong/ts-node/issues/367 - TS_NODE_PROJECT: "test/tsconfig.json" - }) + TS_NODE_PROJECT: "test/tsconfig.json", + }), ); } } else { // Setup a worker - let { map } = args; + const { map } = args; // master sends a { fixtureName, sample } to run process.on("message", async ({ item, i }) => { - (process.send as any)({ - result: await map(item, i) + process.send?.({ + result: await map(item, i), }); }); // Ask master for work - (process.send as any)("ready"); + process.send?.("ready"); } } diff --git a/test/test.ts b/test/test.ts index e51058f76..f6015eafa 100755 --- a/test/test.ts +++ b/test/test.ts @@ -2,12 +2,12 @@ import * as os from "os"; import * as _ from "lodash"; import { inParallel } from "./lib/multicore"; -import { execAsync, Sample } from "./utils"; -import { Fixture, allFixtures } from "./fixtures"; +import { execAsync, type Sample } from "./utils"; +import { type Fixture, allFixtures } from "./fixtures"; import { affectedFixtures, divideParallelJobs } from "./buildkite"; const exit = require("exit"); -const CPUs = parseInt(process.env.CPUs || "0", 10) || os.cpus().length; +const CPUs = Number.parseInt(process.env.CPUs || "0", 10) || os.cpus().length; ////////////////////////////////////// // Test driver @@ -20,24 +20,36 @@ async function main(sources: string[]) { const fixturesFromCmdline = process.env.FIXTURE; if (fixturesFromCmdline) { const fixtureNames = fixturesFromCmdline.split(","); - fixtures = _.filter(fixtures, fixture => _.some(fixtureNames, name => fixture.runForName(name))); + fixtures = _.filter(fixtures, (fixture) => + _.some(fixtureNames, (name) => fixture.runForName(name)), + ); } if (allFixtures.length !== fixtures.length) { - console.error(`* Running a subset of fixtures: ${fixtures.map(f => f.name).join(", ")}`); + console.error( + `* Running a subset of fixtures: ${fixtures.map((f) => f.name).join(", ")}`, + ); } // Get an array of all { sample, fixtureName } objects we'll run. // We can't just put the fixture in there because these WorkItems // will be sent in a message, removing all code. - const samples = _.map(fixtures, fixture => ({ + const samples = _.map(fixtures, (fixture) => ({ fixtureName: fixture.name, - samples: fixture.getSamples(sources) + samples: fixture.getSamples(sources), })); - const priority = _.flatMap(samples, x => - _.map(x.samples.priority, s => ({ fixtureName: x.fixtureName, sample: s })) + const priority = _.flatMap(samples, (x) => + _.map(x.samples.priority, (s) => ({ + fixtureName: x.fixtureName, + sample: s, + })), + ); + const others = _.flatMap(samples, (x) => + _.map(x.samples.others, (s) => ({ + fixtureName: x.fixtureName, + sample: s, + })), ); - const others = _.flatMap(samples, x => _.map(x.samples.others, s => ({ fixtureName: x.fixtureName, sample: s }))); const tests = divideParallelJobs(_.concat(priority, others)); @@ -46,7 +58,9 @@ async function main(sources: string[]) { workers: CPUs, setup: async () => { - console.error(`* Running ${tests.length} tests between ${fixtures.length} fixtures`); + console.error( + `* Running ${tests.length} tests between ${fixtures.length} fixtures`, + ); for (const fixture of fixtures) { await execAsync(`rm -rf test/runs`); @@ -57,19 +71,19 @@ async function main(sources: string[]) { }, map: async ({ sample, fixtureName }: WorkItem, index) => { - let fixture = _.find(fixtures, { name: fixtureName }) as Fixture; + const fixture = _.find(fixtures, { name: fixtureName }) as Fixture; try { await fixture.runWithSample(sample, index, tests.length); } catch (e) { console.trace(e); exit(1); } - } + }, }); } // skip 2 `node` args -main(process.argv.slice(2)).catch(reason => { +main(process.argv.slice(2)).catch((reason) => { console.error(reason); process.exit(1); }); diff --git a/test/tsconfig.json b/test/tsconfig.json index 26618760c..a042b47f7 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -4,7 +4,8 @@ "strict": true, "alwaysStrict": true, "noUnusedLocals": true, - "noUnusedParameters": true + "noUnusedParameters": true, + "resolveJsonModule": true }, "include": ["*.ts", "../dist/*.js", "../dist/*.d.ts"] } diff --git a/test/utils.ts b/test/utils.ts index f2fa81fe9..b532a2e8f 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -1,16 +1,19 @@ -import * as fs from "fs"; -import * as path from "path"; +import * as fs from "node:fs"; +import * as path from "node:path"; import * as _ from "lodash"; import * as shell from "shelljs"; -import { main as quicktype_, CLIOptions } from "../src"; -import { RendererOptions } from "quicktype-core"; -import * as languages from "./languages"; +import { main as quicktype_, type CLIOptions } from "../src"; +import type { RendererOptions } from "quicktype-core"; +import type * as languages from "./languages"; import deepEquals from "./lib/deepEquals"; import chalk from "chalk"; -const strictDeepEquals: (x: any, y: any) => boolean = require("deep-equal"); +const strictDeepEquals: ( + x: unknown, + y: unknown, +) => boolean = require("deep-equal"); const DEBUG = process.env.DEBUG !== undefined; const ASSUME_STRINGS_EQUAL = process.env.ASSUME_STRINGS_EQUAL !== undefined; @@ -22,7 +25,7 @@ export function debug(x: T): T { return x; } -export function failWith(message: string, obj: { [key: string]: any }): never { +export function failWith(message: string, obj: Record): never { obj.cwd = process.cwd(); console.error(chalk.red(message)); console.error(chalk.red(JSON.stringify(obj, null, " "))); @@ -44,24 +47,25 @@ export function callAndExpectFailure(message: string, f: () => T): void { } catch { return; } - return failWith(message, { result }); + + failWith(message, { result }); } export function exec( s: string, env: NodeJS.ProcessEnv | undefined, - printFailure = true + printFailure = true, ): { stdout: string; code: number } { debug(s); if (env === undefined) { env = process.env; } - const result = shell.exec(s, { silent: !DEBUG, env }) as any; + const result = shell.exec(s, { silent: !DEBUG, env }); if (result.code !== 0) { const failureObj = { command: s, - code: result.code + code: result.code, }; if (!printFailure) { throw failureObj; @@ -74,7 +78,10 @@ export function exec( return result; } -export function execAsync(s: string, opts: { silent: boolean } = { silent: !DEBUG }) { +export function execAsync( + s: string, + opts: { silent: boolean } = { silent: !DEBUG }, +) { return new Promise<{ stdout: string; code: number }>((resolve, reject) => { debug(s); shell.exec(s, opts, (code, stdout, stderr) => { @@ -89,9 +96,9 @@ export function execAsync(s: string, opts: { silent: boolean } = { silent: !DEBU } async function time(work: () => Promise): Promise<[T, number]> { - let start = +new Date(); - let result = await work(); - let end = +new Date(); + const start = +new Date(); + const result = await work(); + const end = +new Date(); return [result, end - start]; } @@ -99,7 +106,9 @@ async function time(work: () => Promise): Promise<[T, number]> { export function mkdirs(dir: string): void { const components = dir.split(path.sep); if (components.length === 0) { - throw new Error("mkdirs must be called with at least one path component"); + throw new Error( + "mkdirs must be called with at least one path component", + ); } let soFar: string; if (components[0].length === 0) { @@ -132,7 +141,7 @@ export async function quicktypeForLanguage( sourceLanguage: string, alphabetizeProperties: boolean, additionalRendererOptions: RendererOptions, - graphqlSchema?: string + graphqlSchema?: string, ) { try { await quicktype({ @@ -143,12 +152,16 @@ export async function quicktypeForLanguage( graphqlSchema, topLevel: language.topLevel, alphabetizeProperties, - rendererOptions: _.merge({}, language.rendererOptions, additionalRendererOptions), + rendererOptions: _.merge( + {}, + language.rendererOptions, + additionalRendererOptions, + ), quiet: true, telemetry: "disable", // GraphQL input can leave unreachable types in the graph, which means // their provenance won't be propagated. It does that for non-nullables. - debug: graphqlSchema === undefined ? "provenance" : undefined + debug: graphqlSchema === undefined ? "provenance" : undefined, }); } catch (e) { failWith("quicktype threw an exception", { @@ -157,13 +170,13 @@ export async function quicktypeForLanguage( sourceFile, sourceLanguage, graphqlSchema, - additionalRendererOptions + additionalRendererOptions, }); } } export async function inDir(dir: string, work: () => Promise) { - let origin = process.cwd(); + const origin = process.cwd(); debug(`cd ${dir}`); process.chdir(dir); @@ -183,28 +196,33 @@ export interface Sample { } export function samplesFromPaths(paths: string[]): Sample[] { - return paths.map(p => ({ path: p, additionalRendererOptions: {}, saveOutput: true })); + return paths.map((p) => ({ + path: p, + additionalRendererOptions: {}, + saveOutput: true, + })); } export function samplesFromSources( sources: string[], prioritySamples: string[], miscSamples: string[], - extension: string + extension: string, ): { priority: Sample[]; others: Sample[] } { if (sources.length === 0) { return { priority: samplesFromPaths(prioritySamples), - others: samplesFromPaths(miscSamples) + others: samplesFromPaths(miscSamples), }; - } else if (sources.length === 1 && fs.lstatSync(sources[0]).isDirectory()) { + } + if (sources.length === 1 && fs.lstatSync(sources[0]).isDirectory()) { return { priority: samplesFromPaths(testsInDir(sources[0], extension)), - others: [] + others: [], }; - } else { - return { priority: samplesFromPaths(sources), others: [] }; } + + return { priority: samplesFromPaths(sources), others: [] }; } export type ComparisonRelaxations = { @@ -212,10 +230,12 @@ export type ComparisonRelaxations = { allowStringifiedIntegers?: boolean; }; -export type FileOrCommand = { file: string } | { command: string; env: NodeJS.ProcessEnv }; +export type FileOrCommand = + | { file: string } + | { command: string; env: NodeJS.ProcessEnv }; function fileOrCommandIsFile(foc: FileOrCommand): foc is { file: string } { - return (foc as any).file !== undefined; + return "file" in foc && foc.file !== undefined; } export type ComparisonArgs = ComparisonRelaxations & { @@ -231,24 +251,34 @@ export function compareJsonFileToJson(args: ComparisonArgs) { const { given } = args; const jsonString = fileOrCommandIsFile(given) - ? callAndReportFailure("Could not read JSON output file", () => fs.readFileSync(given.file, "utf8")) - : callAndReportFailure("Could not run command for JSON output", () => exec(given.command, given.env).stdout); + ? callAndReportFailure("Could not read JSON output file", () => + fs.readFileSync(given.file, "utf8"), + ) + : callAndReportFailure( + "Could not run command for JSON output", + () => exec(given.command, given.env).stdout, + ); - const givenJSON = callAndReportFailure("Could not parse output JSON", () => JSON.parse(jsonString)); - const expectedJSON = callAndReportFailure("Could not read or parse expected JSON file", () => - JSON.parse(fs.readFileSync(expectedFile, "utf8")) + const givenJSON = callAndReportFailure("Could not parse output JSON", () => + JSON.parse(jsonString), + ); + const expectedJSON = callAndReportFailure( + "Could not read or parse expected JSON file", + () => JSON.parse(fs.readFileSync(expectedFile, "utf8")), ); - let jsonAreEqual = strict - ? callAndReportFailure("Failed to strictly compare objects", () => strictDeepEquals(givenJSON, expectedJSON)) + const jsonAreEqual = strict + ? callAndReportFailure("Failed to strictly compare objects", () => + strictDeepEquals(givenJSON, expectedJSON), + ) : callAndReportFailure("Failed to compare objects.", () => - deepEquals(expectedJSON, givenJSON, ASSUME_STRINGS_EQUAL, args) + deepEquals(expectedJSON, givenJSON, ASSUME_STRINGS_EQUAL, args), ); if (!jsonAreEqual) { failWith("Error: Output is not equivalent to input.", { expectedFile, - given + given, }); } } diff --git a/tsconfig.json b/tsconfig.json index 60bab643b..4f1446d5e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,8 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "outDir": "dist", - "baseUrl": "src" + "baseUrl": "src", + "resolveJsonModule": true }, "include": ["src"] } diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 6bfd49e76..000000000 --- a/tslint.json +++ /dev/null @@ -1,88 +0,0 @@ -{ - "rules": { - "await-promise": true, - "promise-function-async": true, - "no-floating-promises": true, - "align": [true, "parameters", "statements"], - "ban": false, - "class-name": true, - "comment-format": [true, "check-space"], - "curly": false, - "eofline": false, - "forin": true, - "indent": [true, "spaces", 4], - "interface-name": [true, "never-prefix"], - "jsdoc-format": true, - "jsx-no-lambda": false, - "jsx-no-multiline-js": false, - "label-position": true, - "max-line-length": false, - "member-ordering": [true, "static-before-instance"], - - "no-any": false, - - "no-arg": true, - "no-bitwise": false, - "no-console": [ - false, - "log", - "error", - "debug", - "info", - "time", - "timeEnd", - "trace" - ], - "no-consecutive-blank-lines": true, - "no-construct": true, - "no-debugger": true, - "no-duplicate-variable": true, - "no-empty": [true, "allow-empty-catch"], - "no-eval": true, - "no-shadowed-variable": true, - "no-string-literal": false, - "no-switch-case-fall-through": true, - "no-trailing-whitespace": false, - "no-unsafe-any": false, - "no-unused-expression": true, - "no-use-before-declare": false, - "no-unused-variable": true, - "no-var-keyword": true, - "no-void-expression": false, - "strict-boolean-expressions": true, - "one-line": [ - true, - "check-catch", - "check-else", - "check-open-brace", - "check-whitespace" - ], - "quotemark": [true, "double", "avoid-escape"], - "radix": true, - "semicolon": [true, "always", "ignore-bound-class-methods"], - "switch-default": true, - - "trailing-comma": false, - - "triple-equals": [true, "allow-null-check"], - "typedef": [true, "parameter", "property-declaration"], - "typedef-whitespace": [ - true, - { - "call-signature": "nospace", - "index-signature": "nospace", - "parameter": "nospace", - "property-declaration": "nospace", - "variable-declaration": "nospace" - } - ], - "variable-name": [ - true, - "ban-keywords", - "check-format", - "allow-leading-underscore", - "allow-pascal-case" - ], - "whitespace": [false] - } -}