Showing preview only (4,816K chars total). Download the full file or copy to clipboard to get everything.
Repository: Netflix/falcor
Branch: master
Commit: 39d64776cf9d
Files: 367
Total size: 4.5 MB
Directory structure:
gitextract_2ph5kury/
├── .bithoundrc
├── .editorconfig
├── .eslintrc
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── docs.yml
├── .gitignore
├── .npmignore
├── .npmrc
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.txt
├── MIGRATIONS.md
├── OSSMETADATA
├── README.md
├── all.js
├── authors.txt
├── bower.json
├── browser.js
├── build/
│ ├── deploy-ghpages.sh
│ ├── falcor-jsdoc-template/
│ │ ├── README.md
│ │ ├── publish.js
│ │ └── tmpl/
│ │ ├── augments.tmpl
│ │ ├── container.tmpl
│ │ ├── details.tmpl
│ │ ├── example.tmpl
│ │ ├── examples.tmpl
│ │ ├── exceptions.tmpl
│ │ ├── layout.tmpl
│ │ ├── mainpage.tmpl
│ │ ├── members.tmpl
│ │ ├── method.tmpl
│ │ ├── navigation-subgroup.tmpl
│ │ ├── navigation.tmpl
│ │ ├── params.tmpl
│ │ ├── properties.tmpl
│ │ ├── returns.tmpl
│ │ ├── source.tmpl
│ │ ├── tutorial.tmpl
│ │ └── type.tmpl
│ ├── gulp-build.js
│ ├── gulp-clean.js
│ ├── gulp-perf.js
│ └── jsdoc.json
├── conf.json
├── deployKey.enc
├── dist/
│ ├── falcor.all.js
│ └── falcor.browser.js
├── doc/
│ ├── DataSource.html
│ ├── FromEsObserverAdapter.html
│ ├── Model.html
│ ├── Model.js.html
│ ├── ModelResponse.html
│ ├── ModelResponseObserver.html
│ ├── Observable.html
│ ├── Subscription.html
│ ├── ToEsSubscriptionAdapter.html
│ ├── get_getCache.js.html
│ ├── global.html
│ ├── index.html
│ ├── index.js.html
│ ├── internal_index.js.html
│ ├── invalidate_invalidatePathMaps.js.html
│ ├── invalidate_invalidatePathSets.js.html
│ ├── request_GetRequestV2.js.html
│ ├── request_RequestQueueV2.js.html
│ ├── request_complement.js.html
│ ├── response_AssignableDisposable.js.html
│ ├── response_ModelResponse.js.html
│ ├── response_ModelResponseObserver.js.html
│ ├── response_get_GetResponse.js.html
│ ├── response_set_SetResponse.js.html
│ ├── response_set_setGroupsIntoCache.js.html
│ ├── response_set_setRequestCycle.js.html
│ ├── set_setJSONGraphs.js.html
│ ├── set_setPathMaps.js.html
│ ├── set_setPathValues.js.html
│ ├── support_reconstructPath.js.html
│ ├── toEsObservable.js.html
│ ├── typedefs_Atom.js.html
│ ├── typedefs_DataSource.js.html
│ ├── typedefs_JSONEnvelope.js.html
│ ├── typedefs_JSONGraph.js.html
│ ├── typedefs_JSONGraphEnvelope.js.html
│ ├── typedefs_Key.js.html
│ ├── typedefs_KeySet.js.html
│ ├── typedefs_Observable.js.html
│ ├── typedefs_Path.js.html
│ ├── typedefs_PathSet.js.html
│ ├── typedefs_PathValue.js.html
│ └── typedefs_Range.js.html
├── examples/
│ └── datasource/
│ └── webWorkerSource.js
├── gulpfile.js
├── lib/
│ ├── Model.js
│ ├── ModelDataSourceAdapter.js
│ ├── ModelRoot.js
│ ├── deref/
│ │ ├── hasValidParentReference.js
│ │ ├── index.js
│ │ └── sync.js
│ ├── errors/
│ │ ├── BoundJSONGraphModelError.js
│ │ ├── InvalidDerefInputError.js
│ │ ├── InvalidModelError.js
│ │ ├── InvalidSourceError.js
│ │ ├── MaxRetryExceededError.js
│ │ ├── NullInPathError.js
│ │ └── applyErrorPrototype.js
│ ├── get/
│ │ ├── followReference.js
│ │ ├── get.js
│ │ ├── getBoundValue.js
│ │ ├── getCache.js
│ │ ├── getCachePosition.js
│ │ ├── getValue.js
│ │ ├── getValueSync.js
│ │ ├── getVersion.js
│ │ ├── index.js
│ │ ├── onError.js
│ │ ├── onMissing.js
│ │ ├── onValue.js
│ │ ├── onValueType.js
│ │ ├── sync.js
│ │ ├── util/
│ │ │ ├── clone.js
│ │ │ ├── isExpired.js
│ │ │ ├── isMaterialzed.js
│ │ │ └── isPathValue.js
│ │ └── walkPath.js
│ ├── index.js
│ ├── internal/
│ │ ├── absolutePath.js
│ │ ├── context.js
│ │ ├── head.js
│ │ ├── index.js
│ │ ├── invalidated.js
│ │ ├── key.js
│ │ ├── model-created.js
│ │ ├── next.js
│ │ ├── parent.js
│ │ ├── path.js
│ │ ├── prev.js
│ │ ├── privatePrefix.js
│ │ ├── ref-index.js
│ │ ├── ref.js
│ │ ├── refs-length.js
│ │ ├── reservedPrefix.js
│ │ ├── tail.js
│ │ └── version.js
│ ├── invalidate/
│ │ ├── invalidatePathMaps.js
│ │ └── invalidatePathSets.js
│ ├── lru/
│ │ ├── collect.js
│ │ ├── promote.js
│ │ └── splice.js
│ ├── request/
│ │ ├── GetRequestV2.js
│ │ ├── RequestQueueV2.js
│ │ ├── RequestTypes.js
│ │ ├── complement.js
│ │ ├── flushGetRequest.js
│ │ └── sendSetRequest.js
│ ├── response/
│ │ ├── AssignableDisposable.js
│ │ ├── CallResponse.js
│ │ ├── InvalidateResponse.js
│ │ ├── ModelResponse.js
│ │ ├── ModelResponseObserver.js
│ │ ├── get/
│ │ │ ├── GetResponse.js
│ │ │ ├── checkCacheAndReport.js
│ │ │ ├── getRequestCycle.js
│ │ │ ├── getWithPaths.js
│ │ │ ├── index.js
│ │ │ └── validInput.js
│ │ └── set/
│ │ ├── SetResponse.js
│ │ ├── index.js
│ │ ├── setGroupsIntoCache.js
│ │ ├── setRequestCycle.js
│ │ └── setValidInput.js
│ ├── schedulers/
│ │ ├── ASAPScheduler.js
│ │ ├── ImmediateScheduler.js
│ │ └── TimeoutScheduler.js
│ ├── set/
│ │ ├── index.js
│ │ ├── setJSONGraphs.js
│ │ ├── setPathMaps.js
│ │ ├── setPathValues.js
│ │ ├── setValue.js
│ │ └── sync.js
│ ├── support/
│ │ ├── array-flat-map.js
│ │ ├── clone.js
│ │ ├── createHardlink.js
│ │ ├── currentCacheVersion.js
│ │ ├── expireNode.js
│ │ ├── getExpires.js
│ │ ├── getSize.js
│ │ ├── getTimestamp.js
│ │ ├── getType.js
│ │ ├── hasOwn.js
│ │ ├── identity.js
│ │ ├── incrementVersion.js
│ │ ├── insertNode.js
│ │ ├── isAlreadyExpired.js
│ │ ├── isExpired.js
│ │ ├── isFunction.js
│ │ ├── isInternalKey.js
│ │ ├── isJSONEnvelope.js
│ │ ├── isJSONGraphEnvelope.js
│ │ ├── isObject.js
│ │ ├── isPathInvalidation.js
│ │ ├── isPathValue.js
│ │ ├── isPrimitive.js
│ │ ├── mergeJSONGraphNode.js
│ │ ├── mergeValueOrInsertBranch.js
│ │ ├── noop.js
│ │ ├── now.js
│ │ ├── reconstructPath.js
│ │ ├── removeNode.js
│ │ ├── removeNodeAndDescendants.js
│ │ ├── replaceNode.js
│ │ ├── transferBackReferences.js
│ │ ├── unlinkBackReferences.js
│ │ ├── unlinkForwardReference.js
│ │ ├── updateBackReferenceVersions.js
│ │ ├── updateNodeAncestors.js
│ │ ├── validateInput.js
│ │ └── wrapNode.js
│ ├── toEsObservable.js
│ ├── typedefs/
│ │ ├── Atom.js
│ │ ├── DataSource.js
│ │ ├── JSONEnvelope.js
│ │ ├── JSONGraph.js
│ │ ├── JSONGraphEnvelope.js
│ │ ├── Key.js
│ │ ├── KeySet.js
│ │ ├── Observable.js
│ │ ├── Path.js
│ │ ├── PathSet.js
│ │ ├── PathValue.js
│ │ └── Range.js
│ ├── types/
│ │ ├── atom.js
│ │ ├── error.js
│ │ └── ref.js
│ └── values/
│ ├── expires-never.js
│ └── expires-now.js
├── package.json
├── performance/
│ ├── README.md
│ ├── TriggerDataSource.js
│ ├── browser.js
│ ├── device.js
│ ├── formatter/
│ │ ├── CSVFormatter.js
│ │ └── CSVTransform.js
│ ├── karma.conf.js
│ ├── models/
│ │ ├── index.js
│ │ └── legacy/
│ │ ├── _.js
│ │ ├── _Cache.js
│ │ ├── index.js
│ │ └── macro/
│ │ └── _Falcor.js
│ ├── node.js
│ ├── reporters/
│ │ ├── browserTestReporter.js
│ │ ├── karmaBenchmarkCSVReporter.js
│ │ └── nodeTestReporter.js
│ ├── scripts/
│ │ └── transformCSV.js
│ ├── testRunner.js
│ └── tests/
│ ├── clone/
│ │ └── clone.perf.js
│ ├── deref/
│ │ └── index.js
│ ├── get/
│ │ ├── get.core.perf.js
│ │ ├── get.perf.js
│ │ ├── onValue.perf.js
│ │ └── walk.perf.js
│ ├── inMemoryCache.js
│ ├── lru/
│ │ └── index.js
│ ├── request/
│ │ └── request-queue.js
│ ├── set/
│ │ └── set.json-graph.perf.js
│ ├── standard.js
│ ├── testMerge.js
│ └── testSuite.js
├── server.js
├── test/
│ ├── .eslintrc.yaml
│ ├── CacheGenerator.js
│ ├── Model.spec.js
│ ├── cleanData.js
│ ├── data/
│ │ ├── Cache.js
│ │ ├── ErrorDataSource.js
│ │ ├── LocalDataSource.js
│ │ ├── ReducedCache.js
│ │ ├── asyncifyDataSource.js
│ │ └── expected/
│ │ ├── Bound.js
│ │ ├── Complex.js
│ │ ├── References.js
│ │ ├── Values.js
│ │ └── index.js
│ ├── falcor/
│ │ ├── call/
│ │ │ └── call.spec.js
│ │ ├── deref/
│ │ │ ├── deref.errors.spec.js
│ │ │ ├── deref.hasValidParentReference.spec.js
│ │ │ └── deref.spec.js
│ │ ├── error/
│ │ │ └── error.spec.js
│ │ ├── get/
│ │ │ ├── get.cache-only.spec.js
│ │ │ ├── get.cacheAsDataSource.spec.js
│ │ │ ├── get.clone.spec.js
│ │ │ ├── get.dataSource-and-bind.spec.js
│ │ │ ├── get.dataSource-and-cache.spec.js
│ │ │ ├── get.dataSource-only.spec.js
│ │ │ ├── get.gen.spec.js
│ │ │ ├── get.model.adapter.spec.js
│ │ │ └── get.pathSyntax.spec.js
│ │ ├── invalidate/
│ │ │ ├── invalidate.cache-only.spec.js
│ │ │ └── invalidate.change-handler.spec.js
│ │ ├── operations.spec.js
│ │ ├── schedulers/
│ │ │ └── schedulers.spec.js
│ │ └── set/
│ │ ├── set.cache-only.spec.js
│ │ ├── set.cacheAsDataSource-and-cache.spec.js
│ │ ├── set.change-handler.spec.js
│ │ ├── set.dataSource-and-bind.spec.js
│ │ ├── set.dataSource-and-cache.spec.js
│ │ ├── set.dataSource-only.spec.js
│ │ ├── set.pathSyntax.spec.js
│ │ └── set.setCache.spec.js
│ ├── get-core/
│ │ ├── deref.spec.js
│ │ ├── edges.spec.js
│ │ ├── errors.spec.js
│ │ ├── get.cache.spec.js
│ │ ├── missing.spec.js
│ │ ├── null.spec.js
│ │ ├── references.spec.js
│ │ └── values.spec.js
│ ├── getCoreRunner.js
│ ├── getTestRunner.js
│ ├── hardlink/
│ │ ├── hardlink.add.spec.js
│ │ └── hardlink.remove.spec.js
│ ├── integration/
│ │ ├── call.spec.js
│ │ ├── dedupe.spec.js
│ │ ├── express.spec.js
│ │ └── get.spec.js
│ ├── internal/
│ │ ├── ModelRoot.comparator.spec.js
│ │ ├── request/
│ │ │ ├── GetRequest.add.spec.js
│ │ │ ├── GetRequest.batch.spec.js
│ │ │ ├── GetRequest.spec.js
│ │ │ ├── RequestQueue.get.spec.js
│ │ │ └── complement.spec.js
│ │ └── sync/
│ │ └── _setValueSync.spec.js
│ ├── invalidate/
│ │ ├── invalidate.spec.js
│ │ ├── pathMaps.spec.js
│ │ └── pathSets.spec.js
│ ├── isAssertionError.js
│ ├── lru/
│ │ ├── lru.promote.get.spec.js
│ │ ├── lru.promote.set.spec.js
│ │ ├── lru.splice.expired.spec.js
│ │ └── lru.splice.overwrite.spec.js
│ ├── outputGenerator.js
│ ├── response/
│ │ └── ModelResponseObserver.spec.js
│ ├── set/
│ │ ├── edge-cases.spec.js
│ │ ├── jsonGraphs/
│ │ │ ├── atom.spec.js
│ │ │ ├── branch.spec.js
│ │ │ ├── expired.spec.js
│ │ │ ├── primitive.spec.js
│ │ │ └── reference.spec.js
│ │ ├── pathMaps/
│ │ │ ├── atom.spec.js
│ │ │ ├── branch.spec.js
│ │ │ ├── expired.spec.js
│ │ │ └── primitive.spec.js
│ │ ├── pathValues/
│ │ │ ├── atom.spec.js
│ │ │ ├── branch.spec.js
│ │ │ ├── expired.spec.js
│ │ │ └── primitive.spec.js
│ │ └── support/
│ │ ├── getModel.js
│ │ ├── jsonGraph.js
│ │ ├── jsonGraphEnvelope.js
│ │ ├── partial-cache.js
│ │ ├── pathMap.js
│ │ ├── pathMapEnvelope.js
│ │ ├── strip.js
│ │ └── whole-cache.js
│ ├── testRunner.js
│ ├── toObs.js
│ └── zipSpy.js
└── webpack.config.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .bithoundrc
================================================
{
"ignore": [
"**/node_modules/**",
"build/**",
"coverage/**",
"dist/**",
"macros/**",
"performance/**",
"test/**",
"gulpfile.js",
"server.js"
]
}
================================================
FILE: .editorconfig
================================================
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
insert_final_newline = false
trim_trailing_whitespace = false
================================================
FILE: .eslintrc
================================================
{
"env": {
"browser": false,
"node": true,
"es6": false
},
"rules": {
// possible errors
"comma-dangle": [ 2, "only-multiline" ],
"no-console": [ 2 ],
"no-constant-condition": [ 2 ],
"no-control-regex": [ 2 ],
"no-debugger": [ 2 ],
"no-dupe-args": [ 2 ],
"no-dupe-keys": [ 2 ],
"no-duplicate-case": [ 2 ],
"no-empty": [ 2 ],
"no-empty-character-class": [ 2 ],
"no-ex-assign": [ 2 ],
"no-extra-boolean-cast": [ 2 ],
"no-cond-assign": [ 2, "always" ],
"no-extra-semi": [ 2 ],
"no-func-assign": [ 2 ],
// this is for variable hoisting, not necessary if we use block scoped declarations
// "no-inner-declarations": [ 2, "both" ],
"no-invalid-regexp": [ 2 ],
"no-irregular-whitespace": [ 2 ],
"no-negated-in-lhs": [ 2 ],
// when IE8 dies
"no-reserved-keys": [ 0 ],
"no-regex-spaces": [ 2 ],
"no-sparse-arrays": [ 2 ],
"no-unreachable": [ 2 ],
"use-isnan": [ 2 ],
// should we enforce valid documentation comments?
// i.e., if you do documentation, do it right
// "valid-jsdoc": [ 2 ],
"valid-typeof": [ 2 ],
// best practices
"block-scoped-var": [ 2 ],
"consistent-return": [ 2 ],
"curly": [ 2 ],
"default-case": [ 2 ],
"dot-notation": [ 2, { "allowKeywords": true } ],
"eqeqeq": [ 2, "smart" ],
"guard-for-in": [ 2 ],
"no-alert": [ 2 ],
"no-caller": [ 2 ],
"no-div-regex": [ 2 ],
"no-eq-null": [ 0 ],
"no-eval": [ 2 ],
"no-extend-native": [ 2 ],
"no-extra-bind": [ 2 ],
"no-fallthrough": [ 2 ],
"no-floating-decimal": [ 2 ],
"no-implied-eval": [ 2 ],
"no-iterator": [ 2 ],
"no-labels": [ 0 ],
"no-lone-blocks": [ 2 ],
"no-loop-func": [ 2 ],
"no-multi-spaces": [ 2 ],
"no-native-reassign": [ 2 ],
"no-new": [ 2 ],
"no-new-func": [ 2 ],
"no-new-wrappers": [ 2 ],
"no-octal": [ 2 ],
"no-octal-escape": [ 2 ],
"no-param-reassign": [ 0 ],
"no-proto": [ 2 ],
"no-process-env": [ 2 ],
"no-redeclare": [ 2 ],
"no-return-assign": [ 2 ],
"no-script-url": [ 2 ],
"no-self-compare": [ 2 ],
"no-sequences": [ 2 ],
"no-throw-literal": [ 2 ],
"no-unused-expressions": [ 2 ],
"no-warning-comments": [ 0 ],
"no-with": [ 2 ],
"radix": [ 2 ],
"wrap-iife": [ 2 ],
"yoda": [ 0 ],
// strict mode
/*
"strict": [ 2, "global" ],
*/
// variables
"no-catch-shadow": [ 2 ],
"no-delete-var": [ 2 ],
"no-shadow": [ 2 ],
"no-shadow-restricted-names": [ 2 ],
"no-undef": [ 2 ],
"no-undef-init": [ 2 ],
"no-undefined": [ 0 ],
"no-unused-vars": [ 2, { "vars": "all", "args": "none" } ],
"no-use-before-define": [ 2, "nofunc" ],
// node.js
"handle-callback-err": [ 2, "^.*(e|E)rr" ],
"no-mixed-requires": [ 2 ],
"no-new-require": [ 2 ],
"no-path-concat": [ 2 ],
"no-process-exit": [ 0 ],
// ES6
"generator-star-spacing": [ 2, "after" ],
// stylistic
"block-spacing": [ "error", "always" ],
// lotsa Stroustrup for else-blocks
// "brace-style": [ "error", "1tbs", { "allowSingleLine": true } ],
"comma-spacing": [ "error" ],
"comma-style": [ "error" ],
"quote-props": [ "error", "as-needed" ],
"camelcase": [ 1, { "properties": "always" } ],
"eol-last": [ 2 ],
"key-spacing": [ 2 ],
"keyword-spacing": [ 2 ],
"no-lonely-if": [ 2 ],
"no-array-constructor": [ 2 ],
"no-extra-parens": [ 2, "functions" ],
"no-mixed-spaces-and-tabs": [ 2, "smart-tabs" ],
"no-nested-ternary": [ 2 ],
"no-new-object": [ 2 ],
"no-underscore-dangle": [ 0 ],
"no-trailing-spaces": [ 2 ],
"semi": [ 2, "always" ],
"space-before-blocks": [ 2, "always" ],
"space-before-function-paren": [ 2, { "anonymous": "never", "named": "never" } ],
"space-infix-ops": [ 2 ],
"space-unary-ops": [ 2, { "words": true, "nonwords": false } ],
"spaced-comment": [ 2, "always", { "exceptions": [ "-", "+" ] } ],
"quotes": [ 2, "double", "avoid-escape" ],
"wrap-regex": [ 2 ]
}
}
================================================
FILE: .github/workflows/ci.yml
================================================
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 10.x
- name: Install dependencies
run: npm install
- name: Run eslint
run: npx eslint *.js lib/**/*.js
- name: Run tests
run: npm test
- name: Run test coverage report
uses: coverallsapp/github-action@master
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
================================================
FILE: .github/workflows/docs.yml
================================================
name: Docs
on:
push:
branches: [ master ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 10.x
- name: Install dependencies
run: npm install
- name: Generate docs
run: npm run doc
- name: Publish docs to gh-pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./doc
destination_dir: doc
keep_files: true
enable_jekyll: true
================================================
FILE: .gitignore
================================================
node_modules
.DS_Store
bin/
bin2
out/
tmp/
performance/bin/
performance/device/
!tasks/bin
coverage
.idea
*.iml
*.tar.gz
cTestFinal.js
npm-debug.log
.vscode
================================================
FILE: .npmignore
================================================
test/
.DS_Store
bin/
bin2
out/
tmp/
performance/bin/
performance/device/
!tasks/bin
coverage
.idea
*.iml
*.tar.gz
cTestFinal.js
npm-debug.log
.vscode
================================================
FILE: .npmrc
================================================
registry=https://registry.npmjs.com
================================================
FILE: .travis.yml
================================================
language: node_js
node_js:
- "10"
branches:
only:
- master
- 0.x
- 1.0.0
# Set up keys to allow pushes, and update npm to the latest version
before_install: npm update -g npm
# travis runs 'npm install' by default, as the 'install' step
before_script: npm run dist;
# travis runs 'npm test' by default, as the 'script' step
# PLACEHOLDER FOR COVERAGE REPORTS ON GITHUB, IF WE WANT THEM.
# ALSO NEED TO ADD .coveralls.yml, IF WE WANT TO USE IT ON THE PRIVATE
# REPO.
after_script:
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
- npm run deploy-ghpages
notifications:
email:
falcor@netflix.com
================================================
FILE: CHANGELOG.md
================================================
# 2.4.1
## Bugfix
- Republished to remove an issue with a hash generation of 2.4.0
# 2.4.0
## Changes
- [Handling fromPath errors in SetResponse constructor](https://github.com/Netflix/falcor/pull/989)
# 2.3.2
## Bugfix
- [Handling fromPath errors in SetResponse constructor](https://github.com/Netflix/falcor/pull/989)
# 2.3.1
## Bugfix
- [Avoid fetching null paths](https://github.com/Netflix/falcor/pull/984)
# 2.3.0
## Changes
- [Skip nulls in path instead of throwing](https://github.com/Netflix/falcor/pull/982)
# 2.2.2
## Changes
- Updated falcor-path-utils to pull in changes: [Use NOINLINE to avoid inlining function definitions](https://github.com/Netflix/falcor-path-utils/pull/23)
- [Reduced allocation garbage](https://github.com/Netflix/falcor/pull/980)
# 2.2.1
## Bugs
- [Empty key sets in path sets could result in an incomplete response](https://github.com/Netflix/falcor/pull/979)
# 2.2.0
## Features
- [Request attempt count passed down to DataSource get/set](https://github.com/Netflix/falcor/pull/970)
# 2.1.0
## Features
- [Added flags for potentially expensive algorithms](https://github.com/Netflix/falcor/pull/962)
## Other
- [Unit tests converted to Jest](https://github.com/Netflix/falcor/pull/961)
# 2.0.7
## Bugs
- [Correct module.export usage](https://github.com/Netflix/falcor/pull/960)
# 2.0.6
## Bugs
- [Fix handling of empty keysets](https://github.com/Netflix/falcor/pull/955)
# 2.0.5
## Bugs
- [Fix request path deduplication](https://github.com/Netflix/falcor/pull/949)
# 2.0.4
## Bugs
- [Make Model#_clone return instance of current type](https://github.com/Netflix/falcor/pull/730)
- [Fix error stack traces](https://github.com/Netflix/falcor/pull/941)
- [Fix handling of outerResults as an optional argument](https://github.com/Netflix/falcor/pull/947)
# 2.0.3
## Bugs
- [Fix model._setValueSync() internal API to set path bound values in cache](https://github.com/Netflix/falcor/pull/933)
# 2.0.2
## Bugs
- [Fix model.get() dispose to cancel asynchronous DataSource request](https://github.com/Netflix/falcor/pull/933)
- [Fix model.batch() losing maxRetries config](https://github.com/Netflix/falcor/pull/932)
# 2.0.1
## Bugs
- [Fix build issues by replacing asap with falcor-asap](https://github.com/Netflix/falcor/pull/928)
# 2.0.0
## Features
- [Dedupe requests partially with existing requests](https://github.com/Netflix/falcor/pull/897)
- [Add missing paths information when raising
MaxRetryExceededError](https://github.com/Netflix/falcor/pull/874)
## Bugs
- [Fix "expires: 0" metadata on atoms](https://github.com/Netflix/falcor/pull/905/commits)
- [Protect against model.invalidate from destroying cache](https://github.com/Netflix/falcor/pull/903)
- [Fix retry count logic](https://github.com/Netflix/falcor/pull/904)
# 1.1.0
## Bugs
- [Fix maxRetries on clone](https://github.com/Netflix/falcor/pull/917)
- [Disables whole-branch response merging](https://github.com/Netflix/falcor/pull/920)
- [Fix model.set claiming objects passed as argument](https://github.com/Netflix/falcor/pull/920)
# 1.0.0
## Features
- [Allow errorSelector to change $type](https://github.com/Netflix/falcor/issues/828)
- [Falcor.keys](https://github.com/Netflix/falcor/issues/708)
- Adds a function to the namespace of `falcor` for ease of json key iteration.
- [Remove Rx From Core](https://github.com/Netflix/falcor/issues/465)
- [Remove Rx From Get](https://github.com/Netflix/falcor/issues/506)
- [Remove Rx From Set](https://github.com/Netflix/falcor/issues/604)
- [Add Falcor Build that contains Router](https://github.com/Netflix/falcor/issues/521)
- [Code clean-up: Remove selector function / output PathValues code throughout code base](https://github.com/Netflix/falcor/issues/453)
- [Remove asPathValues from ModelResponse](https://github.com/Netflix/falcor/issues/452)
- [Improve deref for better MVC Integration](https://github.com/Netflix/falcor/issues/501)
## Bugs
- [Webpack](https://github.com/Netflix/falcor/issues/586)
- [MaxRetryExceededError when a route returns a null value not wrapped in an atom](https://github.com/Netflix/falcor/issues/535)
- [The latest release throws model.get(...).then is not a function error](https://github.com/Netflix/falcor/issues/530)
- [Collect does not adjust cache size.](https://github.com/Netflix/falcor/issues/507)
- [number 0 becomes empty atom](https://github.com/Netflix/falcor/issues/460)
- [\`this.clone()\` is undefined](https://github.com/Netflix/falcor/issues/442)
- [Model#call() -> Error: "no method 'reduce' on 'localRoot.set(...).reduce'"](https://github.com/Netflix/falcor/issues/533)
- [Observable and CompositeDisposable declared but not used](https://github.com/Netflix/falcor/issues/573)
- [Path returned from falcor-router is undefined after call](https://github.com/Netflix/falcor/issues/589)
- [New deref doesn't work when deref'ing to a reference.](https://github.com/Netflix/falcor/issues/559)
- [New deref from an already deref'd model doesn't include the parent model's path.](https://github.com/Netflix/falcor/issues/560)
# 0.1.15
## Bugs
- [Fix deref completing without onNext'ing if preload paths fail](https://github.com/Netflix/falcor/pull/667)
- [Fix deref handling for paths that return an $atom of undefined](https://github.com/Netflix/falcor/pull/663)
- [Make sure deref calls the DataSource, when starting from a broken reference](https://github.com/Netflix/falcor/pull/661)
- [Fix expired reference handling, to return undefined, instead of InvalidModelError](https://github.com/Netflix/falcor/pull/658)
- [Fixed expiry handling for getValueSync](https://github.com/Netflix/falcor/pull/651)
- [Fixed distinct comparator to account for meta-data ($expires for example)](https://github.com/Netflix/falcor/pull/644)
- [Fix getCache() serialization issues](https://github.com/Netflix/falcor/pull/640)
- [Fixed reference promotion in LRU list](https://github.com/Netflix/falcor/pull/636)
- [Fixed errorSelector bugs - cases where it wasn't invoked, and invoked with malformed paths](https://github.com/Netflix/falcor/pull/611)
- [Fixed exceptions when call responses didn't contain any returned path/values](https://github.com/Netflix/falcor/pull/600)
================================================
FILE: LICENSE.txt
================================================
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 2012 Netflix, Inc.
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.
================================================
FILE: MIGRATIONS.md
================================================
# 1.x to 2.x
Models always (usually) onNext
-------
When starting with the following json graph
```javascript
{
lists: {
2343: {
0: { $type: "ref", value: ["videos", 123] },
1: { $type: "ref", value: ["videos", 123] }
}
},
videos: {
123: {
name: { $type: "atom", value: undefined }
}
}
}
```
A `get` would not emit values for intermediate branches found in the cache, unless an atom was found
```javascript
const json = await model.get(["lists", 2343, {to: 1}, "name"]);
{
json: {
{
lists: {
2343: {
0: {}
}
}
}
}
}
```
Where now, any branches or references found in the cache will always be emitted in the json output
```javascript
const json = await model.get(["lists", 2343, {to: 1}, "name"]);
{
json: {
lists: {
2343: {
0: {},
1: {}
}
}
}
}
```
That means that even requesting no paths will emit an empty object, as the cache root will be found
```javascript
const json = await model.get();
{
json: {}
}
```
The only case where get won't onNext at least one value is when it receives only errors from the underlying data source.
# 0.x to 1.x
Refs no longer emitted as json
-------
`get` no longer emits references as leaf values.
When starting with the following json graph
```javascript
{
lists: {
2343: {
0: { $type: "ref", value: ["videos", 123] }
}
},
videos: {
123: {
name: "House of cards"
}
}
}
```
Previously the following would emit a ref
```javascript
const json = await model.get(["lists", 2343, "0"]);
{
lists: {
2343: {
0: ["videos", 123]
}
}
}
```
Where now, a key with undefined is emitted
```javascript
const json = await model.get(["lists", 2343, "0"]);
{
lists: {
2343: {
0: undefined
}
}
}
```
No More Rx
-------
[Documentation on ModelResponse is found here](http://netflix.github.io/falcor/doc/ModelResponse.html)
In 0.x `ModelResponse`'s prototype inherited from `Rx.Observable` in the
following way.
```javascript
var Rx = require('rx/dist/rx');
var ModelResponse = function ModelResponse(...) {...};
ModelResponse.prototype = Object.create(Rx.Observable.prototype);
...
```
This means that after a `get`, `set`, or `call` any `Rx` operator could be used.
E.G.
```javascript
model.
get(['hello', 'falcor']).
doAction(function(x) {
...
}).
flatMap(function(x) {
return model.get(...);
}).
subscribe(...);
```
If your application relies on that behavior there are two possible upgrade
paths. If your application does not rely on `Rx`, but only the `subscribe` from
`Observable` then nothing has changed except for file size.
#### Option 1
Alter the prototype for `get`, `set`, and `call` to return `Rx.Observables`.
```javascript
var Rx = require('rx');
var falcor = require('./lib');
var Model = falcor.Model;
var slice = Array.prototype.slice;
var noRx = {
get: Model.prototype.get,
set: Model.prototype.set,
call: Model.prototype.call
};
Model.prototype.get = function getWithRx() {
var args = slice.call(arguments, 0);
return convertToRx(this, 'get', args);
};
Model.prototype.set = function setWithRx() {
var args = slice.call(arguments, 0);
return convertToRx(this, 'set', args);
};
Model.prototype.call = function callWithRx() {
var args = slice.call(arguments, 0);
return convertToRx(this, 'call', args);
};
function convertToRx(model, method, args) {
return Rx.Observable.create(function(observer) {
return noRx[method].apply(model, args).subscribe(observer);
});
}
```
##### Pros
* This upgrade only has to be done once and required once for the whole
application to receive the benefits.
##### Cons
* In the same vein, the whole application is forced into using the Rx based
falcor whether it wants to or not since the prototype has been edited.
#### Option 2
Wrap all calls to falcor with a Falcor.Subscribable -> Rx.Observable call.
```javascript
var Rx = require('rx');
var Observable = Rx.Observable;
module.exports = function toObservable(response) {
return Observable.create(function(observer) {
return response.subscribe(observer);
});
};
...
// Don't forget to wrap the progressively() call as well.
toObservable(
model.
get(['my', 'path']).
progressively()).
doAction(function() {
// Something awesome goes here
}).
subscribe();
```
##### Pros
* Its a more controlled approach since its opt-in only.
##### Cons
* This has to be done everywhere a call to falcor is made and Rx is the desired
output format.
* can be a bit tedious :)
Deref
-------------
[Documentation on deref is found here](http://netflix.github.io/falcor/doc/Model.html#deref)
`deref` has changed to use the output from a `ModelResponse` instead of
specifying the destination via path and leaves. This means that there will be
problems if you rely on `Object.keys` to iterate over your `json`. Instead,
use `falcor.keys`. It will strip out the `$__path` from the `ModelResponse's`
`json`.
Lets create a model with some initial cache.
```javascript
var model = new Model({
cache: {
genreLists: {
0: Model.ref(['lists', 'A'])
},
lists: {
A: {
1337: Model.ref(['videos', 1337])
}
},
videos: {
1337: {
title: Model.atom('Total Recall (June 1st, 1990)')
}
}
}
});
```
If we were to use `deref` in the **old** way we would have to perform the
following to dereference to [genreLists, 0, 0].
```javascript
model.
// Creates a dataSource (more than likely means a network call) call since
// imageUrl does not exist in the cache.
deref(['genreLists', 0, 0], ['title', 'imageUrl']).
subscribe(function(boundModel) {
// equivalent to model.get(['genreLists', 0, 0, 'title'])
// -> { json: { title: 'Total Recall (June 1st, 1990)' } }
boundModel.get(['title'])...
// Other rendering stuff / application logic
...
});
```
##### Cons
* The knowledge of leaves were required.
* Potential additional network requests could be made.
* Always async.
* Not very simple to explain how this works.
The new `deref` works from the output of `ModelResponse`, so the same thing could be
accomplished with the following.
```javascript
model.
get(['genreLists', 0, 0, 'title']).
subscribe(function(x) {
var json = x.json;
var boundModel = model.deref(json.genreLists[0][0]);
// equivalent to model.get(['genreLists', 0, 0, 'title'])
// -> { json: { title: 'Total Recall (June 1st, 1990)' } }
// If 'imageUrl' is used then a dataSource call would be made.
boundModel.get(['title'])...
// Other rendering stuff / application logic
...
});
```
##### Pros
* Simpler to grok/use
* Promotes better application architecture.
* Always synchronous.
Promise shimming
----------------
In 0.x we depend on the 'promise' npm package to supply a Promise
implementation on platforms missing the Promise builtin. In 1.x the choice of
Promise shim is made at bundle build time. The supplied bundles are built with
the same 'promise' npm package.
To replicate this in your own Browserify build use the `insertGlobalVars`
browserify option to use the Promise shim of your choice:
```javascript
browserify(filename, {
insertGlobalVars: {
Promise: function (file, basedir) {
return 'typeof Promise === "function" ? Promise : require("promise")';
}
}
}
```
With Webpack we can use `ProvidePlugin` to the same effect:
```javascript
var path = require("path");
var webpack = require("webpack");
module.exports = {
plugins: [
new webpack.ProvidePlugin({
Promise: path.join(__dirname, "promise-implementation"),
})
]
};
```
Where promise-implementation.js is:
```javascript
module.exports = global.Promise || require("promise");
```
For those not using Falcor's Promise functionality (i.e. `model.get().then(...)`)
or deploying only to modern browsers, omitting the 'promise' package from your
build will save ~1KB page weight from your build after gzipping and minification.
================================================
FILE: OSSMETADATA
================================================
osslifecycle=active
================================================
FILE: README.md
================================================
<p align="center">
<img src="https://cloud.githubusercontent.com/assets/1016365/8711049/66438ebc-2b03-11e5-8a8a-75934f7ca7ec.png">
</p>
# Falcor
[](https://travis-ci.org/Netflix/falcor)
[](https://coveralls.io/github/Netflix/falcor?branch=master)
## 2.0
**2.0** is the current stable Falcor release. **0.x** and **1.x** users are
welcome to upgrade.
- [Breaking changes between **1.x** and **2.0**](https://github.com/Netflix/falcor/blob/master/MIGRATIONS.md).
- [Breaking changes between **0.x** and **1.x**](https://github.com/Netflix/falcor/blob/1.0.0/MIGRATIONS.md).
## Roadmap
Issues we're tracking as part of our roadmap are tagged with the
[roadmap](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap)
label. They are split into
[enhancement](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap+label%3Aenhancement),
[stability](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap+label%3Astability),
[performance](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap+label%3Aperformance),
[tooling](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap+label%3Atooling),
[infrastructure](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap+label%3Ainfrastructure)
and
[documentation](https://github.com/Netflix/falcor/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap+label%3Adocumentation)
categories, with near, medium and longer term labels to convey a broader sense
of the order in which we plan to approach them.
## Getting Started
You can check out [a working example server for Netflix-like application](https://github.com/netflix/falcor-express-demo) right now. Alternately, you
can go through this barebones tutorial in which we use the Falcor Router to
create a Virtual JSON resource. In this tutorial we will use Falcor's express
middleware to serve the Virtual JSON resource on an application server at the
URL `/model.json`. We will also host a static web page on the same server which
retrieves data from the Virtual JSON resource.
### Creating a Virtual JSON Resource
In this example we will use the falcor Router to build a Virtual JSON resource
on an app server and host it at `/model.json`. The JSON resource will contain
the following contents:
```js
{
"greeting": "Hello World"
}
```
Normally, Routers retrieve the data for their Virtual JSON resource from backend
datastores or other web services on-demand. However, in this simple tutorial, the
Router will simply return static data for a single key.
First we create a folder for our application server.
```bash
$ mkdir falcor-app-server
$ cd falcor-app-server
$ npm init
```
Now we install the falcor Router.
```bash
$ npm install falcor-router --save
```
Then install express and falcor-express. Support for restify is also available,
as is support for hapi via a [third-party
implementation](https://github.com/Netflix/falcor-hapi).
```bash
$ npm install express --save
$ npm install falcor-express --save
```
Now we create an `index.js` file with the following contents:
```js
// index.js
const falcorExpress = require("falcor-express");
const Router = require("falcor-router");
const express = require("express");
const app = express();
app.use(
"/model.json",
falcorExpress.dataSourceRoute(function (req, res) {
// create a Virtual JSON resource with single key ('greeting')
return new Router([
{
// match a request for the key 'greeting'
route: "greeting",
// respond with a PathValue with the value of 'Hello World.'
get: () => ({ path: ["greeting"], value: "Hello World" }),
},
]);
})
);
// serve static files from current directory
app.use(express.static(__dirname + "/"));
app.listen(3000);
```
Now we run the server, which will listen on port `3000` for requests for
`/model.json`.
```bash
$ node index.js
```
### Retrieving Data from the Virtual JSON resource
Now that we've built a simple virtual JSON document with a single read-only key
`greeting`, we will create a test web page and retrieve this key from the
server.
Create an `index.html` file with the following contents:
```html
<!-- index.html -->
<html>
<head>
<!-- Do _not_ rely on this URL in production. Use only during development. -->
<script src="https://netflix.github.io/falcor/build/falcor.browser.js"></script>
<!-- For production use. -->
<!-- <script src="https://cdn.jsdelivr.net/falcor/{VERSION}/falcor.browser.min.js"></script> -->
<script>
var model = falcor({
source: new falcor.HttpDataSource("/model.json"),
});
// retrieve the "greeting" key from the root of the Virtual JSON resource
model.get("greeting").then(function (response) {
document.write(response.json.greeting);
});
</script>
</head>
<body></body>
</html>
```
Now visit `http://localhost:3000/index.html` and you should see the message
retrieved from the server:
```
Hello World
```
## Steps to publish new version
- Make pull request with feature/bug fix and tests
- Merge pull request into master after code review and passing Travis CI checks
- Run `git checkout master` to open `master` branch locally
- Run `git pull` to merge latest code, including built `dist/` and `docs/` by Travis
- Run `npm run dist` to build `dist/` locally
- Ensure the built files are not different from those built by Travis CI, hence creating no change to commit
- Update CHANGELOG with features/bug fixes to be released in the new version and commit
- Run `npm version patch` (or `minor`, `major`, etc) to create a new git commit and tag
- Run `git push origin master && git push --tags` to push code and tags to github
- Run `npm publish` to publish the latest version to NPM
## Additional Resources
- For detailed high-level documentation explaining the Model, the Router, and JSON
Graph check out the [Falcor website](https://netflix.github.io/falcor).
- [API documentation](https://netflix.github.io/falcor/doc/Model.html)
- For a working example of a Router, check out the
[falcor-router-demo](https://github.com/netflix/falcor-router-demo).
- For questions and discussion, use [Stack
Overflow](https://stackoverflow.com/questions/tagged/falcor).
================================================
FILE: all.js
================================================
var falcor = require("./browser.js");
var Router = require("falcor-router");
falcor.Router = Router;
module.exports = falcor;
================================================
FILE: authors.txt
================================================
Jafar Husain <jhusain@gmail.com>
Paul Taylor <ptaylor@netflix.com>
Michael Paulson <mpaulson@netflix.com>
================================================
FILE: bower.json
================================================
{
"name": "falcor",
"main": "./dist/falcor.browser.js",
"ignore": [
"build",
"examples",
"lib",
"performance",
"test",
".bithoundrc",
".eslintrc",
".gitignore",
".travis.yml",
"all.js",
"browser.js",
"conf.json",
"gulpfile.js",
"MIGRATIONS.md",
"OSSMETADATA",
"package.json",
"server.js",
"webpack.conf.js"
],
"dependencies": {
}
}
================================================
FILE: browser.js
================================================
var falcor = require("./lib");
var jsong = require("falcor-json-graph");
falcor.atom = jsong.atom;
falcor.ref = jsong.ref;
falcor.error = jsong.error;
falcor.pathValue = jsong.pathValue;
falcor.HttpDataSource = require("falcor-http-datasource");
module.exports = falcor;
================================================
FILE: build/deploy-ghpages.sh
================================================
#!/bin/bash
if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then
echo -e "Building and committing dist and docs...\n"
TEMP_DIR=$HOME/tmp
FALCOR_DOCS_DIR=$TEMP_DIR/falcordocs
FALCOR_BUILD_DIR=$TEMP_DIR/falcorbuild
GH_PAGES_DIR=$TEMP_DIR/gh-pages
DEPLOYABLE_REPO=git@github.com:Netflix/falcor.git
CURRENT_RELEASE=master
mkdir -p $TEMP_DIR
if [ -d "$FALCOR_BUILD_DIR" ]; then
rm -rf $FALCOR_BUILD_DIR
fi
if [ -d "$FALCOR_DOCS_DIR" ]; then
rm -rf $FALCOR_DOCS_DIR
fi
if [ -d "$GH_PAGES_DIR" ]; then
rm -rf $GH_PAGES_DIR
fi
git config --global user.email "falcorbuild@netflix.com"
git config --global user.name "Falcor Build"
openssl aes-256-cbc -K $encrypted_00000eb5a141_key -iv $encrypted_00000eb5a141_iv -in deployKey.enc -out deployKey -d
chmod 0600 deployKey
eval `ssh-agent -s`
ssh-add deployKey
# Need https url to push changes, and also need to move from detached head to built branch.
git remote add deployable $DEPLOYABLE_REPO
git checkout $TRAVIS_BRANCH
# Generate Docs
npm run doc
npm run dist
git add dist/.
git add doc/.
git commit -m "Travis build $TRAVIS_BUILD_NUMBER committed dist/ and doc/"
git push deployable $TRAVIS_BRANCH
if [ "$TRAVIS_BRANCH" == "$CURRENT_RELEASE" ]; then
echo -e "Updating gh-pages...\n"
cp -R doc $FALCOR_DOCS_DIR
cp -R dist $FALCOR_BUILD_DIR
# Change Working Directory to $HOME
cd $HOME
git clone --quiet --branch=gh-pages $DEPLOYABLE_REPO $GH_PAGES_DIR > /dev/null
# Change Working Directory to $HOME/gh-pages
cd $GH_PAGES_DIR
rsync -r $FALCOR_DOCS_DIR/ doc/
rsync -r $FALCOR_BUILD_DIR/ build/
git add .
git commit -m "Travis build $TRAVIS_BUILD_NUMBER off $TRAVIS_BRANCH pushed to gh-pages"
git push origin gh-pages
echo -e "Deployed docs and build to gh-pages\n"
fi
fi
================================================
FILE: build/falcor-jsdoc-template/README.md
================================================
### Falcor Website JSDoc Theme
Based on the default JSDoc 3 template, with a completely rewritten nav and a number of other improvements.
To easily modify it, take a look at the code in navigation.tmpl. Layout.tmpl, container.tmpl.
The main container.tmpl file has jekyll front matter in it so the falcor site can use it. If you'd like to use the template both inside and outside the site, it should be as simple as moving the front matter to layout.tmpl, then using the default template's ability to swap out layout.tmpl to have your own standalone template frame.
When working with the navigation, you'll notice it generates a long menu with a lot of extra information. That is there so it can be easily styled as you wish with a few lines of CSS. For example, it tracks the active page, so you can adapt which parts of the navigation are visible in a given context.
Like the default template for JSDoc 3, it uses: [the Taffy Database library](http://taffydb.com/) and the [Underscore Template library](http://documentcloud.github.com/underscore/#template).
================================================
FILE: build/falcor-jsdoc-template/publish.js
================================================
/*global env: true */
'use strict';
var doop = require('jsdoc/util/doop');
var fs = require('jsdoc/fs');
var helper = require('jsdoc/util/templateHelper');
var logger = require('jsdoc/util/logger');
var path = require('jsdoc/path');
var taffy = require('taffydb').taffy;
var template = require('jsdoc/template');
var util = require('util');
var _ = require('lodash');
var htmlsafe = helper.htmlsafe;
var linkto = helper.linkto;
var resolveAuthorLinks = helper.resolveAuthorLinks;
var hasOwnProp = Object.prototype.hasOwnProperty;
var data;
var view;
var outdir = path.normalize(env.opts.destination);
function find(spec) {
return helper.find(data, spec);
}
function tutoriallink(tutorial) {
return helper.toTutorial(tutorial, null, { tag: 'em', classname: 'disabled', prefix: 'Tutorial: ' });
}
function getAncestorLinks(doclet) {
return helper.getAncestorLinks(data, doclet);
}
function hashToLink(doclet, hash) {
if ( !/^(#.+)/.test(hash) ) { return hash; }
var url = helper.createLink(doclet);
url = url.replace(/(#.+|$)/, hash);
return '<a href="' + url + '">' + hash + '</a>';
}
function needsSignature(doclet) {
var needsSig = false;
// function and class definitions always get a signature
if (doclet.kind === 'function' || doclet.kind === 'class') {
needsSig = true;
}
// typedefs that contain functions get a signature, too
else if (doclet.kind === 'typedef' && doclet.type && doclet.type.names &&
doclet.type.names.length) {
for (var i = 0, l = doclet.type.names.length; i < l; i++) {
if (doclet.type.names[i].toLowerCase() === 'function') {
needsSig = true;
break;
}
}
}
return needsSig;
}
function getSignatureAttributes(item) {
var attributes = [];
if (item.optional) {
attributes.push('optional');
}
if (item.nullable === true) {
attributes.push('nullable');
}
else if (item.nullable === false) {
attributes.push('non-null');
}
return attributes;
}
function updateItemName(item) {
var attributes = getSignatureAttributes(item);
var itemName = item.name || '';
if (item.variable) {
itemName = '…' + itemName;
}
if (attributes && attributes.length) {
itemName = util.format( '%s<span class="signature-attributes">%s</span>', itemName,
attributes.join(', ') );
}
return itemName;
}
function addParamAttributes(params) {
return params.filter(function(param) {
return param.name && param.name.indexOf('.') === -1;
}).map(updateItemName);
}
function buildItemTypeStrings(item) {
var types = [];
if (item && item.type && item.type.names) {
item.type.names.forEach(function(name) {
types.push( linkto(name, htmlsafe(name)) );
});
}
return types;
}
function buildAttribsString(attribs) {
var attribsString = '';
if (attribs && attribs.length) {
attribsString = htmlsafe( util.format('(%s) ', attribs.join(', ')) );
}
return attribsString;
}
function addNonParamAttributes(items) {
var types = [];
items.forEach(function(item) {
types = types.concat( buildItemTypeStrings(item) );
});
return types;
}
function addSignatureParams(f) {
var params = f.params ? addParamAttributes(f.params) : [];
f.signature = util.format( '%s(%s)', (f.signature || ''), params.join(', ') );
}
function addSignatureReturns(f) {
var attribs = [];
var attribsString = '';
var returnTypes = [];
var returnTypesString = '';
// jam all the return-type attributes into an array. this could create odd results (for example,
// if there are both nullable and non-nullable return types), but let's assume that most people
// who use multiple @return tags aren't using Closure Compiler type annotations, and vice-versa.
if (f.returns) {
f.returns.forEach(function(item) {
helper.getAttribs(item).forEach(function(attrib) {
if (attribs.indexOf(attrib) === -1) {
attribs.push(attrib);
}
});
});
attribsString = buildAttribsString(attribs);
}
if (f.returns) {
returnTypes = addNonParamAttributes(f.returns);
}
if (returnTypes.length) {
returnTypesString = util.format( ' → %s{%s}', attribsString, returnTypes.join('|') );
}
f.signature = '<span class="signature">' + (f.signature || '') + '</span>' +
'<span class="type-signature return-signature">' + returnTypesString + '</span>';
}
function addSignatureTypes(f) {
var types = f.type ? buildItemTypeStrings(f) : [];
f.signature = (f.signature || '') + '<span class="type-signature">' +
(types.length ? ' :' + types.join('|') : '') + '</span>';
}
function addAttribs(f) {
var attribs = helper.getAttribs(f);
var attribsString = buildAttribsString(attribs);
f.attribs = util.format('<span class="type-signature">%s</span>', attribsString);
}
function shortenPaths(files, commonPrefix) {
Object.keys(files).forEach(function(file) {
files[file].shortened = files[file].resolved.replace(commonPrefix, '')
// always use forward slashes
.replace(/\\/g, '/');
});
return files;
}
function getPathFromDoclet(doclet) {
if (!doclet.meta) {
return null;
}
return doclet.meta.path && doclet.meta.path !== 'null' ?
path.join(doclet.meta.path, doclet.meta.filename) :
doclet.meta.filename;
}
function generate(title, docs, filename, resolveLinks) {
resolveLinks = resolveLinks === false ? false : true;
var docData = {
title: title,
docs: docs
};
var outpath = path.join(outdir, filename),
html = view.render('container.tmpl', docData);
if (resolveLinks) {
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
}
fs.writeFileSync(outpath, html, 'utf8');
}
function generateSourceFiles(sourceFiles, encoding) {
encoding = encoding || 'utf8';
Object.keys(sourceFiles).forEach(function(file) {
var source;
// links are keyed to the shortened path in each doclet's `meta.shortpath` property
var sourceOutfile = helper.getUniqueFilename(sourceFiles[file].shortened);
helper.registerLink(sourceFiles[file].shortened, sourceOutfile);
try {
source = {
kind: 'source',
code: helper.htmlsafe( fs.readFileSync(sourceFiles[file].resolved, encoding) )
};
}
catch(e) {
logger.error('Error while generating source file %s: %s', file, e.message);
}
generate(sourceFiles[file].shortened, [source], sourceOutfile, false);
});
}
/**
* Look for classes or functions with the same name as modules (which indicates that the module
* exports only that class or function), then attach the classes or functions to the `module`
* property of the appropriate module doclets. The name of each class or function is also updated
* for display purposes. This function mutates the original arrays.
*
* @private
* @param {Array.<module:jsdoc/doclet.Doclet>} doclets - The array of classes and functions to
* check.
* @param {Array.<module:jsdoc/doclet.Doclet>} modules - The array of module doclets to search.
*/
function attachModuleSymbols(doclets, modules) {
var symbols = {};
// build a lookup table
doclets.forEach(function(symbol) {
symbols[symbol.longname] = symbols[symbol.longname] || [];
symbols[symbol.longname].push(symbol);
});
return modules.map(function(module) {
if (symbols[module.longname]) {
module.modules = symbols[module.longname]
// Only show symbols that have a description. Make an exception for classes, because
// we want to show the constructor-signature heading no matter what.
.filter(function(symbol) {
return symbol.description || symbol.kind === 'class';
})
.map(function(symbol) {
symbol = doop(symbol);
if (symbol.kind === 'class' || symbol.kind === 'function') {
symbol.name = symbol.name.replace('module:', '(require("') + '"))';
}
return symbol;
});
}
});
}
function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) {
var nav = '';
if (items.length) {
var itemsNav = '';
items.forEach(function(item) {
if ( !hasOwnProp.call(item, 'longname') ) {
itemsNav += '<li>' + linktoFn('', item.name) + '</li>';
}
else if ( !hasOwnProp.call(itemsSeen, item.longname) ) {
itemsNav += '<li>' + linktoFn(item.longname, item.name.replace(/^module:/, '')) + '</li>';
itemsSeen[item.longname] = true;
}
});
if (itemsNav !== '') {
nav += '<h3>' + itemHeading + '</h3><ul>' + itemsNav + '</ul>';
}
}
return nav;
}
function linktoTutorial(longName, name) {
return tutoriallink(name);
}
function linktoExternal(longName, name) {
return linkto(longName, name.replace(/(^"|"$)/g, ''));
}
// escapes weird characters that jsdoc puts in ids but jquery chokes on
function escapeDocId(docId) {
return docId.replace(/(:|\.|\[|\]|,|~)/g, '\\$1');
};
// Returns a link just like linkto, but with an id to its target header on
// the page added so bootstrap scrollspy can pick it up use it to work.
// Also sanitizes the input because jsdoc uses all sorts of weird characters
// in their ids. Optionally, link text can be passed in to use instead of
// the doc's name inside the link.
function linkToWithTarget(doc, linkText) {
var linkTag = linkto(doc.longname, linkText || doc.name);
return linkTag.slice(0, linkTag.indexOf('>')) + ' data-target="#' +
escapeDocId(doc.id) + '"' + linkTag.slice(linkTag.indexOf('>'));
};
/**
* Create the navigation sidebar.
* @param {object} members The members that will be used to create the sidebar.
* @param {array<object>} members.classes
* @param {array<object>} members.externals
* @param {array<object>} members.globals
* @param {array<object>} members.mixins
* @param {array<object>} members.modules
* @param {array<object>} members.namespaces
* @param {array<object>} members.tutorials
* @param {array<object>} members.events
* @param {array<object>} members.interfaces
* @return {string} The HTML for the navigation sidebar.
*/
function buildNav(members) {
var nav = '<h2><a href="index.html">Home</a></h2>';
var seen = {};
var seenTutorials = {};
nav += buildMemberNav(members.modules, 'Modules', {}, linkto);
nav += buildMemberNav(members.externals, 'Externals', seen, linktoExternal);
nav += buildMemberNav(members.classes, 'Classes', seen, linkto);
nav += buildMemberNav(members.events, 'Events', seen, linkto);
nav += buildMemberNav(members.namespaces, 'Namespaces', seen, linkto);
nav += buildMemberNav(members.mixins, 'Mixins', seen, linkto);
nav += buildMemberNav(members.tutorials, 'Tutorials', seenTutorials, linktoTutorial);
nav += buildMemberNav(members.interfaces, 'Interfaces', seen, linkto);
if (members.globals.length) {
var globalNav = '';
members.globals.forEach(function(g) {
if ( g.kind !== 'typedef' && !hasOwnProp.call(seen, g.longname) ) {
globalNav += '<li>' + linkto(g.longname, g.name) + '</li>';
}
seen[g.longname] = true;
});
if (!globalNav) {
// turn the heading into a link so you can actually get to the global page
nav += '<h3>' + linkto('global', 'Global') + '</h3>';
}
else {
nav += '<h3>Global</h3><ul>' + globalNav + '</ul>';
}
}
return nav;
}
/**
@param {TAFFY} taffyData See <http://taffydb.com/>.
@param {object} opts
@param {Tutorial} tutorials
*/
exports.publish = function(taffyData, opts, tutorials) {
data = taffyData;
var conf = env.conf.templates || {};
conf.default = conf.default || {};
var templatePath = path.normalize(opts.template);
view = new template.Template( path.join(templatePath, 'tmpl') );
// claim some special filenames in advance, so the All-Powerful Overseer of Filename Uniqueness
// doesn't try to hand them out later
var indexUrl = helper.getUniqueFilename('index');
// don't call registerLink() on this one! 'index' is also a valid longname
var globalUrl = helper.getUniqueFilename('global');
helper.registerLink('global', globalUrl);
// set up templating
view.layout = conf.default.layoutFile ?
path.getResourcePath(path.dirname(conf.default.layoutFile),
path.basename(conf.default.layoutFile) ) :
'layout.tmpl';
// set up tutorials for helper
helper.setTutorials(tutorials);
data = helper.prune(data);
data.sort('longname, version, since');
helper.addEventListeners(data);
var sourceFiles = {};
var sourceFilePaths = [];
data().each(function(doclet) {
doclet.attribs = '';
if (doclet.examples) {
doclet.examples = doclet.examples.map(function(example) {
var caption, code;
if (example.match(/^\s*<caption>([\s\S]+?)<\/caption>(\s*[\n\r])([\s\S]+)$/i)) {
caption = RegExp.$1;
code = RegExp.$3;
}
return {
caption: caption || '',
code: code || example
};
});
}
if (doclet.see) {
doclet.see.forEach(function(seeItem, i) {
doclet.see[i] = hashToLink(doclet, seeItem);
});
}
// build a list of source files
var sourcePath;
if (doclet.meta) {
sourcePath = getPathFromDoclet(doclet);
sourceFiles[sourcePath] = {
resolved: sourcePath,
shortened: null
};
if (sourceFilePaths.indexOf(sourcePath) === -1) {
sourceFilePaths.push(sourcePath);
}
}
});
// update outdir if necessary, then create outdir
var packageInfo = ( find({kind: 'package'}) || [] ) [0];
if (packageInfo && packageInfo.name) {
outdir = path.join( outdir, packageInfo.name, (packageInfo.version || '') );
}
fs.mkPath(outdir);
// All static file functionality is handled by the site jekyll templates now
// This is left in just in case it needs to be restored later.
// copy the template's static files to outdir
// var fromDir = path.join(templatePath, 'static');
// var staticFiles = fs.ls(fromDir, 3);
//
// staticFiles.forEach(function(fileName) {
// var toDir = fs.toDir( fileName.replace(fromDir, outdir) );
// fs.mkPath(toDir);
// fs.copyFileSync(fileName, toDir);
// });
//
// // copy user-specified static files to outdir
// var staticFilePaths;
// var staticFileFilter;
// var staticFileScanner;
// if (conf.default.staticFiles) {
// // The canonical property name is `include`. We accept `paths` for backwards compatibility
// // with a bug in JSDoc 3.2.x.
// staticFilePaths = conf.default.staticFiles.include ||
// conf.default.staticFiles.paths ||
// [];
// staticFileFilter = new (require('jsdoc/src/filter')).Filter(conf.default.staticFiles);
// staticFileScanner = new (require('jsdoc/src/scanner')).Scanner();
//
// staticFilePaths.forEach(function(filePath) {
// var extraStaticFiles;
//
// filePath = path.resolve(env.pwd, filePath);
// extraStaticFiles = staticFileScanner.scan([filePath], 10, staticFileFilter);
//
// extraStaticFiles.forEach(function(fileName) {
// var sourcePath = fs.toDir(filePath);
// var toDir = fs.toDir( fileName.replace(sourcePath, outdir) );
// fs.mkPath(toDir);
// fs.copyFileSync(fileName, toDir);
// });
// });
// }
if (sourceFilePaths.length) {
sourceFiles = shortenPaths( sourceFiles, path.commonPrefix(sourceFilePaths) );
}
data().each(function(doclet) {
var url = helper.createLink(doclet);
helper.registerLink(doclet.longname, url);
// add a shortened version of the full path
var docletPath;
if (doclet.meta) {
docletPath = getPathFromDoclet(doclet);
docletPath = sourceFiles[docletPath].shortened;
if (docletPath) {
doclet.meta.shortpath = docletPath;
}
}
});
data().each(function(doclet) {
var url = helper.longnameToUrl[doclet.longname];
if (url.indexOf('#') > -1) {
doclet.id = helper.longnameToUrl[doclet.longname].split(/#/).pop();
}
else {
doclet.id = doclet.name;
}
if ( needsSignature(doclet) ) {
addSignatureParams(doclet);
addSignatureReturns(doclet);
addAttribs(doclet);
}
});
// do this after the urls have all been generated
data().each(function(doclet) {
doclet.ancestors = getAncestorLinks(doclet);
if (doclet.kind === 'member') {
addSignatureTypes(doclet);
addAttribs(doclet);
}
if (doclet.kind === 'constant') {
addSignatureTypes(doclet);
addAttribs(doclet);
doclet.kind = 'member';
}
});
var members = helper.getMembers(data);
members.tutorials = tutorials.children;
// output pretty-printed source files by default
var outputSourceFiles = conf.default && conf.default.outputSourceFiles !== false ? true :
false;
// add template helpers
view.find = find;
view.linkto = linkto;
view.linkToWithTarget = linkToWithTarget;
view.resolveAuthorLinks = resolveAuthorLinks;
view.tutoriallink = tutoriallink;
view.htmlsafe = htmlsafe;
view.outputSourceFiles = outputSourceFiles;
view._ = _;
// once for all
view.nav = buildNav(members);
attachModuleSymbols( find({ longname: {left: 'module:'} }), members.modules );
// generate the pretty-printed source files first so other pages can link to them
if (outputSourceFiles) {
generateSourceFiles(sourceFiles, opts.encoding);
}
if (members.globals.length) { generate('Global', [{kind: 'globalobj'}], globalUrl); }
// index page displays information from package.json and lists files
var files = find({kind: 'file'}),
packages = find({kind: 'package'});
generate('Home',
packages.concat(
[{kind: 'mainpage', readme: opts.readme, longname: (opts.mainpagetitle) ? opts.mainpagetitle : 'Main Page'}]
).concat(files),
indexUrl);
// set up the lists that we'll use to generate pages
var classes = taffy(members.classes);
var modules = taffy(members.modules);
var namespaces = taffy(members.namespaces);
var mixins = taffy(members.mixins);
var externals = taffy(members.externals);
var interfaces = taffy(members.interfaces);
Object.keys(helper.longnameToUrl).forEach(function(longname) {
var myModules = helper.find(modules, {longname: longname});
if (myModules.length) {
generate('Module: ' + myModules[0].name, myModules, helper.longnameToUrl[longname]);
}
var myClasses = helper.find(classes, {longname: longname});
if (myClasses.length) {
generate('Class: ' + myClasses[0].name, myClasses, helper.longnameToUrl[longname]);
}
var myNamespaces = helper.find(namespaces, {longname: longname});
if (myNamespaces.length) {
generate('Namespace: ' + myNamespaces[0].name, myNamespaces, helper.longnameToUrl[longname]);
}
var myMixins = helper.find(mixins, {longname: longname});
if (myMixins.length) {
generate('Mixin: ' + myMixins[0].name, myMixins, helper.longnameToUrl[longname]);
}
var myExternals = helper.find(externals, {longname: longname});
if (myExternals.length) {
generate('External: ' + myExternals[0].name, myExternals, helper.longnameToUrl[longname]);
}
var myInterfaces = helper.find(interfaces, {longname: longname});
if (myInterfaces.length) {
generate('Interface: ' + myInterfaces[0].name, myInterfaces, helper.longnameToUrl[longname]);
}
});
// TODO: move the tutorial functions to templateHelper.js
function generateTutorial(title, tutorial, filename) {
var tutorialData = {
title: title,
header: tutorial.title,
content: tutorial.parse(),
children: tutorial.children
};
var tutorialPath = path.join(outdir, filename),
html = view.render('tutorial.tmpl', tutorialData);
// yes, you can use {@link} in tutorials too!
html = helper.resolveLinks(html); // turn {@link foo} into <a href="foodoc.html">foo</a>
fs.writeFileSync(tutorialPath, html, 'utf8');
}
// tutorials can have only one parent so there is no risk for loops
function saveChildren(node) {
node.children.forEach(function(child) {
generateTutorial('Tutorial: ' + child.title, child, helper.tutorialToUrl(child.name));
saveChildren(child);
});
}
saveChildren(tutorials);
};
================================================
FILE: build/falcor-jsdoc-template/tmpl/augments.tmpl
================================================
<?js
var data = obj;
var self = this;
?>
<?js if (data.augments && data.augments.length) { ?>
<ul><?js data.augments.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }) ?></ul>
<?js } ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/container.tmpl
================================================
---
layout: api-page
title: "<?js= title ?>"
id: api
---
<main class="api-documentation-page">
<?js
var self = this;
var isGlobalPage;
docs.forEach(function(doc, i) {
?>
<?js
// we only need to check this once
if (typeof isGlobalPage === 'undefined') {
isGlobalPage = (doc.kind === 'globalobj');
}
?>
<?js if (doc.kind === 'mainpage' || (doc.kind === 'package')) { ?>
<?js= self.partial('mainpage.tmpl', doc) ?>
<?js } else if (doc.kind === 'source') { ?>
<?js= self.partial('source.tmpl', {doc: doc, fileName: title}) ?>
<?js } else { ?>
<section>
<header>
<?js if (isGlobalPage) { ?>
<h2>Global</h2>
<?js } ?>
<?js if (!doc.longname || doc.kind !== 'module') { ?>
<?js if ((doc.ancestors && doc.ancestors.length) || doc.name || doc.variation) { ?>
<h2><?js if (doc.ancestors && doc.ancestors.length) { ?>
<span class="ancestors"><?js= doc.ancestors.join('') ?></span>
<?js } ?>
<?js= doc.name ?>
<?js if (doc.variation) { ?>
<sup class="variation"><?js= doc.variation ?></sup>
<?js } ?></h2>
<?js } ?>
<?js if (doc.classdesc) { ?>
<div class="class-description"><?js= doc.classdesc ?></div>
<?js } ?>
<?js } else if (doc.kind === 'module' && doc.modules) { ?>
<?js doc.modules.forEach(function(module) { ?>
<?js if (module.classdesc) { ?>
<div class="class-description"><?js= module.classdesc ?></div>
<?js } ?>
<?js }) ?>
<?js } ?>
</header>
<article>
<div class="container-overview">
<?js if (doc.kind === 'module' && doc.modules) { ?>
<?js if (doc.description) { ?>
<div class="description"><?js= doc.description ?></div>
<?js } ?>
<?js doc.modules.forEach(function(module) { ?>
<?js= self.partial('method.tmpl', module) ?>
<?js }) ?>
<?js } else if (doc.kind === 'class') { ?>
<?js= self.partial('method.tmpl', doc) ?>
<?js } else { ?>
<?js if (doc.description) { ?>
<div class="description"><?js= doc.description ?></div>
<?js } ?>
<?js= self.partial('details.tmpl', doc) ?>
<?js if (doc.examples && doc.examples.length) { ?>
<h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3>
<?js= self.partial('examples.tmpl', doc.examples) ?>
<?js } ?>
<?js } ?>
</div>
<?js if (doc.augments && doc.augments.length) { ?>
<h3 class="subsection-title">Extends</h3>
<?js= self.partial('augments.tmpl', doc) ?>
<?js } ?>
<?js if (doc.requires && doc.requires.length) { ?>
<h3 class="subsection-title">Requires</h3>
<ul><?js doc.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r, r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js
var classes = self.find({kind: 'class', memberof: doc.longname});
if (!isGlobalPage && classes && classes.length) {
?>
<h3 class="subsection-title">Classes</h3>
<dl><?js classes.forEach(function(c) { ?>
<dt><?js= self.linkto(c.longname, c.name) ?></dt>
<dd><?js if (c.summary) { ?><?js= c.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var mixins = self.find({kind: 'mixin', memberof: doc.longname});
if (!isGlobalPage && mixins && mixins.length) {
?>
<h3 class="subsection-title">Mixins</h3>
<dl><?js mixins.forEach(function(m) { ?>
<dt><?js= self.linkto(m.longname, m.name) ?></dt>
<dd><?js if (m.summary) { ?><?js= m.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var namespaces = self.find({kind: 'namespace', memberof: doc.longname});
if (!isGlobalPage && namespaces && namespaces.length) {
?>
<h3 class="subsection-title">Namespaces</h3>
<dl><?js namespaces.forEach(function(n) { ?>
<dt><?js= self.linkto(n.longname, n.name) ?></dt>
<dd><?js if (n.summary) { ?><?js= n.summary ?><?js } ?></dd>
<?js }); ?></dl>
<?js } ?>
<?js
var members = self.find({kind: 'member', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
// symbols that are assigned to module.exports are not globals, even though they're not a memberof anything
if (isGlobalPage && members && members.length && members.forEach) {
members = members.filter(function(m) {
return m.longname && m.longname.indexOf('module:') !== 0;
});
}
if (members && members.length && members.forEach) {
?>
<h3 class="subsection-title">Members</h3>
<?js members.forEach(function(p) { ?>
<?js= self.partial('members.tmpl', p) ?>
<?js }); ?>
<?js } ?>
<?js
var methods = self.find({kind: 'function', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (methods && methods.length && methods.forEach) {
?>
<h3 class="subsection-title">Methods</h3>
<?js methods.forEach(function(m) { ?>
<?js= self.partial('method.tmpl', m) ?>
<?js }); ?>
<?js } ?>
<?js
var typedefs = self.find({kind: 'typedef', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (typedefs && typedefs.length && typedefs.forEach) {
?>
<h3 class="subsection-title">Type Definitions</h3>
<?js typedefs.forEach(function(e) {
if (e.signature) {
?>
<?js= self.partial('method.tmpl', e) ?>
<?js
}
else {
?>
<?js= self.partial('members.tmpl', e) ?>
<?js
}
}); ?>
<?js } ?>
<?js
var events = self.find({kind: 'event', memberof: isGlobalPage ? {isUndefined: true} : doc.longname});
if (events && events.length && events.forEach) {
?>
<h3 class="subsection-title">Events</h3>
<?js events.forEach(function(e) { ?>
<?js= self.partial('method.tmpl', e) ?>
<?js }); ?>
<?js } ?>
</article>
</section>
<?js } ?>
<?js }); ?>
</main>
<?js= self.partial('navigation.tmpl', {docs: docs}) ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/details.tmpl
================================================
<?js
var data = obj;
var self = this;
var defaultObjectClass = '';
// Check if the default value is an object or array; if so, apply code highlighting
if (data.defaultvalue && (data.defaultvaluetype === 'object' || data.defaultvaluetype === 'array')) {
data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
defaultObjectClass = ' class="object-value"';
}
?>
<?js
var properties = data.properties;
if (properties && properties.length && properties.forEach) {
?>
<h5 class="subsection-title">Properties</h5>
<?js= this.partial('properties.tmpl', data) ?>
<?js } ?>
<?js
// Check all of the data below and skip the section if none of it is here.
// Crazy? yes. Necessary? Unfortunately so, otherwise the details-classed
// element takes up space and may make a page look janky
if (
data.version ||
data.since ||
data.inherited ||
(data.inherited && data.inherits && !data.overrides) ||
(data.overrides) || (data.implementations && data.implementations.length) ||
(data.implements && data.implements.length) ||
(data.mixes && data.mixes.length) ||
(data.deprecated) ||
(data.author && author.length) ||
(data.copyright) ||
(data.license) ||
(data.defaultvalue) ||
(data.meta && self.outputSourceFiles) ||
(data.tutorials && tutorials.length) ||
(data.see && see.length) ||
(data.todo && todo.length)
) {
?>
<dl class="details">
<?js if (data.version) {?>
<dt class="tag-version">Version:</dt>
<dd class="tag-version"><?js= version ?></dd>
<?js } ?>
<?js if (data.since) {?>
<dt class="tag-since">Since:</dt>
<dd class="tag-since"><?js= since ?></dd>
<?js } ?>
<?js if (data.inherited && data.inherits && !data.overrides) { ?>
<dt class="inherited-from">Inherited From:</dt>
<dd class="inherited-from">
<?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?>
</dd>
<?js } ?>
<?js if (data.overrides) { ?>
<dt class="tag-overrides">Overrides:</dt>
<dd class="tag-overrides">
<?js= this.linkto(data.overrides, this.htmlsafe(data.overrides)) ?>
</dd>
<?js } ?>
<?js if (data.implementations && data.implementations.length) { ?>
<dt class="implementations">Implementations:</dt>
<dd class="implementations"><ul>
<?js data.implementations.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></dd>
<?js } ?>
<?js if (data.implements && data.implements.length) { ?>
<dt class="implements">Implements:</dt>
<dd class="implements"><ul>
<?js data.implements.forEach(function(impl) { ?>
<li><?js= self.linkto(impl, self.htmlsafe(impl)) ?></li>
<?js }); ?>
</ul></dd>
<?js } ?>
<?js if (data.mixes && data.mixes.length) { ?>
<dt class="mixes">Mixes In:</dt>
<dd class="mixes"><ul>
<?js data.mixes.forEach(function(a) { ?>
<li><?js= self.linkto(a, a) ?></li>
<?js }); ?>
</ul></dd>
<?js } ?>
<?js if (data.deprecated) { ?>
<dt class="important tag-deprecated">Deprecated:</dt><?js
if (data.deprecated === true) { ?><dd class="yes-def tag-deprecated">Yes</dd><?js }
else { ?><dd><?js= data.deprecated ?></dd><?js }
?>
<?js } ?>
<?js if (data.author && author.length) {?>
<dt class="tag-author">Author:</dt>
<dd class="tag-author">
<ul><?js author.forEach(function(a) { ?>
<li><?js= self.resolveAuthorLinks(a) ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
<?js if (data.copyright) {?>
<dt class="tag-copyright">Copyright:</dt>
<dd class="tag-copyright"><?js= copyright ?></dd>
<?js } ?>
<?js if (data.license) {?>
<dt class="tag-license">License:</dt>
<dd class="tag-license"><?js= license ?></dd>
<?js } ?>
<?js if (data.defaultvalue) {?>
<dt class="tag-default">Default Value:</dt>
<dd class="tag-default">
<span<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></span>
</dd>
<?js } ?>
<?js if (data.meta && self.outputSourceFiles) {?>
<dt class="tag-source">Source:</dt>
<dd class="tag-source">
<?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?>
</dd>
<?js } ?>
<?js if (data.tutorials && tutorials.length) {?>
<dt class="tag-tutorial">Tutorials:</dt>
<dd class="tag-tutorial">
<ul><?js tutorials.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t) ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
<?js if (data.see && see.length) {?>
<dt class="tag-see">See:</dt>
<dd class="tag-see">
<ul><?js see.forEach(function(s) { ?>
<li><?js= self.linkto(s) ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
<?js if (data.todo && todo.length) {?>
<dt class="tag-todo">To Do:</dt>
<dd class="tag-todo">
<ul><?js todo.forEach(function(t) { ?>
<li><?js= t ?></li>
<?js }); ?></ul>
</dd>
<?js } ?>
</dl>
<?js } ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/example.tmpl
================================================
<?js var data = obj; ?>
<pre><code><?js= data ?></code></pre>
================================================
FILE: build/falcor-jsdoc-template/tmpl/examples.tmpl
================================================
<?js
var data = obj;
var self = this;
data.forEach(function(example) {
if (example.caption) {
?>
<p class="code-caption"><?js= example.caption ?></p>
<?js } ?>
<pre class="prettyprint"><code><?js= self.htmlsafe(example.code) ?></code></pre>
<?js
});
?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/exceptions.tmpl
================================================
<?js
var data = obj;
?>
<?js if (data.description && data.type && data.type.names) { ?>
<dl>
<dt>
<div class="param-desc">
<?js= data.description ?>
</div>
</dt>
<dd></dd>
<dt>
<dl>
<dt>
Type
</dt>
<dd>
<?js= this.partial('type.tmpl', data.type.names) ?>
</dd>
</dl>
</dt>
<dd></dd>
</dl>
<?js } else { ?>
<div class="param-desc">
<?js if (data.description) { ?>
<?js= data.description ?>
<?js } else if (data.type && data.type.names) { ?>
<?js= this.partial('type.tmpl', data.type.names) ?>
<?js } ?>
</div>
<?js } ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/layout.tmpl
================================================
<?js= content ?>
<?js // All of the content is in container.tmpl ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/mainpage.tmpl
================================================
<?js
var data = obj;
var self = this;
?>
<?js if (data.kind === 'package') { ?>
<h3><?js= data.name ?> <?js= data.version ?></h3>
<?js } ?>
<?js if (data.readme) { ?>
<section>
<article><?js= data.readme ?></article>
</section>
<?js } ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/members.tmpl
================================================
<?js
var data = obj;
var self = this;
?>
<section class="member-section">
<h4 class="name section-header members-header" id="<?js= id ?>"><?js= data.attribs + name + (data.signature ? data.signature : '') ?></h4>
<?js if (data.summary) { ?>
<p class="summary"><?js= summary ?></p>
<?js } ?>
<?js if (data.description) { ?>
<div class="description">
<?js= data.description ?>
</div>
<?js } ?>
<?js if (data.type && data.type.names) {?>
<dl class="member-type">
<dt><span class="h5">Type:</span></dt>
<dd><?js= self.partial('type.tmpl', data.type.names) ?></dd>
</dl>
<?js } ?>
<?js= this.partial('details.tmpl', data) ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
</section>
================================================
FILE: build/falcor-jsdoc-template/tmpl/method.tmpl
================================================
<?js
var data = obj;
var self = this;
?>
<section class="method-section">
<?js if (data.kind !== 'module') { ?>
<?js if (data.kind === 'class' && data.classdesc) { ?>
<h2>Constructor</h2>
<?js } ?>
<h4 class="name section-header function-name" id="<?js= id ?>"><?js= data.attribs + (kind === 'class' ? 'new ' : '') +
name + (data.signature || '') ?></h4>
<?js if (data.summary) { ?>
<p class="summary"><?js= summary ?></p>
<?js } ?>
<?js } ?>
<?js if (data.kind !== 'module' && data.description) { ?>
<div class="description">
<?js= data.description ?>
</div>
<?js } ?>
<?js if (data.augments && data.alias && data.alias.indexOf('module:') === 0) { ?>
<h5>Extends:</h5>
<?js= self.partial('augments.tmpl', data) ?>
<?js } ?>
<?js if (kind === 'event' && data.type && data.type.names) {?>
<h5>Type:</h5>
<ul>
<li>
<?js= self.partial('type.tmpl', data.type.names) ?>
</li>
</ul>
<?js } ?>
<?js if (data['this']) { ?>
<h5>This:</h5>
<ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
<?js } ?>
<?js if (data.params && params.length) { ?>
<h5>Parameters:</h5>
<?js= this.partial('params.tmpl', params) ?>
<?js } ?>
<?js= this.partial('details.tmpl', data) ?>
<?js if (data.kind !== 'module' && data.requires && data.requires.length) { ?>
<h5>Requires:</h5>
<ul><?js data.requires.forEach(function(r) { ?>
<li><?js= self.linkto(r) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.fires && fires.length) { ?>
<h5>Fires:</h5>
<ul><?js fires.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listens && listens.length) { ?>
<h5>Listens to Events:</h5>
<ul><?js listens.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.listeners && listeners.length) { ?>
<h5>Listeners of This Event:</h5>
<ul><?js listeners.forEach(function(f) { ?>
<li><?js= self.linkto(f) ?></li>
<?js }); ?></ul>
<?js } ?>
<?js if (data.exceptions && exceptions.length) { ?>
<h5>Throws:</h5>
<?js if (exceptions.length > 1) { ?><ul><?js
exceptions.forEach(function(r) { ?>
<li><?js= self.partial('exceptions.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
exceptions.forEach(function(r) { ?>
<?js= self.partial('exceptions.tmpl', r) ?>
<?js });
} } ?>
<?js if (data.returns && returns.length) { ?>
<?js if (data.returns.length > 1 || data.returns[0].description) { ?>
<h5>Returns:</h5>
<?js } ?>
<?js if (returns.length > 1) { ?><ul><?js
returns.forEach(function(r) { ?>
<li><?js= self.partial('returns.tmpl', r) ?></li>
<?js });
?></ul><?js } else {
returns.forEach(function(r) { ?>
<?js= self.partial('returns.tmpl', r) ?>
<?js });
} } ?>
<?js if (data.examples && examples.length) { ?>
<h5>Example<?js= examples.length > 1? 's':'' ?></h5>
<?js= this.partial('examples.tmpl', examples) ?>
<?js } ?>
</section>
================================================
FILE: build/falcor-jsdoc-template/tmpl/navigation-subgroup.tmpl
================================================
<?js
var docs = obj.docs;
var title = obj.title;
var id = obj.groupId;
var self = this;
?>
<?js if (docs.length) { ?>
<ul class="toc-api-subgroup toc-api-subgroup-<?js= id ?>">
<li>
<span class="toc-api-subgroup-title"><?js= title ?></span>
</li>
<?js _.each(docs, function (doc) { ?>
<li class="toc-api-subgroup-item">
<?js= self.linkToWithTarget(doc) ?>
</li>
<?js }) ?>
</ul>
<?js } ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/navigation.tmpl
================================================
<?js
(function (self) {
var classDocs = self.find({kind: 'class'})
var keys = _.keys(classDocs[1])
var getSubDocs = function (classDoc, docType) {
var result = self.find({kind: docType, memberof: classDoc.longname})
return result || [];
}
var typeDocs = self.find({kind: 'typedef', memberof: {isUndefined: true}})
// So far I haven't encountered any pages with more than one doc in the doclist, but
// based on the original template I'm guessing it's possible
var currentDoc = _.first(docs);
?>
<?js if (docs && docs.length > 0) { ?>
<!--
In case someone comes along later and sees the active item on the
toc acting weirdly, hopefully they'll see this comment. This page, unlike
any seen during development, has multiple 'docs' passed to container.tmpl.
To debug it and enhance the page as needed, I would suggest looking there first.
-->
<?js } ?>
<!-- Generate the table of contents -->
<nav class="table-of-contents api-doc-toc">
<ul class="nav">
<li>
<?js= self.linkto(_.first(classDocs).longname, 'Classes') ?>
<ul class="toc-api-classes">
<?js _.each(classDocs, function (classDoc) { ?>
<li class="toc-api-class <?js= currentDoc.longname === classDoc.longname ? 'current-page' : '' ?>">
<?js= self.linkToWithTarget(classDoc) ?>
<?js
var methodDocs = getSubDocs(classDoc, 'function');
var typeDocs = getSubDocs(classDoc, 'typedef');
var eventDocs = getSubDocs(classDoc, 'event');
// for now just combine them
var subDocs = methodDocs.concat(eventDocs, typeDocs);
?>
<?js= self.partial('navigation-subgroup.tmpl', {docs: methodDocs, title: 'Methods', groupId: 'methods'}) ?>
<?js= self.partial('navigation-subgroup.tmpl', {docs: typeDocs, title: 'Types', groupId: 'types'}) ?>
<?js= self.partial('navigation-subgroup.tmpl', {docs: eventDocs, title: 'Events', groupId: 'events'}) ?>
</li>
<?js }) ?>
</ul>
</li>
<li class="toc-api-type-list <?js= currentDoc.kind === 'globalobj' ? 'current-page' : '' ?>">
<?js= self.linkto('global', 'Global Types') ?>
<ul class="toc-api-types">
<?js _.each(typeDocs, function (typeDoc) { ?>
<li class="toc-api-type">
<?js= self.linkToWithTarget(typeDoc) ?>
</li>
<?js }) ?>
</ul>
</li>
</ul>
</nav>
<?js }(this)) ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/params.tmpl
================================================
<?js
var params = obj;
/* sort subparams under their parent params (like opts.classname) */
var parentParam = null;
params.forEach(function(param, i) {
var paramRegExp;
if (!param) {
return;
}
if (parentParam && parentParam.name && param.name) {
paramRegExp = new RegExp('^(?:' + parentParam.name + '(?:\\[\\])*)\\.(.+)$');
if ( paramRegExp.test(param.name) ) {
param.name = RegExp.$1;
parentParam.subparams = parentParam.subparams || [];
parentParam.subparams.push(param);
params[i] = null;
}
else {
parentParam = param;
}
}
else {
parentParam = param;
}
});
/* determine if we need extra columns, "attributes" and "default" */
params.hasAttributes = false;
params.hasDefault = false;
params.hasName = false;
params.forEach(function(param) {
if (!param) { return; }
if (param.optional || param.nullable || param.variable) {
params.hasAttributes = true;
}
if (param.name) {
params.hasName = true;
}
if (typeof param.defaultvalue !== 'undefined') {
params.hasDefault = true;
}
});
?>
<div class="parameters-section">
<table class="params">
<thead>
<tr>
<?js if (params.hasName) {?>
<th class="header-name-and-attributes">
Name
<?js if (params.hasAttributes) {?>
& Attributes
<?js } ?>
</th>
<?js } ?>
<th class="header-type">Type</th>
<?js if (params.hasDefault) {?>
<th class="header-default">Default</th>
<?js } ?>
<th class="last header-description">Description</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
params.forEach(function(param) {
if (!param) { return; }
?>
<tr>
<?js if (params.hasName) {?>
<td>
<span class="name"><?js= param.name ?></span>
<?js if (params.hasAttributes) {?>
<?js if (param.optional) { ?>
<br>
<span class="attribute">optional</span>
<?js } ?>
<?js if (param.nullable) { ?>
<br>
<span class="attribute">nullable</span>
<?js } ?>
<?js if (param.variable) { ?>
<br>
<span class="attribute">repeatable</span>
<?js } ?>
<?js } ?>
</td>
<?js } ?>
<td class="type">
<?js if (param.type && param.type.names) {?>
<?js= self.partial('type.tmpl', param.type.names) ?>
<?js } ?>
</td>
<?js if (params.hasDefault) {?>
<td class="default">
<?js if (typeof param.defaultvalue !== 'undefined') { ?>
<?js= self.htmlsafe(param.defaultvalue) ?>
<?js } ?>
</td>
<?js } ?>
<td class="description last"><?js= param.description ?><?js if (param.subparams) { ?>
<h6>Properties</h6>
<?js= self.partial('params.tmpl', param.subparams) ?>
<?js } ?></td>
</tr>
<?js }); ?>
</tbody>
</table>
</div>
================================================
FILE: build/falcor-jsdoc-template/tmpl/properties.tmpl
================================================
<?js
var data = obj;
var props = data.subprops || data.properties;
/* sort subprops under their parent props (like opts.classname) */
var parentProp = null;
props.forEach(function(prop, i) {
if (!prop) { return; }
if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
prop.name = prop.name.substr(parentProp.name.length+1);
parentProp.subprops = parentProp.subprops || [];
parentProp.subprops.push(prop);
props[i] = null;
}
else {
parentProp = prop;
}
});
/* determine if we need extra columns, "attributes" and "default" */
props.hasAttributes = false;
props.hasDefault = false;
props.hasName = false;
props.forEach(function(prop) {
if (!prop) { return; }
if (prop.optional || prop.nullable) {
props.hasAttributes = true;
}
if (prop.name) {
props.hasName = true;
}
if (typeof prop.defaultvalue !== 'undefined' && !data.isEnum) {
props.hasDefault = true;
}
});
?>
<table class="props">
<thead>
<tr>
<?js if (props.hasName) {?>
<th>Name</th>
<?js } ?>
<th>Type</th>
<?js if (props.hasAttributes) {?>
<th>Attributes</th>
<?js } ?>
<?js if (props.hasDefault) {?>
<th>Default</th>
<?js } ?>
<th class="last">Description</th>
</tr>
</thead>
<tbody>
<?js
var self = this;
props.forEach(function(prop) {
if (!prop) { return; }
?>
<tr>
<?js if (props.hasName) {?>
<td class="name">
<?js= prop.name ?>
</td>
<?js } ?>
<td class="type">
<?js if (prop.type && prop.type.names) {?>
<?js= self.partial('type.tmpl', prop.type.names) ?>
<?js } ?>
</td>
<?js if (props.hasAttributes) {?>
<td class="attributes">
<?js if (prop.optional) { ?>
<optional><br>
<?js } ?>
<?js if (prop.nullable) { ?>
<nullable><br>
<?js } ?>
</td>
<?js } ?>
<?js if (props.hasDefault) {?>
<td class="default">
<?js if (typeof prop.defaultvalue !== 'undefined') { ?>
<?js= self.htmlsafe(prop.defaultvalue) ?>
<?js } ?>
</td>
<?js } ?>
<td class="description last"><?js= prop.description ?><?js if (prop.subprops) { ?>
<h6>Properties</h6><?js= self.partial('properties.tmpl', prop) ?>
<?js } ?></td>
</tr>
<?js }); ?>
</tbody>
</table>
================================================
FILE: build/falcor-jsdoc-template/tmpl/returns.tmpl
================================================
<?js
var data = obj || {};
if (data.description) {
?>
<div class="param-desc">
<?js= description ?>
</div>
<?js } ?>
<?js if (data.type && data.type.names) {?>
<dl class="return-type">
<dt>
Return Type:
</dt>
<dd>
<?js= this.partial('type.tmpl', data.type.names) ?>
</dd>
</dl>
<?js } ?>
================================================
FILE: build/falcor-jsdoc-template/tmpl/source.tmpl
================================================
<?js
var data = obj.doc;
?>
<h2>
<?js= obj.fileName ?>
</h2>
<section>
<article>
<pre class="prettyprint source linenums"><code><?js= data.code ?></code></pre>
</article>
</section>
================================================
FILE: build/falcor-jsdoc-template/tmpl/tutorial.tmpl
================================================
<section>
<header>
<?js if (children.length > 0) { ?>
<ul><?js
var self = this;
children.forEach(function(t) { ?>
<li><?js= self.tutoriallink(t.name) ?></li>
<?js }); ?></ul>
<?js } ?>
<h2><?js= header ?></h2>
</header>
<article>
<?js= content ?>
</article>
</section>
================================================
FILE: build/falcor-jsdoc-template/tmpl/type.tmpl
================================================
<?js
var data = obj;
var self = this;
data.forEach(function(name, i) { ?>
<span class="param-type"><?js= self.linkto(name, self.htmlsafe(name)) ?></span>
<?js if (i < data.length-1) { ?>or<?js } ?>
<?js }); ?>
================================================
FILE: build/gulp-build.js
================================================
var gulp = require("gulp");
var browserify = require("browserify");
var license = require("gulp-license");
var uglify = require("gulp-uglify");
var vinyl = require("vinyl-source-stream");
var bundleCollapser = require("bundle-collapser/plugin");
var _ = require("lodash");
var path = require("path");
var licenseInfo = {
organization: "Netflix, Inc",
year: "2020",
};
var browserifyOptions = {
standalone: "falcor",
insertGlobalVars: {
Promise: function(file, basedir) {
return 'typeof Promise === "function" ? Promise : require("promise")';
},
},
};
function buildDistBrowser() {
return build({
file: ["./browser.js"],
outName: "falcor.browser",
browserifyOptions: browserifyOptions,
debug: false,
});
}
function buildBrowser() {
return build({
file: ["./browser.js"],
outName: "falcor.browser",
browserifyOptions: browserifyOptions,
});
}
function buildDistAll() {
return build({
file: ["./all.js"],
outName: "falcor.all",
browserifyOptions: browserifyOptions,
debug: false,
});
}
function buildAll() {
return build({
file: ["./all.js"],
outName: "falcor.all",
browserifyOptions: browserifyOptions,
});
}
function build(options) {
options = _.assign(
{
file: "",
browserifyOptions: {},
outName: options.outName,
dest: "dist",
debug: true,
},
options
);
var name = options.outName + ((!options.debug && ".min") || "") + ".js";
return browserify(options.file, options.browserifyOptions)
.plugin(bundleCollapser)
.bundle()
.pipe(vinyl(name))
.pipe(license("Apache", licenseInfo))
.pipe(gulp.dest(options.dest))
// eslint-disable-next-line consistent-return
.on("finish", function() {
if (!options.debug) {
// minify output
var destAndName = path.join(options.dest, name);
return gulp.src(destAndName)
.pipe(uglify())
.pipe(gulp.dest(options.dest));
}
});
}
module.exports = {
buildAll: buildAll,
buildBrowser: buildBrowser,
buildDistAll: buildDistAll,
buildDistBrowser: buildDistBrowser,
};
================================================
FILE: build/gulp-clean.js
================================================
var del = require("del");
function cleanPerf() {
return del(["./performance/bin", "./performance/out"]);
}
function cleanDoc() {
return del(["./doc"]);
}
function cleanBin() {
return del(["./bin"]);
}
function cleanDist() {
return del(["./dist"]);
}
function cleanCoverage() {
return del(["./coverage"]);
}
module.exports = {
bin: cleanBin,
coverage: cleanCoverage,
dist: cleanDist,
doc: cleanDoc,
perf: cleanPerf,
};
================================================
FILE: build/gulp-perf.js
================================================
var gulp = require("gulp");
var concat = require("gulp-concat");
var vinyl = require("vinyl-source-stream");
var browserify = require("browserify");
var gulpShell = require("gulp-shell");
const { runner } = require("karma");
function buildDevice() {
return browserify("./performance/device.js", { ignoreMissing: true })
.bundle()
.pipe(vinyl("device-body.js"))
.pipe(gulp.dest("performance/bin"));
}
function polyfillDevice() {
return gulp
.src(["./node_modules/nf-falcor-device-perf/devicePolyfill.js", "performance/bin/device-body.js"], { allowEmpty: true })
.pipe(concat({ path: "device.js" }))
.pipe(gulp.dest("performance/bin"));
}
function buildBrowser() {
return browserify("./performance/browser.js")
.bundle()
.pipe(vinyl("browser.js"))
.pipe(gulp.dest("performance/bin"));
}
function runBrowser() {
return gulpShell.task("karma start ./performance/karma.conf.js")();
}
function runNode() {
return gulpShell.task("node --expose-gc ./performance/node.js")();
}
module.exports = {
buildDevice: gulp.series(buildDevice, polyfillDevice),
buildBrowser: buildBrowser,
runBrowser: runBrowser,
runNode: runNode,
};
================================================
FILE: build/jsdoc.json
================================================
{
"opts": {
"template": "falcor-jsdoc-template"
},
"templates": {},
"plugins": ["plugins/markdown"]
}
================================================
FILE: conf.json
================================================
{
"plugins": ["plugins/markdown"]
}
================================================
FILE: dist/falcor.all.js
================================================
/*!
* Copyright 2020 Netflix, Inc
*
* 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.
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.falcor = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
var falcor = require(2);
var Router = require(239);
falcor.Router = Router;
module.exports = falcor;
},{"2":2,"239":239}],2:[function(require,module,exports){
var falcor = require(34);
var jsong = require(121);
falcor.atom = jsong.atom;
falcor.ref = jsong.ref;
falcor.error = jsong.error;
falcor.pathValue = jsong.pathValue;
falcor.HttpDataSource = require(116);
module.exports = falcor;
},{"116":116,"121":121,"34":34}],3:[function(require,module,exports){
var ModelRoot = require(5);
var ModelDataSourceAdapter = require(4);
var RequestQueue = require(44);
var ModelResponse = require(52);
var CallResponse = require(50);
var InvalidateResponse = require(51);
var TimeoutScheduler = require(66);
var ImmediateScheduler = require(65);
var collectLru = require(40);
var pathSyntax = require(125);
var getSize = require(78);
var isObject = require(90);
var isPrimitive = require(92);
var isJSONEnvelope = require(88);
var isJSONGraphEnvelope = require(89);
var setCache = require(68);
var setJSONGraphs = require(67);
var jsong = require(121);
var ID = 0;
var validateInput = require(106);
var noOp = function() {};
var getCache = require(19);
var get = require(24);
var GET_VALID_INPUT = require(59);
module.exports = Model;
Model.ref = jsong.ref;
Model.atom = jsong.atom;
Model.error = jsong.error;
Model.pathValue = jsong.pathValue;
/**
* This callback is invoked when the Model's cache is changed.
* @callback Model~onChange
*/
/**
* This function is invoked on every JSONGraph Error retrieved from the DataSource. This function allows Error objects
* to be transformed before being stored in the Model's cache.
* @callback Model~errorSelector
* @param {Object} jsonGraphError - the JSONGraph Error object to transform before it is stored in the Model's cache.
* @returns {Object} the JSONGraph Error object to store in the Model cache.
*/
/**
* This function is invoked every time a value in the Model cache is about to be replaced with a new value. If the
* function returns true, the existing value is replaced with a new value and the version flag on all of the value's
* ancestors in the tree are incremented.
* @callback Model~comparator
* @param {Object} existingValue - the current value in the Model cache.
* @param {Object} newValue - the value about to be set into the Model cache.
* @returns {Boolean} the Boolean value indicating whether the new value and the existing value are equal.
*/
/**
* @typedef {Object} Options
* @property {DataSource} [source] A data source to retrieve and manage the {@link JSONGraph}
* @property {JSONGraph} [cache] Initial state of the {@link JSONGraph}
* @property {number} [maxSize] The maximum size of the cache before cache pruning is performed. The unit of this value
* depends on the algorithm used to calculate the `$size` field on graph nodes by the backing source for the Model's
* DataSource. If no DataSource is used, or the DataSource does not provide `$size` values, a naive algorithm is used
* where the cache size is calculated in terms of graph node count and, for arrays and strings, element count.
* @property {number} [collectRatio] The ratio of the maximum size to collect when the maxSize is exceeded.
* @property {number} [maxRetries] The maximum number of times that the Model will attempt to retrieve the value from
* its DataSource. Defaults to `3`.
* @property {Model~errorSelector} [errorSelector] A function used to translate errors before they are returned
* @property {Model~onChange} [onChange] A function called whenever the Model's cache is changed
* @property {Model~comparator} [comparator] A function called whenever a value in the Model's cache is about to be
* replaced with a new value.
* @property {boolean} [disablePathCollapse] Disables the algorithm that collapses paths on GET requests. The algorithm
* is enabled by default. This is a relatively computationally expensive feature.
* @property {boolean} [disableRequestDeduplication] Disables the algorithm that deduplicates paths across in-flight GET
* requests. The algorithm is enabled by default. This is a computationally expensive feature.
*/
/**
* A Model object is used to execute commands against a {@link JSONGraph} object. {@link Model}s can work with a local JSONGraph cache, or it can work with a remote {@link JSONGraph} object through a {@link DataSource}.
* @constructor
* @param {Options} [o] - a set of options to customize behavior
*/
function Model(o) {
var options = o || {};
this._root = options._root || new ModelRoot(options);
this._path = options.path || options._path || [];
this._source = options.source || options._source;
this._request =
options.request || options._request || new RequestQueue(this, options.scheduler || new ImmediateScheduler());
this._ID = ID++;
if (typeof options.maxSize === "number") {
this._maxSize = options.maxSize;
} else {
this._maxSize = options._maxSize || Model.prototype._maxSize;
}
if (typeof options.maxRetries === "number") {
this._maxRetries = options.maxRetries;
} else {
this._maxRetries = options._maxRetries || Model.prototype._maxRetries;
}
if (typeof options.collectRatio === "number") {
this._collectRatio = options.collectRatio;
} else {
this._collectRatio = options._collectRatio || Model.prototype._collectRatio;
}
if (options.boxed || options.hasOwnProperty("_boxed")) {
this._boxed = options.boxed || options._boxed;
}
if (options.materialized || options.hasOwnProperty("_materialized")) {
this._materialized = options.materialized || options._materialized;
}
if (typeof options.treatErrorsAsValues === "boolean") {
this._treatErrorsAsValues = options.treatErrorsAsValues;
} else if (options.hasOwnProperty("_treatErrorsAsValues")) {
this._treatErrorsAsValues = options._treatErrorsAsValues;
} else {
this._treatErrorsAsValues = false;
}
if (typeof options.disablePathCollapse === "boolean") {
this._enablePathCollapse = !options.disablePathCollapse;
} else if (options.hasOwnProperty("_enablePathCollapse")) {
this._enablePathCollapse = options._enablePathCollapse;
} else {
this._enablePathCollapse = true;
}
if (typeof options.disableRequestDeduplication === "boolean") {
this._enableRequestDeduplication = !options.disableRequestDeduplication;
} else if (options.hasOwnProperty("_enableRequestDeduplication")) {
this._enableRequestDeduplication = options._enableRequestDeduplication;
} else {
this._enableRequestDeduplication = true;
}
this._useServerPaths = options._useServerPaths || false;
this._allowFromWhenceYouCame = options.allowFromWhenceYouCame || options._allowFromWhenceYouCame || false;
this._treatDataSourceErrorsAsJSONGraphErrors = options._treatDataSourceErrorsAsJSONGraphErrors || false;
if (options.cache) {
this.setCache(options.cache);
}
}
Model.prototype.constructor = Model;
Model.prototype._materialized = false;
Model.prototype._boxed = false;
Model.prototype._progressive = false;
Model.prototype._treatErrorsAsValues = false;
Model.prototype._maxSize = Math.pow(2, 53) - 1;
Model.prototype._maxRetries = 3;
Model.prototype._collectRatio = 0.75;
Model.prototype._enablePathCollapse = true;
Model.prototype._enableRequestDeduplication = true;
/**
* The get method retrieves several {@link Path}s or {@link PathSet}s from a {@link Model}. The get method loads each value into a JSON object and returns in a ModelResponse.
* @function
* @param {...PathSet} path - the path(s) to retrieve
* @return {ModelResponse.<JSONEnvelope>} - the requested data as JSON
*/
Model.prototype.get = require(58);
/**
* _getOptimizedBoundPath is an extension point for internal users to polyfill
* legacy soft-bind behavior, as opposed to deref (hardBind). Current falcor
* only supports deref, and assumes _path to be a fully optimized path.
* @function
* @private
* @return {Path} - fully optimized bound path for the model
*/
Model.prototype._getOptimizedBoundPath = function _getOptimizedBoundPath() {
return this._path ? this._path.slice() : this._path;
};
/**
* The get method retrieves several {@link Path}s or {@link PathSet}s from a {@link Model}. The get method loads each value into a JSON object and returns in a ModelResponse.
* @function
* @private
* @param {Array.<PathSet>} paths - the path(s) to retrieve
* @return {ModelResponse.<JSONEnvelope>} - the requested data as JSON
*/
Model.prototype._getWithPaths = require(57);
/**
* Sets the value at one or more places in the JSONGraph model. The set method accepts one or more {@link PathValue}s, each of which is a combination of a location in the document and the value to place there. In addition to accepting {@link PathValue}s, the set method also returns the values after the set operation is complete.
* @function
* @return {ModelResponse.<JSONEnvelope>} - an {@link Observable} stream containing the values in the JSONGraph model after the set was attempted
*/
Model.prototype.set = require(61);
/**
* The preload method retrieves several {@link Path}s or {@link PathSet}s from a {@link Model} and loads them into the Model cache.
* @function
* @param {...PathSet} path - the path(s) to retrieve
* @return {ModelResponse.<JSONEnvelope>} - a ModelResponse that completes when the data has been loaded into the cache.
*/
Model.prototype.preload = function preload() {
var out = validateInput(arguments, GET_VALID_INPUT, "preload");
if (out !== true) {
return new ModelResponse(function(o) {
o.onError(out);
});
}
var args = Array.prototype.slice.call(arguments);
var self = this;
return new ModelResponse(function(obs) {
return self.get.apply(self, args).subscribe(
function() {},
function(err) {
obs.onError(err);
},
function() {
obs.onCompleted();
}
);
});
};
/**
* Invokes a function in the JSON Graph.
* @function
* @param {Path} functionPath - the path to the function to invoke
* @param {Array.<Object>} args - the arguments to pass to the function
* @param {Array.<PathSet>} refPaths - the paths to retrieve from the JSON Graph References in the message returned from the function
* @param {Array.<PathSet>} extraPaths - additional paths to retrieve after successful function execution
* @return {ModelResponse.<JSONEnvelope> - a JSONEnvelope contains the values returned from the function
*/
Model.prototype.call = function call() {
var args;
var argsIdx = -1;
var argsLen = arguments.length;
args = new Array(argsLen);
while (++argsIdx < argsLen) {
var arg = arguments[argsIdx];
args[argsIdx] = arg;
var argType = typeof arg;
if (
(argsIdx > 1 && !Array.isArray(arg)) ||
(argsIdx === 0 && !Array.isArray(arg) && argType !== "string") ||
(argsIdx === 1 && !Array.isArray(arg) && !isPrimitive(arg))
) {
/* eslint-disable no-loop-func */
return new ModelResponse(function(o) {
o.onError(new Error("Invalid argument"));
});
/* eslint-enable no-loop-func */
}
}
return new CallResponse(this, args[0], args[1], args[2], args[3]);
};
/**
* The invalidate method synchronously removes several {@link Path}s or {@link PathSet}s from a {@link Model} cache.
* @function
* @param {...PathSet} path - the paths to remove from the {@link Model}'s cache.
*/
Model.prototype.invalidate = function invalidate() {
var args;
var argsIdx = -1;
var argsLen = arguments.length;
args = [];
while (++argsIdx < argsLen) {
args[argsIdx] = pathSyntax.fromPath(arguments[argsIdx]);
if (!Array.isArray(args[argsIdx]) || !args[argsIdx].length) {
throw new Error("Invalid argument");
}
}
// creates the obs, subscribes and will throw the errors if encountered.
new InvalidateResponse(this, args).subscribe(noOp, function(e) {
throw e;
});
};
/**
* Returns a new {@link Model} bound to a location within the {@link
* JSONGraph}. The bound location is never a {@link Reference}: any {@link
* Reference}s encountered while resolving the bound {@link Path} are always
* replaced with the {@link Reference}s target value. For subsequent operations
* on the {@link Model}, all paths will be evaluated relative to the bound
* path. Deref allows you to:
* - Expose only a fragment of the {@link JSONGraph} to components, rather than
* the entire graph
* - Hide the location of a {@link JSONGraph} fragment from components
* - Optimize for executing multiple operations and path looksup at/below the
* same location in the {@link JSONGraph}
* @method
* @param {Object} responseObject - an object previously retrieved from the
* Model
* @return {Model} - the dereferenced {@link Model}
* @example
var Model = falcor.Model;
var model = new Model({
cache: {
users: [
Model.ref(["usersById", 32])
],
usersById: {
32: {
name: "Steve",
surname: "McGuire"
}
}
}
});
model.
get(['users', 0, 'name']).
subscribe(function(jsonEnv) {
var userModel = model.deref(jsonEnv.json.users[0]);
console.log(model.getPath());
console.log(userModel.getPath());
});
});
// prints the following:
// []
// ["usersById", 32] - because userModel refers to target of reference at ["users", 0]
*/
Model.prototype.deref = require(7);
/**
* A dereferenced model can become invalid when the reference from which it was
* built has been removed/collected/expired/etc etc. To fix the issue, a from
* the parent request should be made (no parent, then from the root) for a valid
* path and re-dereference performed to update what the model is bound too.
*
* @method
* @private
* @return {Boolean} - If the currently deref'd model is still considered a
* valid deref.
*/
Model.prototype._hasValidParentReference = require(6);
/**
* Get data for a single {@link Path}.
* @param {Path} path - the path to retrieve
* @return {Observable.<*>} - the value for the path
* @example
var model = new falcor.Model({source: new HttpDataSource("/model.json") });
model.
getValue('user.name').
subscribe(function(name) {
console.log(name);
});
// The code above prints "Jim" to the console.
*/
Model.prototype.getValue = require(21);
/**
* Set value for a single {@link Path}.
* @param {Path} path - the path to set
* @param {Object} value - the value to set
* @return {Observable.<*>} - the value for the path
* @example
var model = new falcor.Model({source: new HttpDataSource("/model.json") });
model.
setValue('user.name', 'Jim').
subscribe(function(name) {
console.log(name);
});
// The code above prints "Jim" to the console.
*/
Model.prototype.setValue = require(70);
// TODO: Does not throw if given a PathSet rather than a Path, not sure if it should or not.
// TODO: Doc not accurate? I was able to invoke directly against the Model, perhaps because I don't have a data source?
// TODO: Not clear on what it means to "retrieve objects in addition to JSONGraph values"
/**
* Synchronously retrieves a single path from the local {@link Model} only and will not retrieve missing paths from the {@link DataSource}. This method can only be invoked when the {@link Model} does not have a {@link DataSource} or from within a selector function. See {@link Model.prototype.get}. The getValueSync method differs from the asynchronous get methods (ex. get, getValues) in that it can be used to retrieve objects in addition to JSONGraph values.
* @method
* @private
* @arg {Path} path - the path to retrieve
* @return {*} - the value for the specified path
*/
Model.prototype._getValueSync = require(29);
/**
* @private
*/
Model.prototype._setValueSync = require(71);
/**
* @private
*/
Model.prototype._derefSync = require(8);
/**
* Set the local cache to a {@link JSONGraph} fragment. This method can be a useful way of mocking a remote document, or restoring the local cache from a previously stored state.
* @param {JSONGraph} jsonGraph - the {@link JSONGraph} fragment to use as the local cache
*/
Model.prototype.setCache = function modelSetCache(cacheOrJSONGraphEnvelope) {
var cache = this._root.cache;
if (cacheOrJSONGraphEnvelope !== cache) {
var modelRoot = this._root;
var boundPath = this._path;
this._path = [];
this._root.cache = {};
if (typeof cache !== "undefined") {
collectLru(modelRoot, modelRoot.expired, getSize(cache), 0);
}
var out;
if (isJSONGraphEnvelope(cacheOrJSONGraphEnvelope)) {
out = setJSONGraphs(this, [cacheOrJSONGraphEnvelope])[0];
} else if (isJSONEnvelope(cacheOrJSONGraphEnvelope)) {
out = setCache(this, [cacheOrJSONGraphEnvelope])[0];
} else if (isObject(cacheOrJSONGraphEnvelope)) {
out = setCache(this, [{ json: cacheOrJSONGraphEnvelope }])[0];
}
// performs promotion without producing output.
if (out) {
get.getWithPathsAsPathMap(this, out, []);
}
this._path = boundPath;
} else if (typeof cache === "undefined") {
this._root.cache = {};
}
return this;
};
/**
* Get the local {@link JSONGraph} cache. This method can be a useful to store the state of the cache.
* @param {...Array.<PathSet>} [pathSets] - The path(s) to retrieve. If no paths are specified, the entire {@link JSONGraph} is returned.
* @return {JSONGraph} all of the {@link JSONGraph} data in the {@link Model} cache.
* @example
// Storing the boxshot of the first 10 titles in the first 10 genreLists to local storage.
localStorage.setItem('cache', JSON.stringify(model.getCache("genreLists[0...10][0...10].boxshot")));
*/
Model.prototype.getCache = function _getCache() {
var paths = Array.prototype.slice.call(arguments);
if (paths.length === 0) {
return getCache(this._root.cache);
}
var result = [{}];
var path = this._path;
get.getWithPathsAsJSONGraph(this, paths, result);
this._path = path;
return result[0].jsonGraph;
};
/**
* Reset cache maxSize. When the new maxSize is smaller than the old force a collect.
* @param {Number} maxSize - the new maximum cache size
*/
Model.prototype._setMaxSize = function setMaxSize(maxSize) {
var oldMaxSize = this._maxSize;
this._maxSize = maxSize;
if (maxSize < oldMaxSize) {
var modelRoot = this._root;
var modelCache = modelRoot.cache;
// eslint-disable-next-line no-cond-assign
var currentVersion = modelCache.$_version;
collectLru(
modelRoot,
modelRoot.expired,
getSize(modelCache),
this._maxSize,
this._collectRatio,
currentVersion
);
}
};
/**
* Retrieves a number which is incremented every single time a value is changed underneath the Model or the object at an optionally-provided Path beneath the Model.
* @param {Path?} path - a path at which to retrieve the version number
* @return {Number} a version number which changes whenever a value is changed underneath the Model or provided Path
*/
Model.prototype.getVersion = function getVersion(pathArg) {
var path = (pathArg && pathSyntax.fromPath(pathArg)) || [];
if (Array.isArray(path) === false) {
throw new Error("Model#getVersion must be called with an Array path.");
}
if (this._path.length) {
path = this._path.concat(path);
}
return this._getVersion(this, path);
};
Model.prototype._syncCheck = function syncCheck(name) {
if (Boolean(this._source) && this._root.syncRefCount <= 0 && this._root.unsafeMode === false) {
throw new Error("Model#" + name + " may only be called within the context of a request selector.");
}
return true;
};
/* eslint-disable guard-for-in */
Model.prototype._clone = function cloneModel(opts) {
var clone = new this.constructor(this);
for (var key in opts) {
var value = opts[key];
if (value === "delete") {
delete clone[key];
} else {
clone[key] = value;
}
}
clone.setCache = void 0;
return clone;
};
/* eslint-enable */
/**
* Returns a clone of the {@link Model} that enables batching. Within the configured time period,
* paths for get operations are collected and sent to the {@link DataSource} in a batch. Batching
* can be more efficient if the {@link DataSource} access the network, potentially reducing the
* number of HTTP requests to the server.
*
* @param {?Scheduler|number} schedulerOrDelay - Either a {@link Scheduler} that determines when to
* send a batch to the {@link DataSource}, or the number in milliseconds to collect a batch before
* sending to the {@link DataSource}. If this parameter is omitted, then batch collection ends at
* the end of the next tick.
* @return {Model} a Model which schedules a batch of get requests to the DataSource.
*/
Model.prototype.batch = function batch(schedulerOrDelay) {
var scheduler;
if (typeof schedulerOrDelay === "number") {
scheduler = new TimeoutScheduler(Math.round(Math.abs(schedulerOrDelay)));
} else if (!schedulerOrDelay || !schedulerOrDelay.schedule) {
scheduler = new TimeoutScheduler(1);
} else {
scheduler = schedulerOrDelay;
}
var clone = this._clone();
clone._request = new RequestQueue(clone, scheduler);
return clone;
};
/**
* Returns a clone of the {@link Model} that disables batching. This is the default mode. Each get operation will be executed on the {@link DataSource} separately.
* @name unbatch
* @memberof Model.prototype
* @function
* @return {Model} a {@link Model} that batches requests of the same type and sends them to the data source together
*/
Model.prototype.unbatch = function unbatch() {
var clone = this._clone();
clone._request = new RequestQueue(clone, new ImmediateScheduler());
return clone;
};
/**
* Returns a clone of the {@link Model} that treats errors as values. Errors will be reported in the same callback used to report data. Errors will appear as objects in responses, rather than being sent to the {@link Observable~onErrorCallback} callback of the {@link ModelResponse}.
* @return {Model}
*/
Model.prototype.treatErrorsAsValues = function treatErrorsAsValues() {
return this._clone({
_treatErrorsAsValues: true
});
};
/**
* Adapts a Model to the {@link DataSource} interface.
* @return {DataSource}
* @example
var model =
new falcor.Model({
cache: {
user: {
name: "Steve",
surname: "McGuire"
}
}
}),
proxyModel = new falcor.Model({ source: model.asDataSource() });
// Prints "Steve"
proxyModel.getValue("user.name").
then(function(name) {
console.log(name);
});
*/
Model.prototype.asDataSource = function asDataSource() {
return new ModelDataSourceAdapter(this);
};
Model.prototype._materialize = function materialize() {
return this._clone({
_materialized: true
});
};
Model.prototype._dematerialize = function dematerialize() {
return this._clone({
_materialized: "delete"
});
};
/**
* Returns a clone of the {@link Model} that boxes values returning the wrapper ({@link Atom}, {@link Reference}, or {@link Error}), rather than the value inside it. This allows any metadata attached to the wrapper to be inspected.
* @return {Model}
*/
Model.prototype.boxValues = function boxValues() {
return this._clone({
_boxed: true
});
};
/**
* Returns a clone of the {@link Model} that unboxes values, returning the value inside of the wrapper ({@link Atom}, {@link Reference}, or {@link Error}), rather than the wrapper itself. This is the default mode.
* @return {Model}
*/
Model.prototype.unboxValues = function unboxValues() {
return this._clone({
_boxed: "delete"
});
};
/**
* Returns a clone of the {@link Model} that only uses the local {@link JSONGraph} and never uses a {@link DataSource} to retrieve missing paths.
* @return {Model}
*/
Model.prototype.withoutDataSource = function withoutDataSource() {
return this._clone({
_source: "delete"
});
};
Model.prototype.toJSON = function toJSON() {
return {
$type: "ref",
value: this._path
};
};
/**
* Returns the {@link Path} to the object within the JSON Graph that this Model references.
* @return {Path}
* @example
var Model = falcor.Model;
var model = new Model({
cache: {
users: [
Model.ref(["usersById", 32])
],
usersById: {
32: {
name: "Steve",
surname: "McGuire"
}
}
}
});
model.
get(['users', 0, 'name']).
subscribe(function(jsonEnv) {
var userModel = model.deref(jsonEnv.json.users[0]);
console.log(model.getPath());
console.log(userModel.getPath());
});
});
// prints the following:
// []
// ["usersById", 32] - because userModel refers to target of reference at ["users", 0]
*/
Model.prototype.getPath = function getPath() {
return this._path ? this._path.slice() : this._path;
};
/**
* This one is actually private. I would not use this without talking to
* jhusain, sdesai, or michaelbpaulson (github).
* @private
*/
Model.prototype._fromWhenceYouCame = function fromWhenceYouCame(allow) {
return this._clone({
_allowFromWhenceYouCame: allow === undefined ? true : allow
});
};
Model.prototype._getBoundValue = require(18);
Model.prototype._getVersion = require(23);
Model.prototype._getPathValuesAsPathMap = get.getWithPathsAsPathMap;
Model.prototype._getPathValuesAsJSONG = get.getWithPathsAsJSONGraph;
Model.prototype._setPathValues = require(69);
Model.prototype._setPathMaps = require(68);
Model.prototype._setJSONGs = require(67);
Model.prototype._setCache = require(68);
Model.prototype._invalidatePathValues = require(39);
Model.prototype._invalidatePathMaps = require(38);
},{"106":106,"121":121,"125":125,"18":18,"19":19,"21":21,"23":23,"24":24,"29":29,"38":38,"39":39,"4":4,"40":40,"44":44,"5":5,"50":50,"51":51,"52":52,"57":57,"58":58,"59":59,"6":6,"61":61,"65":65,"66":66,"67":67,"68":68,"69":69,"7":7,"70":70,"71":71,"78":78,"8":8,"88":88,"89":89,"90":90,"92":92}],4:[function(require,module,exports){
function ModelDataSourceAdapter(model) {
this._model = model._materialize().treatErrorsAsValues();
}
ModelDataSourceAdapter.prototype.get = function get(pathSets) {
return this._model.get.apply(this._model, pathSets)._toJSONG();
};
ModelDataSourceAdapter.prototype.set = function set(jsongResponse) {
return this._model.set(jsongResponse)._toJSONG();
};
ModelDataSourceAdapter.prototype.call = function call(path, args, suffixes, paths) {
var params = [path, args, suffixes];
Array.prototype.push.apply(params, paths);
return this._model.call.apply(this._model, params)._toJSONG();
};
module.exports = ModelDataSourceAdapter;
},{}],5:[function(require,module,exports){
var isFunction = require(86);
var hasOwn = require(81);
function ModelRoot(o) {
var options = o || {};
this.syncRefCount = 0;
this.expired = options.expired || [];
this.unsafeMode = options.unsafeMode || false;
this.cache = {};
if (isFunction(options.comparator)) {
this.comparator = options.comparator;
}
if (isFunction(options.errorSelector)) {
this.errorSelector = options.errorSelector;
}
if (isFunction(options.onChange)) {
this.onChange = options.onChange;
}
}
ModelRoot.prototype.errorSelector = function errorSelector(x, y) {
return y;
};
ModelRoot.prototype.comparator = function comparator(cacheNode, messageNode) {
if (hasOwn(cacheNode, "value") && hasOwn(messageNode, "value")) {
// They are the same only if the following fields are the same.
return cacheNode.value === messageNode.value &&
cacheNode.$type === messageNode.$type &&
cacheNode.$expires === messageNode.$expires;
}
return cacheNode === messageNode;
};
module.exports = ModelRoot;
},{"81":81,"86":86}],6:[function(require,module,exports){
module.exports = function fromWhenceYeCame() {
var reference = this._referenceContainer;
// Always true when this mode is false.
if (!this._allowFromWhenceYouCame) {
return true;
}
// If fromWhenceYouCame is true and the first set of keys did not have
// a reference, this case can happen. They are always valid.
if (reference === true) {
return true;
}
// was invalid before even derefing.
if (reference === false) {
return false;
}
// Its been disconnected (set over or collected) from the graph.
// eslint-disable-next-line camelcase
if (reference && reference.$_parent === undefined) {
return false;
}
// The reference has expired but has not been collected from the graph.
// eslint-disable-next-line camelcase
if (reference && reference.$_invalidated) {
return false;
}
return true;
};
},{}],7:[function(require,module,exports){
var InvalidDerefInputError = require(10);
var getCachePosition = require(20);
var CONTAINER_DOES_NOT_EXIST = "e";
var $ref = require(111);
module.exports = function deref(boundJSONArg) {
var absolutePath = boundJSONArg && boundJSONArg.$__path;
var refPath = boundJSONArg && boundJSONArg.$__refPath;
var toReference = boundJSONArg && boundJSONArg.$__toReference;
var referenceContainer;
// We deref and then ensure that the reference container is attached to
// the model.
if (absolutePath) {
var validContainer = CONTAINER_DOES_NOT_EXIST;
if (toReference) {
validContainer = false;
referenceContainer = getCachePosition(this, toReference);
// If the reference container is still a sentinel value then compare
// the reference value with refPath. If they are the same, then the
// model is still valid.
if (refPath && referenceContainer &&
referenceContainer.$type === $ref) {
var containerPath = referenceContainer.value;
var i = 0;
var len = refPath.length;
validContainer = true;
for (; validContainer && i < len; ++i) {
if (containerPath[i] !== refPath[i]) {
validContainer = false;
}
}
}
}
// Signal to the deref'd model that it has been disconnected from the
// graph or there is no _fromWhenceYouCame
if (!validContainer) {
referenceContainer = false;
}
// The container did not exist, therefore there is no reference
// container and fromWhenceYouCame should always return true.
else if (validContainer === CONTAINER_DOES_NOT_EXIST) {
referenceContainer = true;
}
return this._clone({
_path: absolutePath,
_referenceContainer: referenceContainer
});
}
throw new InvalidDerefInputError();
};
},{"10":10,"111":111,"20":20}],8:[function(require,module,exports){
var pathSyntax = require(125);
var getBoundValue = require(18);
var InvalidModelError = require(11);
module.exports = function derefSync(boundPathArg) {
var boundPath = pathSyntax.fromPath(boundPathArg);
if (!Array.isArray(boundPath)) {
throw new Error("Model#derefSync must be called with an Array path.");
}
var boundValue = getBoundValue(this, this._path.concat(boundPath), false);
var path = boundValue.path;
var node = boundValue.value;
var found = boundValue.found;
// If the node is not found or the node is found but undefined is returned,
// this happens when a reference is expired.
if (!found || node === undefined) {
return undefined;
}
if (node.$type) {
throw new InvalidModelError(path, path);
}
return this._clone({ _path: path });
};
},{"11":11,"125":125,"18":18}],9:[function(require,module,exports){
var applyErrorPrototype = require(15);
/**
* When a bound model attempts to retrieve JSONGraph it should throw an
* error.
*
* @private
*/
function BoundJSONGraphModelError() {
var instance = new Error("It is not legal to use the JSON Graph " +
"format from a bound Model. JSON Graph format" +
" can only be used from a root model.");
instance.name = "BoundJSONGraphModelError";
if (Object.setPrototypeOf) {
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
}
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, BoundJSONGraphModelError);
}
return instance;
}
applyErrorPrototype(BoundJSONGraphModelError);
module.exports = BoundJSONGraphModelError;
},{"15":15}],10:[function(require,module,exports){
var applyErrorPrototype = require(15);
/**
* An invalid deref input is when deref is used with input that is not generated
* from a get, set, or a call.
*
* @private
*/
function InvalidDerefInputError() {
var instance = new Error("Deref can only be used with a non-primitive object from get, set, or call.");
instance.name = "InvalidDerefInputError";
if (Object.setPrototypeOf) {
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
}
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, InvalidDerefInputError);
}
return instance;
}
applyErrorPrototype(InvalidDerefInputError);
module.exports = InvalidDerefInputError;
},{"15":15}],11:[function(require,module,exports){
var applyErrorPrototype = require(15);
/**
* An InvalidModelError can only happen when a user binds, whether sync
* or async to shorted value. See the unit tests for examples.
*
* @param {*} boundPath
* @param {*} shortedPath
*
* @private
*/
function InvalidModelError(boundPath, shortedPath) {
var instance = new Error("The boundPath of the model is not valid since a value or error was found before the path end.");
instance.name = "InvalidModelError";
instance.boundPath = boundPath;
instance.shortedPath = shortedPath;
if (Object.setPrototypeOf) {
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
}
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, InvalidModelError);
}
return instance;
}
applyErrorPrototype(InvalidModelError);
module.exports = InvalidModelError;
},{"15":15}],12:[function(require,module,exports){
var applyErrorPrototype = require(15);
/**
* InvalidSourceError happens when a dataSource syncronously throws
* an exception during a get/set/call operation.
*
* @param {Error} error - The error that was thrown.
*
* @private
*/
function InvalidSourceError(error) {
var instance = new Error("An exception was thrown when making a request.");
instance.name = "InvalidSourceError";
instance.innerError = error;
if (Object.setPrototypeOf) {
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
}
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, InvalidSourceError);
}
return instance;
}
applyErrorPrototype(InvalidSourceError);
module.exports = InvalidSourceError;
},{"15":15}],13:[function(require,module,exports){
var applyErrorPrototype = require(15);
/**
* A request can only be retried up to a specified limit. Once that
* limit is exceeded, then an error will be thrown.
*
* @param {*} missingOptimizedPaths
*
* @private
*/
function MaxRetryExceededError(missingOptimizedPaths) {
var instance = new Error("The allowed number of retries have been exceeded.");
instance.name = "MaxRetryExceededError";
instance.missingOptimizedPaths = missingOptimizedPaths || [];
if (Object.setPrototypeOf) {
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
}
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, MaxRetryExceededError);
}
return instance;
}
applyErrorPrototype(MaxRetryExceededError);
MaxRetryExceededError.is = function(e) {
return e && e.name === "MaxRetryExceededError";
};
module.exports = MaxRetryExceededError;
},{"15":15}],14:[function(require,module,exports){
var applyErrorPrototype = require(15);
/**
* Does not allow null in path
*
* @private
* @param {Object} [options] - Optional object containing additional error information
* @param {Array} [options.requestedPath] - The path that was being processed when the error occurred
*/
function NullInPathError(options) {
var requestedPathString = options && options.requestedPath && options.requestedPath.join ? options.requestedPath.join(", ") : "";
var instance = new Error("`null` and `undefined` are not allowed in branch key positions for requested path: " + requestedPathString);
instance.name = "NullInPathError";
if (Object.setPrototypeOf) {
Object.setPrototypeOf(instance, Object.getPrototypeOf(this));
}
if (Error.captureStackTrace) {
Error.captureStackTrace(instance, NullInPathError);
}
return instance;
}
applyErrorPrototype(NullInPathError);
module.exports = NullInPathError;
},{"15":15}],15:[function(require,module,exports){
function applyErrorPrototype(errorType) {
errorType.prototype = Object.create(Error.prototype, {
constructor: {
value: Error,
enumerable: false,
writable: true,
configurable: true
}
});
if (Object.setPrototypeOf) {
Object.setPrototypeOf(errorType, Error);
} else {
// eslint-disable-next-line
errorType.__proto__ = Error;
}
}
module.exports = applyErrorPrototype;
},{}],16:[function(require,module,exports){
var createHardlink = require(74);
var onValue = require(27);
var isExpired = require(31);
var $ref = require(111);
var promote = require(41);
/* eslint-disable no-constant-condition */
function followReference(model, root, nodeArg, referenceContainerArg,
referenceArg, seed, isJSONG) {
var node = nodeArg;
var reference = referenceArg;
var referenceContainer = referenceContainerArg;
var depth = 0;
var k, next;
while (true) {
if (depth === 0 && referenceContainer.$_context) {
depth = reference.length;
next = referenceContainer.$_context;
} else {
k = reference[depth++];
next = node[k];
}
if (next) {
var type = next.$type;
var value = type && next.value || next;
if (depth < reference.length) {
if (type) {
node = next;
break;
}
node = next;
continue;
}
// We need to report a value or follow another reference.
else {
node = next;
if (type && isExpired(next)) {
break;
}
if (!referenceContainer.$_context) {
createHardlink(referenceContainer, next);
}
// Restart the reference follower.
if (type === $ref) {
// Nulls out the depth, outerResults,
if (isJSONG) {
onValue(model, next, seed, null, null, null, null,
reference, reference.length, isJSONG);
} else {
promote(model._root, next);
}
depth = 0;
reference = value;
referenceContainer = next;
node = root;
continue;
}
break;
}
} else {
node = void 0;
}
break;
}
if (depth < reference.length && node !== void 0) {
var ref = [];
for (var i = 0; i < depth; i++) {
ref[i] = reference[i];
}
reference = ref;
}
return [node, reference, referenceContainer];
}
/* eslint-enable */
module.exports = followReference;
},{"111":111,"27":27,"31":31,"41":41,"74":74}],17:[function(require,module,exports){
var getCachePosition = require(20);
var InvalidModelError = require(11);
var BoundJSONGraphModelError = require(9);
function mergeInto(target, obj) {
/* eslint guard-for-in: 0 */
if (target === obj) {
return;
}
if (target === null || typeof target !== "object" || target.$type) {
return;
}
if (obj === null || typeof obj !== "object" || obj.$type) {
return;
}
for (var key in obj) {
// When merging over a temporary branch structure (for example, as produced by an error selector)
// with references, we don't want to mutate the path, particularly because it's also $_absolutePath
// on cache nodes
if (key === "$__path") {
continue;
}
var targetValue = target[key];
if (targetValue === undefined) {
target[key] = obj[key];
} else {
mergeInto(targetValue, obj[key]);
}
}
}
function defaultEnvelope(isJSONG) {
return isJSONG ? {jsonGraph: {}, paths: []} : {json: {}};
}
module.exports = function get(walk, isJSONG) {
return function innerGet(model, paths, seed) {
// Result valueNode not immutable for isJSONG.
var nextSeed = isJSONG ? seed : [{}];
var valueNode = nextSeed[0];
var results = {
values: nextSeed,
optimizedPaths: []
};
var cache = model._root.cache;
var boundPath = model._path;
var currentCachePosition = cache;
var optimizedPath, optimizedLength;
var i, len;
var requestedPath = [];
var derefInfo = [];
var referenceContainer;
// If the model is bound, then get that cache position.
if (boundPath.length) {
// JSONGraph output cannot ever be bound or else it will
// throw an error.
if (isJSONG) {
return {
criticalError: new BoundJSONGraphModelError()
};
}
// using _getOptimizedPath because that's a point of extension
// for polyfilling legacy falcor
optimizedPath = model._getOptimizedBoundPath();
optimizedLength = optimizedPath.length;
// We need to get the new cache position path.
currentCachePosition = getCachePosition(model, optimizedPath);
// If there was a short, then we 'throw an error' to the outside
// calling function which will onError the observer.
if (currentCachePosition && currentCachePosition.$type) {
return {
criticalError: new InvalidModelError(boundPath, optimizedPath)
};
}
referenceContainer = model._referenceContainer;
}
// Update the optimized path if we
else {
optimizedPath = [];
optimizedLength = 0;
}
for (i = 0, len = paths.length; i < len; i++) {
walk(model, cache, currentCachePosition, paths[i], 0,
valueNode, results, derefInfo, requestedPath, optimizedPath,
optimizedLength, isJSONG, false, referenceContainer);
}
// Merge in existing results.
// Default to empty envelope if no results were emitted
mergeInto(valueNode, paths.length ? seed[0] : defaultEnvelope(isJSONG));
return results;
};
};
},{"11":11,"20":20,"9":9}],18:[function(require,module,exports){
var getValueSync = require(22);
var InvalidModelError = require(11);
module.exports = function getBoundValue(model, pathArg, materialized) {
var path = pathArg;
var boundPath = pathArg;
var boxed, treatErrorsAsValues,
value, shorted, found;
boxed = model._boxed;
materialized = model._materialized;
treatErrorsAsValues = model._treatErrorsAsValues;
model._boxed = true;
model._materialized = materialized === undefined || materialized;
model._treatErrorsAsValues = true;
value = getValueSync(model, path.concat(null), true);
model._boxed = boxed;
model._materialized = materialized;
model._treatErrorsAsValues = treatErrorsAsValues;
path = value.optimizedPath;
shorted = value.shorted;
found = value.found;
value = value.value;
while (path.length && path[path.length - 1] === null) {
path.pop();
}
if (found && shorted) {
throw new InvalidModelError(boundPath, path);
}
return {
path: path,
value: value,
shorted: shorted,
found: found
};
};
},{"11":11,"22":22}],19:[function(require,module,exports){
var isInternalKey = require(87);
/**
* decends and copies the cache.
*/
module.exports = function getCache(cache) {
var out = {};
_copyCache(cache, out);
return out;
};
function cloneBoxedValue(boxedValue) {
var clonedValue = {};
var keys = Object.keys(boxedValue);
var key;
var i;
var l;
for (i = 0, l = keys.length; i < l; i++) {
key = keys[i];
if (!isInternalKey(key)) {
clonedValue[key] = boxedValue[key];
}
}
return clonedValue;
}
function _copyCache(node, out, fromKey) {
// copy and return
Object.
keys(node).
filter(function(k) {
// Its not an internal key and the node has a value. In the cache
// there are 3 possibilities for values.
// 1: A branch node.
// 2: A $type-value node.
// 3: undefined
// We will strip out 3
return !isInternalKey(k) && node[k] !== undefined;
}).
forEach(function(key) {
var cacheNext = node[key];
var outNext = out[key];
if (!outNext) {
outNext = out[key] = {};
}
// Paste the node into the out cache.
if (cacheNext.$type) {
var isObject = cacheNext.value && typeof cacheNext.value === "object";
var isUserCreatedcacheNext = !cacheNext.$_modelCreated;
var value;
if (isObject || isUserCreatedcacheNext) {
value = cloneBoxedValue(cacheNext);
} else {
value = cacheNext.value;
}
out[key] = value;
return;
}
_copyCache(cacheNext, outNext, key);
});
}
},{"87":87}],20:[function(require,module,exports){
/**
* getCachePosition makes a fast walk to the bound value since all bound
* paths are the most possible optimized path.
*
* @param {Model} model -
* @param {Array} path -
* @returns {Mixed} - undefined if there is nothing in this position.
* @private
*/
module.exports = function getCachePosition(model, path) {
var currentCachePosition = model._root.cache;
var depth = -1;
var maxDepth = path.length;
// The loop is simple now, we follow the current cache position until
//
while (++depth < maxDepth &&
currentCachePosition && !currentCachePosition.$type) {
currentCachePosition = currentCachePosition[path[depth]];
}
return currentCachePosition;
};
},{}],21:[function(require,module,exports){
var ModelResponse = require(52);
var pathSyntax = require(125);
module.exports = function getValue(path) {
var parsedPath = pathSyntax.fromPath(path);
var pathIdx = 0;
var pathLen = parsedPath.length;
while (++pathIdx < pathLen) {
if (typeof parsedPath[pathIdx] === "object") {
/* eslint-disable no-loop-func */
return new ModelResponse(function(o) {
o.onError(new Error("Paths must be simple paths"));
});
/* eslint-enable no-loop-func */
}
}
var self = this;
return new ModelResponse(function(obs) {
return self.get(parsedPath).subscribe(function(data) {
var curr = data.json;
var depth = -1;
var length = parsedPath.length;
while (curr && ++depth < length) {
curr = curr[parsedPath[depth]];
}
obs.onNext(curr);
}, function(err) {
obs.onError(err);
}, function() {
obs.onCompleted();
});
});
};
},{"125":125,"52":52}],22:[function(require,module,exports){
var followReference = require(16);
var clone = require(30);
var isExpired = require(31);
var promote = require(41);
var $ref = require(111);
var $atom = require(109);
var $error = require(110);
module.exports = function getValueSync(model, simplePath, noClone) {
var root = model._root.cache;
var len = simplePath.length;
var optimizedPath = [];
var shorted = false, shouldShort = false;
var depth = 0;
var key, i, next = root, curr = root, out = root, type, ref, refNode;
var found = true;
var expired = false;
while (next && depth < len) {
key = simplePath[depth++];
if (key !== null) {
next = curr[key];
optimizedPath[optimizedPath.length] = key;
}
if (!next) {
out = undefined;
shorted = true;
found = false;
break;
}
type = next.$type;
// A materialized item. There is nothing to deref to.
if (type === $atom && next.value === undefined) {
out = undefined;
found = false;
shorted = depth < len;
break;
}
// Up to the last key we follow references, ensure that they are not
// expired either.
if (depth < len) {
if (type === $ref) {
// If the reference is expired then we need to set expired to
// true.
if (isExpired(next)) {
expired = true;
out = undefined;
break;
}
ref = followReference(model, root, root, next, next.value);
refNode = ref[0];
// The next node is also set to undefined because nothing
// could be found, this reference points to nothing, so
// nothing must be returned.
if (!refNode) {
out = void 0;
next = void 0;
found = false;
break;
}
type = refNode.$type;
next = refNode;
optimizedPath = ref[1].slice(0);
}
if (type) {
break;
}
}
// If there is a value, then we have great success, else, report an undefined.
else {
out = next;
}
curr = next;
}
if (depth < len && !expired) {
// Unfortunately, if all that follows are nulls, then we have not shorted.
for (i = depth; i < len; ++i) {
if (simplePath[depth] !== null) {
shouldShort = true;
break;
}
}
// if we should short or report value. Values are reported on nulls.
if (shouldShort) {
shorted = true;
out = void 0;
} else {
out = next;
}
for (i = depth; i < len; ++i) {
if (simplePath[i] !== null) {
optimizedPath[optimizedPath.length] = simplePath[i];
}
}
}
// promotes if not expired
if (out && type) {
if (isExpired(out)) {
out = void 0;
} else {
promote(model._root, out);
}
}
// if (out && out.$type === $error && !model._treatErrorsAsValues) {
if (out && type === $error && !model._treatErrorsAsValues) {
/* eslint-disable no-throw-literal */
throw {
path: depth === len ? simplePath : simplePath.slice(0, depth),
value: out.value
};
/* eslint-enable no-throw-literal */
} else if (out && model._boxed) {
out = Boolean(type) && !noClone ? clone(out) : out;
} else if (!out && model._materialized) {
out = {$type: $atom};
} else if (out) {
out = out.value;
}
return {
value: out,
shorted: shorted,
optimizedPath: optimizedPath,
found: found
};
};
},{"109":109,"110":110,"111":111,"16":16,"30":30,"31":31,"41":41}],23:[function(require,module,exports){
var getValueSync = require(22);
module.exports = function _getVersion(model, path) {
// ultra fast clone for boxed values.
var gen = getValueSync({
_boxed: true,
_root: model._root,
_treatErrorsAsValues: model._treatErrorsAsValues
}, path, true).value;
var version = gen && gen.$_version;
return (version == null) ? -1 : version;
};
},{"22":22}],24:[function(require,module,exports){
var get = require(17);
var walkPath = require(33);
var getWithPathsAsPathMap = get(walkPath, false);
var getWithPathsAsJSONGraph = get(walkPath, true);
module.exports = {
getValueSync: require(22),
getBoundValue: require(18),
getWithPathsAsPathMap: getWithPathsAsPathMap,
getWithPathsAsJSONGraph: getWithPathsAsJSONGraph
};
},{"17":17,"18":18,"22":22,"33":33}],25:[function(require,module,exports){
var promote = require(41);
var clone = require(30);
module.exports = function onError(model, node, depth,
requestedPath, outerResults) {
var value = node.value;
if (!outerResults.errors) {
outerResults.errors = [];
}
if (model._boxed) {
value = clone(node);
}
outerResults.errors.push({
path: requestedPath.slice(0, depth),
value: value
});
promote(model._root, node);
};
},{"30":30,"41":41}],26:[function(require,module,exports){
module.exports = function onMissing(model, path, depth,
outerResults, requestedPath,
optimizedPath, optimizedLength) {
var pathSlice;
if (!outerResults.requestedMissingPaths) {
outerResults.requestedMissingPaths = [];
outerResults.optimizedMissingPaths = [];
}
if (depth < path.length) {
// If part of path has not been traversed, we need to ensure that there
// are no empty paths (range(1, 0) or empyt array)
var isEmpty = false;
for (var i = depth; i < path.length && !isEmpty; ++i) {
if (isEmptyAtom(path[i])) {
return;
}
}
pathSlice = path.slice(depth);
} else {
pathSlice = [];
}
concatAndInsertMissing(model, pathSlice, depth, requestedPath,
optimizedPath, optimizedLength, outerResults);
};
function concatAndInsertMissing(model, remainingPath, depth, requestedPath,
optimizedPath, optimizedLength, results) {
var requested = requestedPath.slice(0, depth);
Array.prototype.push.apply(requested, remainingPath);
results.requestedMissingPaths[results.requestedMissingPaths.length] = requested;
var optimized = optimizedPath.slice(0, optimizedLength);
Array.prototype.push.apply(optimized, remainingPath);
results.optimizedMissingPaths[results.optimizedMissingPaths.length] = optimized;
}
function isEmptyAtom(atom) {
if (atom === null || typeof atom !== "object") {
return false;
}
var isArray = Array.isArray(atom);
if (isArray && atom.length) {
return false;
}
// Empty array
else if (isArray) {
return true;
}
var from = atom.from;
var to = atom.to;
if (from === undefined || from <= to) {
return false;
}
return true;
}
},{}],27:[function(require,module,exports){
var promote = require(41);
var clone = require(30);
var $ref = require(111);
var $atom = require(109);
var $error = require(110);
module.exports = function onValue(model, node, seed, depth, outerResults,
branchInfo, requestedPath, optimizedPath,
optimizedLength, isJSONG) {
// Promote first. Even if no output is produced we should still promote.
if (node) {
promote(model._root, node);
}
// Preload
if (!seed) {
return;
}
var i, len, k, key, curr, prev = null, prevK;
var materialized = false, valueNode, nodeType = node && node.$type, nodeValue = node && node.value;
if (nodeValue === undefined) {
materialized = model._materialized;
}
// materialized
if (materialized) {
valueNode = {$type: $atom};
}
// Boxed Mode will clone the node.
else if (model._boxed) {
valueNode = clone(node);
}
// We don't want to emit references in json output
else if (!isJSONG && nodeType === $ref) {
valueNode = undefined;
}
// JSONG always clones the node.
else if (nodeType === $ref || nodeType === $error) {
if (isJSONG) {
valueNode = clone(node);
} else {
valueNode = nodeValue;
}
}
else if (isJSONG) {
var isObject = nodeValue && typeof nodeValue === "object";
var isUserCreatedNode = !node || !node.$_modelCreated;
if (isObject || isUserCreatedNode) {
valueNode = clone(node);
} else {
valueNode = nodeValue;
}
}
else if (node && nodeType === undefined && nodeValue === undefined) {
// Include an empty value for branch nodes
valueNode = {};
} else {
valueNode = nodeValue;
}
var hasValues = false;
if (isJSONG) {
curr = seed.jsonGraph;
if (!curr) {
hasValues = true;
curr = seed.jsonGraph = {};
seed.paths = [];
}
for (i = 0, len = optimizedLength - 1; i < len; i++) {
key = optimizedPath[i];
if (!curr[key]) {
hasValues = true;
curr[key] = {};
}
curr = curr[key];
}
// assign the last
key = optimizedPath[i];
// TODO: Special case? do string comparisons make big difference?
curr[key] = materialized ? {$type: $atom} : valueNode;
if (requestedPath) {
seed.paths.push(requestedPath.slice(0, depth));
}
}
// The output is pathMap and the depth is 0. It is just a
// value report it as the found JSON
else if (depth === 0) {
hasValues = true;
seed.json = valueNode;
}
// The output is pathMap but we need to build the pathMap before
// reporting the value.
else {
curr = seed.json;
if (!curr) {
hasValues = true;
curr = seed.json = {};
}
for (i = 0; i < depth - 1; i++) {
k = requestedPath[i];
// The branch info is already generated output from the walk algo
// with the required __path information on it.
if (!curr[k]) {
hasValues = true;
curr[k] = branchInfo[i];
}
prev = curr;
prevK = k;
curr = curr[k];
}
k = requestedPath[i];
if (valueNode !== undefined) {
if (k != null) {
hasValues = true;
if (!curr[k]) {
curr[k] = valueNode;
}
} else {
// We are protected from reaching here when depth is 1 and prev is
// undefined by the InvalidModelError and NullInPathError checks.
prev[prevK] = valueNode;
}
}
}
if (outerResults) {
outerResults.hasValues = hasValues;
}
};
},{"109":109,"110":110,"111":111,"30":30,"41":41}],28:[function(require,module,exports){
var isExpired = require(31);
var $error = require(110);
var onError = require(25);
var onValue = require(27);
var onMissing = require(26);
var isMaterialized = require(32);
var expireNode = require(76);
var currentCacheVersion = require(75);
/**
* When we land on a valueType (or nothing) then we need to report it out to
* the outerResults through errors, missing, or values.
*
* @private
*/
module.exports = function onValueType(
model, node, path, depth, seed, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength, isJSONG, fromReference) {
var currType = node && node.$type;
// There are is nothing here, ether report value, or report the value
// that is missing. If there is no type then report the missing value.
if (!node || !currType) {
var materialized = isMaterialized(model);
if (materialized || !isJSONG) {
onValue(model, node, seed, depth, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength,
isJSONG);
}
if (!materialized) {
onMissing(model, path, depth,
outerResults, requestedPath,
optimizedPath, optimizedLength);
}
return;
}
// If there are expired value, then report it as missing
else if (isExpired(node) &&
!(node.$_version === currentCacheVersion.getVersion() &&
node.$expires === 0)) {
if (!node.$_invalidated) {
expireNode(node, model._root.expired, model._root);
}
onMissing(model, path, depth,
outerResults, requestedPath,
optimizedPath, optimizedLength);
}
// If there is an error, then report it as a value if
else if (currType === $error) {
if (fromReference) {
requestedPath[depth] = null;
depth += 1;
}
if (isJSONG || model._treatErrorsAsValues) {
onValue(model, node, seed, depth, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength,
isJSONG);
} else {
onValue(model, undefined, seed, depth, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength,
isJSONG);
onError(model, node, depth, requestedPath, outerResults);
}
}
// Report the value
else {
if (fromReference) {
requestedPath[depth] = null;
depth += 1;
}
onValue(model, node, seed, depth, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength, isJSONG);
}
};
},{"110":110,"25":25,"26":26,"27":27,"31":31,"32":32,"75":75,"76":76}],29:[function(require,module,exports){
var pathSyntax = require(125);
var getValueSync = require(22);
module.exports = function _getValueSync(pathArg) {
var path = pathSyntax.fromPath(pathArg);
if (Array.isArray(path) === false) {
throw new Error("Model#_getValueSync must be called with an Array path.");
}
if (this._path.length) {
path = this._path.concat(path);
}
this._syncCheck("getValueSync");
return getValueSync(this, path).value;
};
},{"125":125,"22":22}],30:[function(require,module,exports){
// Copies the node
var privatePrefix = require(35);
module.exports = function clone(node) {
if (node === undefined) {
return node;
}
var outValue = {};
for (var k in node) {
if (k.lastIndexOf(privatePrefix, 0) === 0) {
continue;
}
outValue[k] = node[k];
}
return outValue;
};
},{"35":35}],31:[function(require,module,exports){
module.exports = require(85);
},{"85":85}],32:[function(require,module,exports){
module.exports = function isMaterialized(model) {
return model._materialized && !model._source;
};
},{}],33:[function(require,module,exports){
var followReference = require(16);
var onValueType = require(28);
var onValue = require(27);
var isExpired = require(31);
var iterateKeySet = require(137).iterateKeySet;
var $ref = require(111);
var promote = require(41);
module.exports = function walkPath(model, root, curr, path, depth, seed,
outerResults, branchInfo, requestedPath,
optimizedPathArg, optimizedLength, isJSONG,
fromReferenceArg, referenceContainerArg) {
var fromReference = fromReferenceArg;
var optimizedPath = optimizedPathArg;
var referenceContainer = referenceContainerArg;
// The walk is finished when:
// - there is no value in the current cache position
// - there is a JSONG leaf node in the current cache position
// - we've reached the end of the path
if (!curr || curr.$type || depth === path.length) {
onValueType(model, curr, path, depth, seed, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength,
isJSONG, fromReference);
return;
}
var keySet = path[depth];
var isKeySet = keySet !== null && typeof keySet === "object";
var iteratorNote = false;
var key = keySet;
if (isKeySet) {
iteratorNote = {};
key = iterateKeySet(keySet, iteratorNote);
}
var allowFromWhenceYouCame = model._allowFromWhenceYouCame;
var optimizedLengthPlus1 = optimizedLength + 1;
var nextDepth = depth + 1;
var refPath;
// loop over every key in the key set
do {
if (key == null) {
// Skip null/undefined/empty keysets in path and do not descend,
// but capture the partial path in the result
onValue(model, curr, seed, depth, outerResults, branchInfo,
requestedPath, optimizedPath, optimizedLength, isJSONG);
if (iteratorNote && !iteratorNote.done) {
key = iterateKeySet(keySet, iteratorNote);
}
continue;
}
fromReference = false;
optimizedPath[optimizedLength] = key;
requestedPath[depth] = key;
var next = curr[key];
var nextOptimizedPath = optimizedPath;
var nextOptimizedLength = optimizedLengthPlus1;
// If there is the next position we need to consider references.
if (next) {
var nType = next.$type;
var value = nType && next.value || next;
// If next is a reference follow it. If we are in JSONG mode,
// report that value into the seed without passing the requested
// path. If a requested path is passed to onValueType then it
// will add that path to the JSONGraph envelope under `paths`
if (nextDepth < path.length && nType &&
nType === $ref && !isExpired(next)) {
// promote the node so that the references don't get cleaned up.
promote(model._root, next);
if (isJSONG) {
onValue(model, next, seed, nextDepth, outerResults, null,
null, optimizedPath, nextOptimizedLength, isJSONG);
}
var ref = followReference(model, root, root, next,
value, seed, isJSONG);
fromReference = true;
next = ref[0];
refPath = ref[1];
referenceContainer = ref[2];
nextOptimizedPath = refPath.slice();
nextOptimizedLength = refPath.length;
}
// The next can be set to undefined by following a reference that
// does not exist.
if (next) {
var obj;
// There was a reference container.
if (referenceContainer && allowFromWhenceYouCame) {
obj = {
// eslint-disable-next-line camelcase
$__path: next.$_absolutePath,
// eslint-disable-next-line camelcase
$__refPath: referenceContainer.value,
// eslint-disable-next-line camelcase
$__toReference: referenceContainer.$_absolutePath
};
}
// There is no reference container meaning this request was
// neither from a model and/or the first n (depth) keys do not
// contain references.
else {
obj = {
// eslint-disable-next-line camelcase
$__path: next.$_absolutePath
};
}
branchInfo[depth] = obj;
}
}
// Recurse to the next level.
walkPath(model, root, next, path, nextDepth, seed, outerResults,
branchInfo, requestedPath, nextOptimizedPath,
nextOptimizedLength, isJSONG,
fromReference, referenceContainer);
// If the iteratorNote is not done, get the next key.
if (iteratorNote && !iteratorNote.done) {
key = iterateKeySet(keySet, iteratorNote);
}
} while (iteratorNote && !iteratorNote.done);
};
},{"111":111,"137":137,"16":16,"27":27,"28":28,"31":31,"41":41}],34:[function(require,module,exports){
"use strict";
function falcor(opts) {
return new falcor.Model(opts);
}
/**
* A filtering method for keys from a falcor json response. The only gotcha
* to this method is when the incoming json is undefined, then undefined will
* be returned.
*
* @public
* @param {Object} json - The json response from a falcor model.
* @returns {Array} - the keys that are in the model response minus the deref
* _private_ meta data.
*/
falcor.keys = function getJSONKeys(json) {
if (!json) {
return undefined;
}
return Object.
keys(json).
filter(function(key) {
return key !== "$__path";
});
};
module.exports = falcor;
falcor.Model = require(3);
},{"3":3}],35:[function(require,module,exports){
var reservedPrefix = require(37);
module.exports = reservedPrefix + "_";
},{"37":37}],36:[function(require,module,exports){
module.exports = require(35) + "ref";
},{"35":35}],37:[function(require,module,exports){
module.exports = "$";
},{}],38:[function(require,module,exports){
var createHardlink = require(74);
var __prefix = require(37);
var $ref = require(111);
var getBoundValue = require(18);
var promote = require(41);
var getSize = require(78);
var hasOwn = require(81);
var isObject = require(90);
var isExpired = require(85);
var isFunction = require(86);
var isPrimitive = require(92);
var expireNode = require(76);
var incrementVersion = require(82);
var updateNodeAncestors = require(105);
var removeNodeAndDescendants = require(99);
/**
* Sets a list of PathMaps into a JSON Graph.
* @function
* @param {Object} model - the Model for which to insert the PathMaps.
* @param {Array.<PathMapEnvelope>} pathMapEnvelopes - the a list of @PathMapEnvelopes to set.
*/
module.exports = function invalidatePathMaps(model, pathMapEnvelopes) {
var modelRoot = model._root;
var lru = modelRoot;
var expired = modelRoot.expired;
var version = incrementVersion();
var bound = model._path;
var cache = modelRoot.cache;
var node = bound.length ? getBoundValue(model, bound).value : cache;
var parent = node.$_parent || cache;
var initialVersion = cache.$_version;
var pathMapIndex = -1;
var pathMapCount = pathMapEnvelopes.length;
while (++pathMapIndex < pathMapCount) {
var pathMapEnvelope = pathMapEnvelopes[pathMapIndex];
invalidatePathMap(pathMapEnvelope.json, cache, parent, node, version, expired, lru);
}
var newVersion = cache.$_version;
var rootChangeHandler = modelRoot.onChange;
if (isFunction(rootChangeHandler) && initialVersion !== newVersion) {
rootChangeHandler();
}
};
function invalidatePathMap(pathMap, root, parent, node, version, expired, lru) {
if (isPrimitive(pathMap) || pathMap.$type) {
return;
}
for (var key in pathMap) {
if (key[0] !== __prefix && hasOwn(pathMap, key)) {
var child = pathMap[key];
var branch = isObject(child) && !child.$type;
var results = invalidateNode(root, parent, node, key, branch, expired, lru);
var nextNode = results[0];
var nextParent = results[1];
if (nextNode) {
if (branch) {
invalidatePathMap(child, root, nextParent, nextNode, version, expired, lru);
} else if (removeNodeAndDescendants(nextNode, nextParent, key, lru)) {
updateNodeAncestors(nextParent, getSize(nextNode), lru, version);
}
}
}
}
}
function invalidateReference(root, node, expired, lru) {
if (isExpired(node)) {
expireNode(node, expired, lru);
return [undefined, root];
}
promote(lru, node);
var container = node;
var reference = node.value;
var parent = root;
node = node.$_context;
if (node != null) {
parent = node.$_parent || root;
} else {
var index = 0;
var count = reference.length - 1;
parent = node = root;
do {
var key = reference[index];
var branch = index < count;
var results = invalidateNode(root, parent, node, key, branch, expired, lru);
node = results[0];
if (isPrimitive(node)) {
return results;
}
parent = results[1];
} while (index++ < count);
if (container.$_context !== node) {
createHardlink(container, node);
}
}
return [node, parent];
}
function invalidateNode(root, parent, node, key, branch, expired, lru) {
var type = node.$type;
while (type === $ref) {
var results = invalidateReference(root, node, expired, lru);
node = results[0];
if (isPrimitive(node)) {
return results;
}
parent = results[1];
type = node && node.$type;
}
if (type !== void 0) {
return [node, parent];
}
if (key == null) {
if (branch) {
throw new Error("`null` is not allowed in branch key positions.");
} else if (node) {
key = node.$_key;
}
} else {
parent = node;
node = parent[key];
}
return [node, parent];
}
},{"105":105,"111":111,"18":18,"37":37,"41":41,"74":74,"76":76,"78":78,"81":81,"82":82,"85":85,"86":86,"90":90,"92":92,"99":99}],39:[function(require,module,exports){
var __ref = require(36);
var $ref = require(111);
var getBoundValue = require(18);
var promote = require(41);
var getSize = require(78);
var isExpired = require(85);
var isFunction = require(86);
var isPrimitive = require(92);
var expireNode = require(76);
var iterateKeySet = require(137).iterateKeySet;
var incrementVersion = require(82);
var updateNodeAncestors = require(105);
var removeNodeAndDescendants = require(99);
/**
* Invalidates a list of Paths in a JSON Graph.
* @function
* @param {Object} model - the Model for which to insert the PathValues.
* @param {Array.<PathValue>} paths - the PathValues to set.
*/
module.exports = function invalidatePathSets(model, paths) {
var modelRoot = model._root;
var lru = modelRoot;
var expired = modelRoot.expired;
var version = incrementVersion();
var bound = model._path;
var cache = modelRoot.cache;
var node = bound.length ? getBoundValue(model, bound).value : cache;
// eslint-disable-next-line camelcase
var parent = node.$_parent || cache;
// eslint-disable-next-line camelcase
var initialVersion = cache.$_version;
var pathIndex = -1;
var pathCount = paths.length;
while (++pathIndex < pathCount) {
var path = paths[pathIndex];
invalidatePathSet(path, 0, cache, parent, node, version, expired, lru);
}
// eslint-disable-next-line camelcase
var newVersion = cache.$_version;
var rootChangeHandler = modelRoot.onChange;
if (isFunction(rootChangeHandler) && initialVersion !== newVersion) {
rootChangeHandler();
}
};
function invalidatePathSet(
path, depth, root, parent, node,
version, expired, lru) {
var note = {};
var branch = depth < path.length - 1;
var keySet = path[depth];
var key = iterateKeySet(keySet, note);
do {
var results = invalidateNode(root, parent, node, key, branch, expired, lru);
var nextNode = results[0];
var nextParent = results[1];
if (nextNode) {
if (branch) {
invalidatePathSet(
path, depth + 1,
root, nextParent, nextNode,
version, expired, lru
);
} else if (removeNodeAndDescendants(nextNode, nextParent, key, lru, undefined)) {
updateNodeAncestors(nextParent, getSize(nextNode), lru, version);
}
}
key = iterateKeySet(keySet, note);
} while (!note.done);
}
function invalidateReference(root, node, expired, lru) {
if (isExpired(node)) {
expireNode(node, expired, lru);
return [undefined, root];
}
promote(lru, node);
var container = node;
var reference = node.value;
var parent = root;
// eslint-disable-next-line camelcase
node = node.$_context;
if (node != null) {
// eslint-disable-next-line camelcase
parent = node.$_parent || root;
} else {
var index = 0;
var count = reference.length - 1;
parent = node = root;
do {
var key = reference[index];
var branch = index < count;
var results = invalidateNode(root, parent, node, key, branch, expired, lru);
node = results[0];
if (isPrimitive(node)) {
return results;
}
parent = results[1];
} while (index++ < count);
// eslint-disable-next-line camelcase
if (container.$_context !== node) {
// eslint-disable-next-line camelcase
var backRefs = node.$_refsLength || 0;
// eslint-disable-next-line camelcase
node.$_refsLength = backRefs + 1;
node[__ref + backRefs] = container;
// eslint-disable-next-line camelcase
container.$_context = node;
// eslint-disable-next-line camelcase
container.$_refIndex = backRefs;
}
}
return [node, parent];
}
function invalidateNode(root, parent, node, key, branch, expired, lru) {
var type = node.$type;
while (type === $ref) {
var results = invalidateReference(root, node, expired, lru);
node = results[0];
if (isPrimitive(node)) {
return results;
}
parent = results[1];
type = node.$type;
}
if (type !== void 0) {
return [node, parent];
}
if (key == null) {
if (branch) {
throw new Error("`null` is not allowed in branch key positions.");
} else if (node) {
key = node.$_key;
}
} else {
parent = node;
node = parent[key];
}
return [node, parent];
}
},{"105":105,"111":111,"137":137,"18":18,"36":36,"41":41,"76":76,"78":78,"82":82,"85":85,"86":86,"92":92,"99":99}],40:[function(require,module,exports){
var removeNode = require(98);
var updateNodeAncestors = require(105);
module.exports = function collect(lru, expired, totalArg, max, ratioArg, version) {
var total = totalArg;
var ratio = ratioArg;
if (typeof ratio !== "number") {
ratio = 0.75;
}
var shouldUpdate = typeof version === "number";
var targetSize = max * ratio;
var parent, node, size;
node = expired.pop();
while (node) {
size = node.$size || 0;
total -= size;
if (shouldUpdate === true) {
updateNodeAncestors(node, size, lru, version);
// eslint-disable-next-line camelcase
} else if (parent = node.$_parent) { // eslint-disable-line no-cond-assign
// eslint-disable-next-line camelcase
removeNode(node, parent, node.$_key, lru);
}
node = expired.pop();
}
if (total >= max) {
// eslint-disable-next-line camelcase
var prev = lru.$_tail;
node = prev;
while ((total >= targetSize) && node) {
// eslint-disable-next-line camelcase
prev = prev.$_prev;
size = node.$size || 0;
total -= size;
if (shouldUpdate === true) {
updateNodeAncestors(node, size, lru, version);
}
node = prev;
}
// eslint-disable-next-line camelcase
lru.$_tail = lru.$_prev = node;
if (node == null) {
// eslint-disable-next-line camelcase
lru.$_head = lru.$_next = undefined;
} else {
// eslint-disable-next-line camelcase
node.$_next = undefined;
}
}
};
},{"105":105,"98":98}],41:[function(require,module,exports){
var EXPIRES_NEVER = require(112);
// [H] -> Next -> ... -> [T]
// [T] -> Prev -> ... -> [H]
module.exports = function lruPromote(root, object) {
// Never promote node.$expires === 1. They cannot expire.
if (object.$expires === EXPIRES_NEVER) {
return;
}
// eslint-disable-next-line camelcase
var head = root.$_head;
// Nothing is in the cache.
if (!head) {
// eslint-disable-next-line camelcase
root.$_head = root.$_tail = object;
return;
}
if (head === object) {
return;
}
// The item always exist in the cache since to get anything in the
// cache it first must go through set.
// eslint-disable-next-line camelcase
var prev = object.$_prev;
// eslint-disable-next-line camelcase
var next = object.$_next;
if (next) {
// eslint-disable-next-line camelcase
next.$_prev = prev;
}
if (prev) {
// eslint-disable-next-line camelcase
prev.$_next = next;
}
// eslint-disable-next-line camelcase
object.$_prev = undefined;
// Insert into head position
// eslint-disable-next-line camelcase
root.$_head = object;
// eslint-disable-next-line camelcase
object.$_next = head;
// eslint-disable-next-line camelcase
head.$_prev = object;
// If the item we promoted was the tail, then set prev to tail.
// eslint-disable-next-line camelcase
if (object === root.$_tail) {
// eslint-disable-next-line camelcase
root.$_tail = prev;
}
};
},{"112":112}],42:[function(require,module,exports){
module.exports = function lruSplice(root, object) {
// Its in the cache. Splice out.
// eslint-disable-next-line camelcase
var prev = object.$_prev;
// eslint-disable-next-line camelcase
var next = object.$_next;
if (next) {
// eslint-disable-next-line camelcase
next.$_prev = prev;
}
if (prev) {
// eslint-disable-next-line camelcase
prev.$_next = next;
}
// eslint-disable-next-line camelcase
object.$_prev = object.$_next = undefined;
// eslint-disable-next-line camelcase
if (object === root.$_head) {
// eslint-disable-next-line camelcase
root.$_head = next;
}
// eslint-disable-next-line camelcase
if (object === root.$_tail) {
// eslint-disable-next-line camelcase
root.$_tail = prev;
}
};
},{}],43:[function(require,module,exports){
var complement = require(46);
var flushGetRequest = require(47);
var incrementVersion = require(82);
var currentCacheVersion = require(75);
var REQUEST_ID = 0;
var GetRequestType = require(45).GetRequest;
var setJSONGraphs = require(67);
var setPathValues = require(69);
var $error = require(110);
var emptyArray = [];
var InvalidSourceError = require(12);
/**
* Creates a new GetRequest. This GetRequest takes a scheduler and
* the request queue. Once the scheduler fires, all batched requests
* will be sent to the server. Upon request completion, the data is
* merged back into the cache and all callbacks are notified.
*
* @param {Scheduler} scheduler -
* @param {RequestQueueV2} requestQueue -
* @param {number} attemptCount
*/
var GetRequestV2 = function(scheduler, requestQueue, attemptCount) {
this.sent = false;
this.scheduled = false;
this.requestQueue = requestQueue;
this.id = ++REQUEST_ID;
this.type = GetRequestType;
this._scheduler = scheduler;
this._attemptCount = attemptCount;
this._pathMap = {};
this._optimizedPaths = [];
this._requestedPaths = [];
this._callbacks = [];
this._count = 0;
this._disposable = null;
this._collapsed = null;
this._disposed = false;
};
GetRequestV2.prototype = {
/**
* batches the paths that are passed in. Once the request is complete,
* all callbacks will be called and the request will be removed from
* parent queue.
* @param {Array} requestedPaths -
* @param {Array} optimizedPaths -
* @param {Function} callback -
*/
batch: function(requestedPaths, optimizedPaths, callback) {
var self = this;
var batchedOptPathSets = self._optimizedPaths;
var batchedReqPathSets = self._requestedPaths;
var batchedCallbacks = self._callbacks;
var batchIx = batchedOptPathSets.length;
// If its not sent, simply add it to the requested paths
// and callbacks.
batchedOptPathSets[batchIx] = optimizedPaths;
batchedReqPathSets[batchIx] = requestedPaths;
batchedCallbacks[batchIx] = callback;
++self._count;
// If it has not been scheduled, then schedule the action
if (!self.scheduled) {
self.scheduled = true;
var flushedDisposable;
var scheduleDisposable = self._scheduler.schedule(function() {
flushedDisposable = flushGetRequest(self, batchedOptPathSets, function(err, data) {
var i, fn, len;
var model = self.requestQueue.model;
self.requestQueue.removeRequest(self);
self._disposed = true;
if (model._treatDataSourceErrorsAsJSONGraphErrors ? err instanceof InvalidSourceError : !!err) {
for (i = 0, len = batchedCallbacks.length; i < len; ++i) {
fn = batchedCallbacks[i];
if (fn) {
fn(err);
}
}
return;
}
// If there is at least one callback remaining, then
// callback the callbacks.
if (self._count) {
// currentVersion will get added to each inserted
// node as node.$_version inside of self._merge.
//
// atom values just downloaded with $expires: 0
// (now-expired) will get assigned $_version equal
// to currentVersion, and checkCacheAndReport will
// later consider those nodes to not have expired
// for the duration of current event loop tick
//
// we unset currentCacheVersion after all callbacks
// have been called, to ensure that only these
// particular callbacks and any synchronous model.get
// callbacks inside of these, get the now-expired
// values
var currentVersion = incrementVersion.getCurrentVersion();
currentCacheVersion.setVersion(currentVersion);
var mergeContext = { hasInvalidatedResult: false };
var pathsErr = model._useServerPaths && data && data.paths === undefined ?
new Error("Server responses must include a 'paths' field when Model._useServerPaths === true") : undefined;
if (!pathsErr) {
self._merge(batchedReqPathSets, err, data, mergeContext);
}
// Call the callbacks. The first one inserts all
// the data so that the rest do not have consider
// if their data is present or not.
for (i = 0, len = batchedCallbacks.length; i < len; ++i) {
fn = batchedCallbacks[i];
if (fn) {
fn(pathsErr || err, data, mergeContext.hasInvalidatedResult);
}
}
currentCacheVersion.setVersion(null);
}
});
self._disposable = flushedDisposable;
});
// If the scheduler is sync then `flushedDisposable` will be
// defined, and we want to use it, because that's what aborts an
// in-flight XHR request, for example.
// But if the scheduler is async, then `flushedDisposable` won't be
// defined yet, and so we must use the scheduler's disposable until
// `flushedDisposable` is defined. Since we want to still use
// `flushedDisposable` once it is defined (to be able to abort in-
// flight XHR requests), hence the reassignment of `_disposable`
// above.
self._disposable = flushedDisposable || scheduleDisposable;
}
// Disposes this batched request. This does not mean that the
// entire request has been disposed, but just the local one, if all
// requests are disposed, then the outer disposable will be removed.
return createDisposable(self, batchIx);
},
/**
* Attempts to add paths to the outgoing request. If there are added
* paths then the request callback will be added to the callback list.
* Handles adding partial paths as well
*
* @returns {Array} - whether new requested paths were inserted in this
* request, the remaining paths that could not be added,
* and disposable for the inserted requested paths.
*/
add: function(requested, optimized, callback) {
// uses the length tree complement calculator.
var self = this;
var complementResult = complement(requested, optimized, self._pathMap);
var inserted = false;
var disposable = false;
// If we found an intersection, then just add new callback
// as one of the dependents of that request
if (complementResult.intersection.length) {
inserted = true;
var batchIx = self._callbacks.length;
self._callbacks[batchIx] = callback;
self._requestedPaths[batchIx] = complementResult.intersection;
self._optimizedPaths[batchIx] = [];
++self._count;
disposable = createDisposable(self, batchIx);
}
return [inserted, complementResult.requestedComplement, complementResult.optimizedComplement, disposable];
},
/**
* merges the response into the model"s cache.
*/
_merge: function(requested, err, data, mergeContext) {
var self = this;
var model = self.requestQueue.model;
var modelRoot = model._root;
var errorSelector = modelRoot.errorSelector;
var comparator = modelRoot.comparator;
var boundPath = model._path;
gitextract_2ph5kury/ ├── .bithoundrc ├── .editorconfig ├── .eslintrc ├── .github/ │ └── workflows/ │ ├── ci.yml │ └── docs.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE.txt ├── MIGRATIONS.md ├── OSSMETADATA ├── README.md ├── all.js ├── authors.txt ├── bower.json ├── browser.js ├── build/ │ ├── deploy-ghpages.sh │ ├── falcor-jsdoc-template/ │ │ ├── README.md │ │ ├── publish.js │ │ └── tmpl/ │ │ ├── augments.tmpl │ │ ├── container.tmpl │ │ ├── details.tmpl │ │ ├── example.tmpl │ │ ├── examples.tmpl │ │ ├── exceptions.tmpl │ │ ├── layout.tmpl │ │ ├── mainpage.tmpl │ │ ├── members.tmpl │ │ ├── method.tmpl │ │ ├── navigation-subgroup.tmpl │ │ ├── navigation.tmpl │ │ ├── params.tmpl │ │ ├── properties.tmpl │ │ ├── returns.tmpl │ │ ├── source.tmpl │ │ ├── tutorial.tmpl │ │ └── type.tmpl │ ├── gulp-build.js │ ├── gulp-clean.js │ ├── gulp-perf.js │ └── jsdoc.json ├── conf.json ├── deployKey.enc ├── dist/ │ ├── falcor.all.js │ └── falcor.browser.js ├── doc/ │ ├── DataSource.html │ ├── FromEsObserverAdapter.html │ ├── Model.html │ ├── Model.js.html │ ├── ModelResponse.html │ ├── ModelResponseObserver.html │ ├── Observable.html │ ├── Subscription.html │ ├── ToEsSubscriptionAdapter.html │ ├── get_getCache.js.html │ ├── global.html │ ├── index.html │ ├── index.js.html │ ├── internal_index.js.html │ ├── invalidate_invalidatePathMaps.js.html │ ├── invalidate_invalidatePathSets.js.html │ ├── request_GetRequestV2.js.html │ ├── request_RequestQueueV2.js.html │ ├── request_complement.js.html │ ├── response_AssignableDisposable.js.html │ ├── response_ModelResponse.js.html │ ├── response_ModelResponseObserver.js.html │ ├── response_get_GetResponse.js.html │ ├── response_set_SetResponse.js.html │ ├── response_set_setGroupsIntoCache.js.html │ ├── response_set_setRequestCycle.js.html │ ├── set_setJSONGraphs.js.html │ ├── set_setPathMaps.js.html │ ├── set_setPathValues.js.html │ ├── support_reconstructPath.js.html │ ├── toEsObservable.js.html │ ├── typedefs_Atom.js.html │ ├── typedefs_DataSource.js.html │ ├── typedefs_JSONEnvelope.js.html │ ├── typedefs_JSONGraph.js.html │ ├── typedefs_JSONGraphEnvelope.js.html │ ├── typedefs_Key.js.html │ ├── typedefs_KeySet.js.html │ ├── typedefs_Observable.js.html │ ├── typedefs_Path.js.html │ ├── typedefs_PathSet.js.html │ ├── typedefs_PathValue.js.html │ └── typedefs_Range.js.html ├── examples/ │ └── datasource/ │ └── webWorkerSource.js ├── gulpfile.js ├── lib/ │ ├── Model.js │ ├── ModelDataSourceAdapter.js │ ├── ModelRoot.js │ ├── deref/ │ │ ├── hasValidParentReference.js │ │ ├── index.js │ │ └── sync.js │ ├── errors/ │ │ ├── BoundJSONGraphModelError.js │ │ ├── InvalidDerefInputError.js │ │ ├── InvalidModelError.js │ │ ├── InvalidSourceError.js │ │ ├── MaxRetryExceededError.js │ │ ├── NullInPathError.js │ │ └── applyErrorPrototype.js │ ├── get/ │ │ ├── followReference.js │ │ ├── get.js │ │ ├── getBoundValue.js │ │ ├── getCache.js │ │ ├── getCachePosition.js │ │ ├── getValue.js │ │ ├── getValueSync.js │ │ ├── getVersion.js │ │ ├── index.js │ │ ├── onError.js │ │ ├── onMissing.js │ │ ├── onValue.js │ │ ├── onValueType.js │ │ ├── sync.js │ │ ├── util/ │ │ │ ├── clone.js │ │ │ ├── isExpired.js │ │ │ ├── isMaterialzed.js │ │ │ └── isPathValue.js │ │ └── walkPath.js │ ├── index.js │ ├── internal/ │ │ ├── absolutePath.js │ │ ├── context.js │ │ ├── head.js │ │ ├── index.js │ │ ├── invalidated.js │ │ ├── key.js │ │ ├── model-created.js │ │ ├── next.js │ │ ├── parent.js │ │ ├── path.js │ │ ├── prev.js │ │ ├── privatePrefix.js │ │ ├── ref-index.js │ │ ├── ref.js │ │ ├── refs-length.js │ │ ├── reservedPrefix.js │ │ ├── tail.js │ │ └── version.js │ ├── invalidate/ │ │ ├── invalidatePathMaps.js │ │ └── invalidatePathSets.js │ ├── lru/ │ │ ├── collect.js │ │ ├── promote.js │ │ └── splice.js │ ├── request/ │ │ ├── GetRequestV2.js │ │ ├── RequestQueueV2.js │ │ ├── RequestTypes.js │ │ ├── complement.js │ │ ├── flushGetRequest.js │ │ └── sendSetRequest.js │ ├── response/ │ │ ├── AssignableDisposable.js │ │ ├── CallResponse.js │ │ ├── InvalidateResponse.js │ │ ├── ModelResponse.js │ │ ├── ModelResponseObserver.js │ │ ├── get/ │ │ │ ├── GetResponse.js │ │ │ ├── checkCacheAndReport.js │ │ │ ├── getRequestCycle.js │ │ │ ├── getWithPaths.js │ │ │ ├── index.js │ │ │ └── validInput.js │ │ └── set/ │ │ ├── SetResponse.js │ │ ├── index.js │ │ ├── setGroupsIntoCache.js │ │ ├── setRequestCycle.js │ │ └── setValidInput.js │ ├── schedulers/ │ │ ├── ASAPScheduler.js │ │ ├── ImmediateScheduler.js │ │ └── TimeoutScheduler.js │ ├── set/ │ │ ├── index.js │ │ ├── setJSONGraphs.js │ │ ├── setPathMaps.js │ │ ├── setPathValues.js │ │ ├── setValue.js │ │ └── sync.js │ ├── support/ │ │ ├── array-flat-map.js │ │ ├── clone.js │ │ ├── createHardlink.js │ │ ├── currentCacheVersion.js │ │ ├── expireNode.js │ │ ├── getExpires.js │ │ ├── getSize.js │ │ ├── getTimestamp.js │ │ ├── getType.js │ │ ├── hasOwn.js │ │ ├── identity.js │ │ ├── incrementVersion.js │ │ ├── insertNode.js │ │ ├── isAlreadyExpired.js │ │ ├── isExpired.js │ │ ├── isFunction.js │ │ ├── isInternalKey.js │ │ ├── isJSONEnvelope.js │ │ ├── isJSONGraphEnvelope.js │ │ ├── isObject.js │ │ ├── isPathInvalidation.js │ │ ├── isPathValue.js │ │ ├── isPrimitive.js │ │ ├── mergeJSONGraphNode.js │ │ ├── mergeValueOrInsertBranch.js │ │ ├── noop.js │ │ ├── now.js │ │ ├── reconstructPath.js │ │ ├── removeNode.js │ │ ├── removeNodeAndDescendants.js │ │ ├── replaceNode.js │ │ ├── transferBackReferences.js │ │ ├── unlinkBackReferences.js │ │ ├── unlinkForwardReference.js │ │ ├── updateBackReferenceVersions.js │ │ ├── updateNodeAncestors.js │ │ ├── validateInput.js │ │ └── wrapNode.js │ ├── toEsObservable.js │ ├── typedefs/ │ │ ├── Atom.js │ │ ├── DataSource.js │ │ ├── JSONEnvelope.js │ │ ├── JSONGraph.js │ │ ├── JSONGraphEnvelope.js │ │ ├── Key.js │ │ ├── KeySet.js │ │ ├── Observable.js │ │ ├── Path.js │ │ ├── PathSet.js │ │ ├── PathValue.js │ │ └── Range.js │ ├── types/ │ │ ├── atom.js │ │ ├── error.js │ │ └── ref.js │ └── values/ │ ├── expires-never.js │ └── expires-now.js ├── package.json ├── performance/ │ ├── README.md │ ├── TriggerDataSource.js │ ├── browser.js │ ├── device.js │ ├── formatter/ │ │ ├── CSVFormatter.js │ │ └── CSVTransform.js │ ├── karma.conf.js │ ├── models/ │ │ ├── index.js │ │ └── legacy/ │ │ ├── _.js │ │ ├── _Cache.js │ │ ├── index.js │ │ └── macro/ │ │ └── _Falcor.js │ ├── node.js │ ├── reporters/ │ │ ├── browserTestReporter.js │ │ ├── karmaBenchmarkCSVReporter.js │ │ └── nodeTestReporter.js │ ├── scripts/ │ │ └── transformCSV.js │ ├── testRunner.js │ └── tests/ │ ├── clone/ │ │ └── clone.perf.js │ ├── deref/ │ │ └── index.js │ ├── get/ │ │ ├── get.core.perf.js │ │ ├── get.perf.js │ │ ├── onValue.perf.js │ │ └── walk.perf.js │ ├── inMemoryCache.js │ ├── lru/ │ │ └── index.js │ ├── request/ │ │ └── request-queue.js │ ├── set/ │ │ └── set.json-graph.perf.js │ ├── standard.js │ ├── testMerge.js │ └── testSuite.js ├── server.js ├── test/ │ ├── .eslintrc.yaml │ ├── CacheGenerator.js │ ├── Model.spec.js │ ├── cleanData.js │ ├── data/ │ │ ├── Cache.js │ │ ├── ErrorDataSource.js │ │ ├── LocalDataSource.js │ │ ├── ReducedCache.js │ │ ├── asyncifyDataSource.js │ │ └── expected/ │ │ ├── Bound.js │ │ ├── Complex.js │ │ ├── References.js │ │ ├── Values.js │ │ └── index.js │ ├── falcor/ │ │ ├── call/ │ │ │ └── call.spec.js │ │ ├── deref/ │ │ │ ├── deref.errors.spec.js │ │ │ ├── deref.hasValidParentReference.spec.js │ │ │ └── deref.spec.js │ │ ├── error/ │ │ │ └── error.spec.js │ │ ├── get/ │ │ │ ├── get.cache-only.spec.js │ │ │ ├── get.cacheAsDataSource.spec.js │ │ │ ├── get.clone.spec.js │ │ │ ├── get.dataSource-and-bind.spec.js │ │ │ ├── get.dataSource-and-cache.spec.js │ │ │ ├── get.dataSource-only.spec.js │ │ │ ├── get.gen.spec.js │ │ │ ├── get.model.adapter.spec.js │ │ │ └── get.pathSyntax.spec.js │ │ ├── invalidate/ │ │ │ ├── invalidate.cache-only.spec.js │ │ │ └── invalidate.change-handler.spec.js │ │ ├── operations.spec.js │ │ ├── schedulers/ │ │ │ └── schedulers.spec.js │ │ └── set/ │ │ ├── set.cache-only.spec.js │ │ ├── set.cacheAsDataSource-and-cache.spec.js │ │ ├── set.change-handler.spec.js │ │ ├── set.dataSource-and-bind.spec.js │ │ ├── set.dataSource-and-cache.spec.js │ │ ├── set.dataSource-only.spec.js │ │ ├── set.pathSyntax.spec.js │ │ └── set.setCache.spec.js │ ├── get-core/ │ │ ├── deref.spec.js │ │ ├── edges.spec.js │ │ ├── errors.spec.js │ │ ├── get.cache.spec.js │ │ ├── missing.spec.js │ │ ├── null.spec.js │ │ ├── references.spec.js │ │ └── values.spec.js │ ├── getCoreRunner.js │ ├── getTestRunner.js │ ├── hardlink/ │ │ ├── hardlink.add.spec.js │ │ └── hardlink.remove.spec.js │ ├── integration/ │ │ ├── call.spec.js │ │ ├── dedupe.spec.js │ │ ├── express.spec.js │ │ └── get.spec.js │ ├── internal/ │ │ ├── ModelRoot.comparator.spec.js │ │ ├── request/ │ │ │ ├── GetRequest.add.spec.js │ │ │ ├── GetRequest.batch.spec.js │ │ │ ├── GetRequest.spec.js │ │ │ ├── RequestQueue.get.spec.js │ │ │ └── complement.spec.js │ │ └── sync/ │ │ └── _setValueSync.spec.js │ ├── invalidate/ │ │ ├── invalidate.spec.js │ │ ├── pathMaps.spec.js │ │ └── pathSets.spec.js │ ├── isAssertionError.js │ ├── lru/ │ │ ├── lru.promote.get.spec.js │ │ ├── lru.promote.set.spec.js │ │ ├── lru.splice.expired.spec.js │ │ └── lru.splice.overwrite.spec.js │ ├── outputGenerator.js │ ├── response/ │ │ └── ModelResponseObserver.spec.js │ ├── set/ │ │ ├── edge-cases.spec.js │ │ ├── jsonGraphs/ │ │ │ ├── atom.spec.js │ │ │ ├── branch.spec.js │ │ │ ├── expired.spec.js │ │ │ ├── primitive.spec.js │ │ │ └── reference.spec.js │ │ ├── pathMaps/ │ │ │ ├── atom.spec.js │ │ │ ├── branch.spec.js │ │ │ ├── expired.spec.js │ │ │ └── primitive.spec.js │ │ ├── pathValues/ │ │ │ ├── atom.spec.js │ │ │ ├── branch.spec.js │ │ │ ├── expired.spec.js │ │ │ └── primitive.spec.js │ │ └── support/ │ │ ├── getModel.js │ │ ├── jsonGraph.js │ │ ├── jsonGraphEnvelope.js │ │ ├── partial-cache.js │ │ ├── pathMap.js │ │ ├── pathMapEnvelope.js │ │ ├── strip.js │ │ └── whole-cache.js │ ├── testRunner.js │ ├── toObs.js │ └── zipSpy.js └── webpack.config.js
SYMBOL INDEX (698 symbols across 77 files)
FILE: build/falcor-jsdoc-template/publish.js
function find (line 24) | function find(spec) {
function tutoriallink (line 28) | function tutoriallink(tutorial) {
function getAncestorLinks (line 32) | function getAncestorLinks(doclet) {
function hashToLink (line 36) | function hashToLink(doclet, hash) {
function needsSignature (line 45) | function needsSignature(doclet) {
function getSignatureAttributes (line 66) | function getSignatureAttributes(item) {
function updateItemName (line 83) | function updateItemName(item) {
function addParamAttributes (line 99) | function addParamAttributes(params) {
function buildItemTypeStrings (line 105) | function buildItemTypeStrings(item) {
function buildAttribsString (line 117) | function buildAttribsString(attribs) {
function addNonParamAttributes (line 127) | function addNonParamAttributes(items) {
function addSignatureParams (line 137) | function addSignatureParams(f) {
function addSignatureReturns (line 143) | function addSignatureReturns(f) {
function addSignatureTypes (line 175) | function addSignatureTypes(f) {
function addAttribs (line 182) | function addAttribs(f) {
function shortenPaths (line 189) | function shortenPaths(files, commonPrefix) {
function getPathFromDoclet (line 199) | function getPathFromDoclet(doclet) {
function generate (line 209) | function generate(title, docs, filename, resolveLinks) {
function generateSourceFiles (line 227) | function generateSourceFiles(sourceFiles, encoding) {
function attachModuleSymbols (line 260) | function attachModuleSymbols(doclets, modules) {
function buildMemberNav (line 290) | function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) {
function linktoTutorial (line 314) | function linktoTutorial(longName, name) {
function linktoExternal (line 318) | function linktoExternal(longName, name) {
function escapeDocId (line 323) | function escapeDocId(docId) {
function linkToWithTarget (line 332) | function linkToWithTarget(doc, linkText) {
function buildNav (line 353) | function buildNav(members) {
function generateTutorial (line 641) | function generateTutorial(title, tutorial, filename) {
function saveChildren (line 659) | function saveChildren(node) {
FILE: build/gulp-build.js
function buildDistBrowser (line 24) | function buildDistBrowser() {
function buildBrowser (line 33) | function buildBrowser() {
function buildDistAll (line 41) | function buildDistAll() {
function buildAll (line 50) | function buildAll() {
function build (line 58) | function build(options) {
FILE: build/gulp-clean.js
function cleanPerf (line 3) | function cleanPerf() {
function cleanDoc (line 7) | function cleanDoc() {
function cleanBin (line 11) | function cleanBin() {
function cleanDist (line 15) | function cleanDist() {
function cleanCoverage (line 19) | function cleanCoverage() {
FILE: build/gulp-perf.js
function buildDevice (line 8) | function buildDevice() {
function polyfillDevice (line 15) | function polyfillDevice() {
function buildBrowser (line 22) | function buildBrowser() {
function runBrowser (line 29) | function runBrowser() {
function runNode (line 33) | function runNode() {
FILE: dist/falcor.all.js
function r (line 16) | function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==...
function Model (line 124) | function Model(o) {
function ModelDataSourceAdapter (line 748) | function ModelDataSourceAdapter(model) {
function ModelRoot (line 772) | function ModelRoot(o) {
function BoundJSONGraphModelError (line 947) | function BoundJSONGraphModelError() {
function InvalidDerefInputError (line 978) | function InvalidDerefInputError() {
function InvalidModelError (line 1010) | function InvalidModelError(boundPath, shortedPath) {
function InvalidSourceError (line 1043) | function InvalidSourceError(error) {
function MaxRetryExceededError (line 1075) | function MaxRetryExceededError(missingOptimizedPaths) {
function NullInPathError (line 1110) | function NullInPathError(options) {
function applyErrorPrototype (line 1132) | function applyErrorPrototype(errorType) {
function followReference (line 1160) | function followReference(model, root, nodeArg, referenceContainerArg,
function mergeInto (line 1250) | function mergeInto(target, obj) {
function defaultEnvelope (line 1279) | function defaultEnvelope(isJSONG) {
function cloneBoxedValue (line 1410) | function cloneBoxedValue(boxedValue) {
function _copyCache (line 1429) | function _copyCache(node, out, fromKey) {
function concatAndInsertMissing (line 1751) | function concatAndInsertMissing(model, remainingPath, depth, requestedPath,
function isEmptyAtom (line 1762) | function isEmptyAtom(atom) {
function falcor (line 2200) | function falcor(opts) {
function invalidatePathMap (line 2298) | function invalidatePathMap(pathMap, root, parent, node, version, expired...
function invalidateReference (line 2322) | function invalidateReference(root, node, expired, lru) {
function invalidateNode (line 2365) | function invalidateNode(root, parent, node, key, branch, expired, lru) {
function invalidatePathSet (line 2458) | function invalidatePathSet(
function invalidateReference (line 2486) | function invalidateReference(root, node, expired, lru) {
function invalidateNode (line 2540) | function invalidateNode(root, parent, node, key, branch, expired, lru) {
function createDisposable (line 2966) | function createDisposable(request, batchIx) {
function flattenRequestedPaths (line 2993) | function flattenRequestedPaths(requested) {
function RequestQueueV2 (line 3020) | function RequestQueueV2(model, scheduler) {
function refCountCallback (line 3130) | function refCountCallback(err, data, hasInvalidatedResult) {
function findPartialIntersections (line 3245) | function findPartialIntersections(requestedPath, optimizedPath, requestT...
function recurse (line 3269) | function recurse(requestedPath, optimizedPath, currentTree, depth, rCurr...
function arrayConcatSlice (line 3360) | function arrayConcatSlice(a1, a2, start) {
function arrayConcatSlice2 (line 3374) | function arrayConcatSlice2(a1, a2, a3, start) {
function arrayConcatElement (line 3388) | function arrayConcatElement(a1, element) {
function CallResponse (line 3636) | function CallResponse(model, callPath, args, suffix, paths) {
function InvalidateResponse (line 3716) | function InvalidateResponse(model, args) {
function ModelResponse (line 3791) | function ModelResponse(subscribe) {
function ModelResponseObserver (line 3944) | function ModelResponseObserver(
function pluckPath (line 4517) | function pluckPath(pathValue) {
function pluckEnvelopePaths (line 4521) | function pluckEnvelopePaths(jsonGraphEnvelope) {
function getJSONGraph (line 4635) | function getJSONGraph(model, optimizedPaths) {
function subscribeToFollowupGet (line 4645) | function subscribeToFollowupGet(model, observer, requestedPaths, isJSONG...
function ImmediateScheduler (line 4668) | function ImmediateScheduler() {}
function TimeoutScheduler (line 4683) | function TimeoutScheduler(delay) {
function setJSONGraphPathSet (line 4788) | function setJSONGraphPathSet(
function setReference (line 4838) | function setReference(
function setNode (line 4895) | function setNode(
function setPathMap (line 5023) | function setPathMap(
function setReference (line 5077) | function setReference(
function setNode (line 5133) | function setNode(
function getKeys (line 5180) | function getKeys(pathMap) {
function setPathSet (line 5268) | function setPathSet(
function setReference (line 5315) | function setReference(
function setNode (line 5372) | function setNode(
function FromEsObserverAdapter (line 6357) | function FromEsObserverAdapter(esObserver) {
function ToEsSubscriptionAdapter (line 6383) | function ToEsSubscriptionAdapter(subscription) {
function toEsObservable (line 6392) | function toEsObservable(_self) {
function throwFirstError (line 6429) | function throwFirstError() {
function asap (line 6444) | function asap(task) {
function RawTask (line 6457) | function RawTask() {
function rawAsap (line 6500) | function rawAsap(task) {
function flush (line 6532) | function flush() {
function makeRequestCallFromMutationObserver (line 6626) | function makeRequestCallFromMutationObserver(callback) {
function makeRequestCallFromTimer (line 6677) | function makeRequestCallFromTimer(callback) {
function simpleExtend (line 6718) | function simpleExtend(obj, obj2) {
function XMLHttpSource (line 6726) | function XMLHttpSource(jsongUrl, config) {
function Observable (line 6894) | function Observable() {}
function request (line 6928) | function request(method, options, context) {
function _handleXhrError (line 7044) | function _handleXhrError(observer, textStatus, errorThrown) {
function onXhrLoad (line 7053) | function onXhrLoad(observer, xhr, e) {
function onXhrError (line 7103) | function onXhrError(observer, xhr, status, e) {
function sentinel (line 7112) | function sentinel(type, value, props) {
function toOutput (line 7732) | function toOutput(token, type, done) {
function getNext (line 7740) | function getNext(string, idx, ext) {
function followReference (line 7882) | function followReference(cacheRoot, ref, maxRefFollow) {
function maybeIntegerKey (line 8044) | function maybeIntegerKey(val) {
function isIntegerKey (line 8059) | function isIntegerKey(val) {
function initializeRange (line 8161) | function initializeRange(key, memo) {
function initializeNote (line 8173) | function initializeNote(key, note) {
function toJsonKey (line 8190) | function toJsonKey(obj) {
function replacer (line 8200) | function replacer(key, value) {
function maybeJsonKey (line 8212) | function maybeJsonKey(key) {
function isJsonKey (line 8228) | function isJsonKey(key) {
function optimizePathSet (line 8299) | function optimizePathSet(cache, cacheRoot, pathSet,
function getRangeOrKeySize (line 8371) | function getRangeOrKeySize(rangeOrKey) {
function getRangeSize (line 8389) | function getRangeSize(range) {
function getPathCount (line 8431) | function getPathCount(pathSet) {
function cloneArray (line 8539) | function cloneArray(arr, index) {
function isObject (line 8576) | function isObject(value) {
function collapsePathMap (line 8580) | function collapsePathMap(pathmap, depth, length) {
function collapsePathSetIndexes (line 8672) | function collapsePathSetIndexes(pathset) {
function collapseIndex (line 8695) | function collapseIndex(keyset) {
function sortListAscending (line 8735) | function sortListAscending(a, b) {
function getKeys (line 8740) | function getKeys(map, keys, sort) {
function getHashCode (line 8749) | function getHashCode(key) {
function __reducer (line 8773) | function __reducer(acc, path) {
function innerToTree (line 8778) | function innerToTree(seed, path, depth) {
function initializeRange (line 8985) | function initializeRange(key, memo) {
function initializeNote (line 8997) | function initializeNote(key, note) {
function optimizePathSet (line 9034) | function optimizePathSet(cache, cacheRoot, pathSet,
function isObject (line 9143) | function isObject(value) {
function collapsePathMap (line 9147) | function collapsePathMap(pathmap, depth, length) {
function collapsePathSetIndexes (line 9241) | function collapsePathSetIndexes(pathset) {
function collapseIndex (line 9264) | function collapseIndex(keyset) {
function sortListAscending (line 9304) | function sortListAscending(a, b) {
function getSortedKeys (line 9309) | function getSortedKeys(map, keys, sort) {
function getHashCode (line 9320) | function getHashCode(key) {
function isSafeNumber (line 9335) | function isSafeNumber(val) {
function innerToTree (line 9379) | function innerToTree(seed, path, depth) {
function __ (line 9414) | function __() { this.constructor = d; }
function InnerSubscriber (line 9425) | function InnerSubscriber(parent, outerValue, outerIndex) {
function Notification (line 9465) | function Notification(kind, value, error) {
function Observable (line 9594) | function Observable(subscribe) {
function __ (line 9728) | function __() { this.constructor = d; }
function OuterSubscriber (line 9739) | function OuterSubscriber() {
function Scheduler (line 9774) | function Scheduler(SchedulerAction, now) {
function __ (line 9809) | function __() { this.constructor = d; }
function Subscriber (line 9836) | function Subscriber(destinationOrNext, error, complete) {
function SafeSubscriber (line 9961) | function SafeSubscriber(_parentSubscriber, observerOrNext, error, comple...
function Subscription (line 10091) | function Subscription(unsubscribe) {
function flattenUnsubscriptionErrors (line 10256) | function flattenUnsubscriptionErrors(errors) {
function __ (line 10363) | function __() { this.constructor = d; }
function ArrayLikeObservable (line 10376) | function ArrayLikeObservable(arrayLike, scheduler) {
function __ (line 10434) | function __() { this.constructor = d; }
function ArrayObservable (line 10448) | function ArrayObservable(array, scheduler) {
function __ (line 10557) | function __() { this.constructor = d; }
function DeferObservable (line 10570) | function DeferObservable(observableFactory) {
function DeferSubscriber (line 10631) | function DeferSubscriber(destination, factory) {
function __ (line 10657) | function __() { this.constructor = d; }
function EmptyObservable (line 10668) | function EmptyObservable(scheduler) {
function __ (line 10739) | function __() { this.constructor = d; }
function ErrorObservable (line 10750) | function ErrorObservable(error, scheduler) {
function __ (line 10822) | function __() { this.constructor = d; }
function FromObservable (line 10843) | function FromObservable(ish, scheduler) {
function __ (line 10945) | function __() { this.constructor = d; }
function IteratorObservable (line 10958) | function IteratorObservable(iterator, scheduler) {
function StringIterator (line 11021) | function StringIterator(str, idx, len) {
function ArrayIterator (line 11041) | function ArrayIterator(arr, idx, len) {
function getIterator (line 11060) | function getIterator(obj) {
function toLength (line 11074) | function toLength(o) {
function numberIsFinite (line 11091) | function numberIsFinite(value) {
function sign (line 11094) | function sign(value) {
function __ (line 11109) | function __() { this.constructor = d; }
function PromiseObservable (line 11121) | function PromiseObservable(promise, scheduler) {
function dispatchNext (line 11213) | function dispatchNext(arg) {
function dispatchError (line 11220) | function dispatchError(arg) {
function __ (line 11231) | function __() { this.constructor = d; }
function ScalarObservable (line 11242) | function ScalarObservable(value, scheduler) {
function __ (line 11315) | function __() { this.constructor = d; }
function _catch (line 11379) | function _catch(selector) {
function CatchOperator (line 11386) | function CatchOperator(selector) {
function CatchSubscriber (line 11401) | function CatchSubscriber(destination, selector, caught) {
function concat (line 11483) | function concat() {
function concatStatic (line 11542) | function concatStatic() {
function __ (line 11563) | function __() { this.constructor = d; }
function defaultIfEmpty (line 11598) | function defaultIfEmpty(defaultValue) {
function DefaultIfEmptyOperator (line 11604) | function DefaultIfEmptyOperator(defaultValue) {
function DefaultIfEmptySubscriber (line 11619) | function DefaultIfEmptySubscriber(destination, defaultValue) {
function __ (line 11641) | function __() { this.constructor = d; }
function _do (line 11689) | function _do(nextOrObserver, error, complete) {
function DoOperator (line 11694) | function DoOperator(nextOrObserver, error, complete) {
function DoSubscriber (line 11711) | function DoSubscriber(destination, nextOrObserver, error, complete) {
function __ (line 11755) | function __() { this.constructor = d; }
function expand (line 11808) | function expand(project, concurrent, scheduler) {
function ExpandOperator (line 11816) | function ExpandOperator(project, concurrent, scheduler) {
function ExpandSubscriber (line 11834) | function ExpandSubscriber(destination, project, concurrent, scheduler) {
function __ (line 11907) | function __() { this.constructor = d; }
function filter (line 11951) | function filter(predicate, thisArg) {
function FilterOperator (line 11956) | function FilterOperator(predicate, thisArg) {
function FilterSubscriber (line 11972) | function FilterSubscriber(destination, predicate, thisArg) {
function __ (line 12001) | function __() { this.constructor = d; }
function map (line 12038) | function map(project, thisArg) {
function MapOperator (line 12046) | function MapOperator(project, thisArg) {
function MapSubscriber (line 12063) | function MapSubscriber(destination, project, thisArg) {
function __ (line 12089) | function __() { this.constructor = d; }
function materialize (line 12138) | function materialize() {
function MaterializeOperator (line 12143) | function MaterializeOperator() {
function MaterializeSubscriber (line 12157) | function MaterializeSubscriber(destination) {
function __ (line 12180) | function __() { this.constructor = d; }
function mergeAll (line 12229) | function mergeAll(concurrent) {
function MergeAllOperator (line 12235) | function MergeAllOperator(concurrent) {
function MergeAllSubscriber (line 12251) | function MergeAllSubscriber(destination, concurrent) {
function __ (line 12292) | function __() { this.constructor = d; }
function mergeMap (line 12356) | function mergeMap(project, resultSelector, concurrent) {
function MergeMapOperator (line 12366) | function MergeMapOperator(project, resultSelector, concurrent) {
function MergeMapSubscriber (line 12385) | function MergeMapSubscriber(destination, project, resultSelector, concur...
function __ (line 12464) | function __() { this.constructor = d; }
function observeOn (line 12478) | function observeOn(scheduler, delay) {
function ObserveOnOperator (line 12484) | function ObserveOnOperator(scheduler, delay) {
function ObserveOnSubscriber (line 12502) | function ObserveOnSubscriber(destination, scheduler, delay) {
function ObserveOnMessage (line 12529) | function ObserveOnMessage(notification, destination) {
function __ (line 12541) | function __() { this.constructor = d; }
function reduce (line 12591) | function reduce(accumulator, seed) {
function ReduceOperator (line 12605) | function ReduceOperator(accumulator, seed, hasSeed) {
function ReduceSubscriber (line 12624) | function ReduceSubscriber(destination, accumulator, seed, hasSeed) {
function __ (line 12669) | function __() { this.constructor = d; }
function toArray (line 12678) | function toArray() {
function ToArrayOperator (line 12683) | function ToArrayOperator() {
function ToArraySubscriber (line 12697) | function ToArraySubscriber(destination) {
function __ (line 12715) | function __() { this.constructor = d; }
function Action (line 12735) | function Action(scheduler, work) {
function __ (line 12760) | function __() { this.constructor = d; }
function AsyncAction (line 12772) | function AsyncAction(scheduler, work) {
function __ (line 12903) | function __() { this.constructor = d; }
function AsyncScheduler (line 12909) | function AsyncScheduler() {
function __ (line 12955) | function __() { this.constructor = d; }
function QueueAction (line 12966) | function QueueAction(scheduler, work) {
function __ (line 13005) | function __() { this.constructor = d; }
function QueueScheduler (line 13011) | function QueueScheduler() {
function symbolIteratorPonyfill (line 13027) | function symbolIteratorPonyfill(root) {
function getSymbolObservable (line 13062) | function getSymbolObservable(context) {
function __ (line 13093) | function __() { this.constructor = d; }
function UnsubscriptionError (line 13102) | function UnsubscriptionError(errors) {
function isFunction (line 13126) | function isFunction(x) {
function isObject (line 13133) | function isObject(x) {
function isPromise (line 13140) | function isPromise(value) {
function isScheduler (line 13147) | function isScheduler(value) {
function subscribeToResult (line 13178) | function subscribeToResult(outerSubscriber, result, outerValue, outerInd...
function toSubscriber (line 13252) | function toSubscriber(nextOrObserver, error, complete) {
function tryCatcher (line 13272) | function tryCatcher() {
function tryCatch (line 13281) | function tryCatch(fn) {
function C (line 13332) | function C(options) {
function merge (line 13543) | function merge(config, cache, message, depth, path, fromParent, fromKey) {
function optimizePathSet (line 13687) | function optimizePathSet(cache, cacheRoot, pathSet,
function innerPathValueMerge (line 13792) | function innerPathValueMerge(cache, pathValue) {
function onRange (line 13951) | function onRange(out, range) {
function onKey (line 13958) | function onKey(out, key) {
function onKey (line 13975) | function onKey(out, key) {
function onRange (line 13979) | function onRange(out, range) {
function match (line 14107) | function match(
function isNumber (line 14315) | function isNumber(x) {
function doubleEquals (line 14325) | function doubleEquals(a, b) {
function _hasIntersection (line 14359) | function _hasIntersection(path, node, depth) {
function onRange (line 14442) | function onRange(out, range) {
function keyReduce (line 14449) | function keyReduce(out, key, range) {
function createNamedVariables (line 14888) | function createNamedVariables(route, action) {
function buildParseTree (line 15047) | function buildParseTree(node, routeObject, depth) {
function setHashOrThrowError (line 15125) | function setHashOrThrowError(parseMap, routeObject) {
function decendTreeByRoutedToken (line 15157) | function decendTreeByRoutedToken(node, value, routeToken) {
function getHashesFromRoute (line 15184) | function getHashesFromRoute(route, depth, hashes, hash) {
function getPathsCount (line 15493) | function getPathsCount(pathSets) {
function outerRunCallAction (line 15721) | function outerRunCallAction(routerInstance, callPath, args,
function runCallAction (line 15729) | function runCallAction(matchAndPath, routerInstance, callPath, args,
function convertNoteToJsongOrPV (line 16017) | function convertNoteToJsongOrPV(pathOrPathSet,
function noop (line 16122) | function noop() {}
function toRxNewObserver (line 16124) | function toRxNewObserver(observer) {
function getAction (line 16200) | function getAction(routerInstance, matchAndPath, jsongCache, methodSumma...
function mergeCacheAndGatherRefsAndInvalidations (line 16288) | function mergeCacheAndGatherRefsAndInvalidations(
function _recurseMatchAndExecute (line 16494) | function _recurseMatchAndExecute(
function runSetAction (line 16648) | function runSetAction(routerInstance, jsongMessage, matchAndPath,
function cloneArray (line 16777) | function cloneArray(arr, index) {
function _spread (line 16910) | function _spread(pathSet, depth, out, currentPath) {
function noop (line 16960) | function noop() {}
function getThen (line 16981) | function getThen(obj) {
function tryCallOne (line 16990) | function tryCallOne(fn, a) {
function tryCallTwo (line 16998) | function tryCallTwo(fn, a, b) {
function Promise (line 17009) | function Promise(fn) {
function safeThen (line 17036) | function safeThen(self, onFulfilled, onRejected) {
function handle (line 17043) | function handle(self, deferred) {
function handleResolved (line 17067) | function handleResolved(self, deferred) {
function resolve (line 17086) | function resolve(self, newValue) {
function reject (line 17120) | function reject(self, newValue) {
function finale (line 17128) | function finale(self) {
function Handler (line 17141) | function Handler(onFulfilled, onRejected, promise){
function doResolve (line 17153) | function doResolve(fn, promise) {
function valuePromise (line 17204) | function valuePromise(value) {
function res (line 17253) | function res(i, val) {
function denodeifyWithCount (line 17363) | function denodeifyWithCount(fn, argumentCount) {
function denodeifyWithoutCount (line 17384) | function denodeifyWithoutCount(fn) {
function _interopRequireDefault (line 17543) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function symbolObservablePonyfill (line 17570) | function symbolObservablePonyfill(root) {
FILE: dist/falcor.browser.js
function r (line 16) | function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==...
function Model (line 116) | function Model(o) {
function ModelDataSourceAdapter (line 740) | function ModelDataSourceAdapter(model) {
function ModelRoot (line 764) | function ModelRoot(o) {
function BoundJSONGraphModelError (line 939) | function BoundJSONGraphModelError() {
function InvalidDerefInputError (line 970) | function InvalidDerefInputError() {
function InvalidModelError (line 1002) | function InvalidModelError(boundPath, shortedPath) {
function InvalidSourceError (line 1035) | function InvalidSourceError(error) {
function MaxRetryExceededError (line 1067) | function MaxRetryExceededError(missingOptimizedPaths) {
function NullInPathError (line 1102) | function NullInPathError(options) {
function applyErrorPrototype (line 1124) | function applyErrorPrototype(errorType) {
function followReference (line 1152) | function followReference(model, root, nodeArg, referenceContainerArg,
function mergeInto (line 1242) | function mergeInto(target, obj) {
function defaultEnvelope (line 1271) | function defaultEnvelope(isJSONG) {
function cloneBoxedValue (line 1402) | function cloneBoxedValue(boxedValue) {
function _copyCache (line 1421) | function _copyCache(node, out, fromKey) {
function concatAndInsertMissing (line 1743) | function concatAndInsertMissing(model, remainingPath, depth, requestedPath,
function isEmptyAtom (line 1754) | function isEmptyAtom(atom) {
function falcor (line 2192) | function falcor(opts) {
function invalidatePathMap (line 2290) | function invalidatePathMap(pathMap, root, parent, node, version, expired...
function invalidateReference (line 2314) | function invalidateReference(root, node, expired, lru) {
function invalidateNode (line 2357) | function invalidateNode(root, parent, node, key, branch, expired, lru) {
function invalidatePathSet (line 2450) | function invalidatePathSet(
function invalidateReference (line 2478) | function invalidateReference(root, node, expired, lru) {
function invalidateNode (line 2532) | function invalidateNode(root, parent, node, key, branch, expired, lru) {
function createDisposable (line 2958) | function createDisposable(request, batchIx) {
function flattenRequestedPaths (line 2985) | function flattenRequestedPaths(requested) {
function RequestQueueV2 (line 3012) | function RequestQueueV2(model, scheduler) {
function refCountCallback (line 3122) | function refCountCallback(err, data, hasInvalidatedResult) {
function findPartialIntersections (line 3237) | function findPartialIntersections(requestedPath, optimizedPath, requestT...
function recurse (line 3261) | function recurse(requestedPath, optimizedPath, currentTree, depth, rCurr...
function arrayConcatSlice (line 3352) | function arrayConcatSlice(a1, a2, start) {
function arrayConcatSlice2 (line 3366) | function arrayConcatSlice2(a1, a2, a3, start) {
function arrayConcatElement (line 3380) | function arrayConcatElement(a1, element) {
function CallResponse (line 3628) | function CallResponse(model, callPath, args, suffix, paths) {
function InvalidateResponse (line 3708) | function InvalidateResponse(model, args) {
function ModelResponse (line 3783) | function ModelResponse(subscribe) {
function ModelResponseObserver (line 3936) | function ModelResponseObserver(
function pluckPath (line 4509) | function pluckPath(pathValue) {
function pluckEnvelopePaths (line 4513) | function pluckEnvelopePaths(jsonGraphEnvelope) {
function getJSONGraph (line 4627) | function getJSONGraph(model, optimizedPaths) {
function subscribeToFollowupGet (line 4637) | function subscribeToFollowupGet(model, observer, requestedPaths, isJSONG...
function ImmediateScheduler (line 4660) | function ImmediateScheduler() {}
function TimeoutScheduler (line 4675) | function TimeoutScheduler(delay) {
function setJSONGraphPathSet (line 4780) | function setJSONGraphPathSet(
function setReference (line 4830) | function setReference(
function setNode (line 4887) | function setNode(
function setPathMap (line 5015) | function setPathMap(
function setReference (line 5069) | function setReference(
function setNode (line 5125) | function setNode(
function getKeys (line 5172) | function getKeys(pathMap) {
function setPathSet (line 5260) | function setPathSet(
function setReference (line 5307) | function setReference(
function setNode (line 5364) | function setNode(
function FromEsObserverAdapter (line 6349) | function FromEsObserverAdapter(esObserver) {
function ToEsSubscriptionAdapter (line 6375) | function ToEsSubscriptionAdapter(subscription) {
function toEsObservable (line 6384) | function toEsObservable(_self) {
function throwFirstError (line 6421) | function throwFirstError() {
function asap (line 6436) | function asap(task) {
function RawTask (line 6449) | function RawTask() {
function rawAsap (line 6492) | function rawAsap(task) {
function flush (line 6524) | function flush() {
function makeRequestCallFromMutationObserver (line 6618) | function makeRequestCallFromMutationObserver(callback) {
function makeRequestCallFromTimer (line 6669) | function makeRequestCallFromTimer(callback) {
function simpleExtend (line 6710) | function simpleExtend(obj, obj2) {
function XMLHttpSource (line 6718) | function XMLHttpSource(jsongUrl, config) {
function Observable (line 6886) | function Observable() {}
function request (line 6920) | function request(method, options, context) {
function _handleXhrError (line 7036) | function _handleXhrError(observer, textStatus, errorThrown) {
function onXhrLoad (line 7045) | function onXhrLoad(observer, xhr, e) {
function onXhrError (line 7095) | function onXhrError(observer, xhr, status, e) {
function sentinel (line 7104) | function sentinel(type, value, props) {
function toOutput (line 7724) | function toOutput(token, type, done) {
function getNext (line 7732) | function getNext(string, idx, ext) {
function followReference (line 7874) | function followReference(cacheRoot, ref, maxRefFollow) {
function maybeIntegerKey (line 8036) | function maybeIntegerKey(val) {
function isIntegerKey (line 8051) | function isIntegerKey(val) {
function initializeRange (line 8153) | function initializeRange(key, memo) {
function initializeNote (line 8165) | function initializeNote(key, note) {
function toJsonKey (line 8182) | function toJsonKey(obj) {
function replacer (line 8192) | function replacer(key, value) {
function maybeJsonKey (line 8204) | function maybeJsonKey(key) {
function isJsonKey (line 8220) | function isJsonKey(key) {
function optimizePathSet (line 8291) | function optimizePathSet(cache, cacheRoot, pathSet,
function getRangeOrKeySize (line 8363) | function getRangeOrKeySize(rangeOrKey) {
function getRangeSize (line 8381) | function getRangeSize(range) {
function getPathCount (line 8423) | function getPathCount(pathSet) {
function cloneArray (line 8531) | function cloneArray(arr, index) {
function isObject (line 8568) | function isObject(value) {
function collapsePathMap (line 8572) | function collapsePathMap(pathmap, depth, length) {
function collapsePathSetIndexes (line 8664) | function collapsePathSetIndexes(pathset) {
function collapseIndex (line 8687) | function collapseIndex(keyset) {
function sortListAscending (line 8727) | function sortListAscending(a, b) {
function getKeys (line 8732) | function getKeys(map, keys, sort) {
function getHashCode (line 8741) | function getHashCode(key) {
function __reducer (line 8765) | function __reducer(acc, path) {
function innerToTree (line 8770) | function innerToTree(seed, path, depth) {
function noop (line 8822) | function noop() {}
function getThen (line 8843) | function getThen(obj) {
function tryCallOne (line 8852) | function tryCallOne(fn, a) {
function tryCallTwo (line 8860) | function tryCallTwo(fn, a, b) {
function Promise (line 8871) | function Promise(fn) {
function safeThen (line 8898) | function safeThen(self, onFulfilled, onRejected) {
function handle (line 8905) | function handle(self, deferred) {
function handleResolved (line 8929) | function handleResolved(self, deferred) {
function resolve (line 8948) | function resolve(self, newValue) {
function reject (line 8982) | function reject(self, newValue) {
function finale (line 8990) | function finale(self) {
function Handler (line 9003) | function Handler(onFulfilled, onRejected, promise){
function doResolve (line 9015) | function doResolve(fn, promise) {
function valuePromise (line 9066) | function valuePromise(value) {
function res (line 9115) | function res(i, val) {
function denodeifyWithCount (line 9225) | function denodeifyWithCount(fn, argumentCount) {
function denodeifyWithoutCount (line 9246) | function denodeifyWithoutCount(fn) {
function _interopRequireDefault (line 9405) | function _interopRequireDefault(obj) { return obj && obj.__esModule ? ob...
function symbolObservablePonyfill (line 9432) | function symbolObservablePonyfill(root) {
FILE: examples/datasource/webWorkerSource.js
function WorkerServer (line 12) | function WorkerServer(dataSource) {
function WebWorkerSource (line 86) | function WebWorkerSource(worker) {
FILE: gulpfile.js
function lint (line 9) | function lint() {
function generateDocs (line 16) | function generateDocs() {
FILE: lib/Model.js
function Model (line 87) | function Model(o) {
FILE: lib/ModelDataSourceAdapter.js
function ModelDataSourceAdapter (line 1) | function ModelDataSourceAdapter(model) {
FILE: lib/ModelRoot.js
function ModelRoot (line 4) | function ModelRoot(o) {
FILE: lib/errors/BoundJSONGraphModelError.js
function BoundJSONGraphModelError (line 9) | function BoundJSONGraphModelError() {
FILE: lib/errors/InvalidDerefInputError.js
function InvalidDerefInputError (line 9) | function InvalidDerefInputError() {
FILE: lib/errors/InvalidModelError.js
function InvalidModelError (line 12) | function InvalidModelError(boundPath, shortedPath) {
FILE: lib/errors/InvalidSourceError.js
function InvalidSourceError (line 11) | function InvalidSourceError(error) {
FILE: lib/errors/MaxRetryExceededError.js
function MaxRetryExceededError (line 11) | function MaxRetryExceededError(missingOptimizedPaths) {
FILE: lib/errors/NullInPathError.js
function NullInPathError (line 10) | function NullInPathError(options) {
FILE: lib/errors/applyErrorPrototype.js
function applyErrorPrototype (line 1) | function applyErrorPrototype(errorType) {
FILE: lib/get/followReference.js
function followReference (line 8) | function followReference(model, root, nodeArg, referenceContainerArg,
FILE: lib/get/get.js
function mergeInto (line 5) | function mergeInto(target, obj) {
function defaultEnvelope (line 34) | function defaultEnvelope(isJSONG) {
FILE: lib/get/getCache.js
function cloneBoxedValue (line 13) | function cloneBoxedValue(boxedValue) {
function _copyCache (line 32) | function _copyCache(node, out, fromKey) {
FILE: lib/get/onMissing.js
function concatAndInsertMissing (line 29) | function concatAndInsertMissing(model, remainingPath, depth, requestedPath,
function isEmptyAtom (line 40) | function isEmptyAtom(atom) {
FILE: lib/index.js
function falcor (line 3) | function falcor(opts) {
FILE: lib/invalidate/invalidatePathMaps.js
function invalidatePathMap (line 57) | function invalidatePathMap(pathMap, root, parent, node, version, expired...
function invalidateReference (line 81) | function invalidateReference(root, node, expired, lru) {
function invalidateNode (line 124) | function invalidateNode(root, parent, node, key, branch, expired, lru) {
FILE: lib/invalidate/invalidatePathSets.js
function invalidatePathSet (line 58) | function invalidatePathSet(
function invalidateReference (line 86) | function invalidateReference(root, node, expired, lru) {
function invalidateNode (line 140) | function invalidateNode(root, parent, node, key, branch, expired, lru) {
FILE: lib/request/GetRequestV2.js
function createDisposable (line 243) | function createDisposable(request, batchIx) {
function flattenRequestedPaths (line 270) | function flattenRequestedPaths(requested) {
FILE: lib/request/RequestQueueV2.js
function RequestQueueV2 (line 13) | function RequestQueueV2(model, scheduler) {
function refCountCallback (line 123) | function refCountCallback(err, data, hasInvalidatedResult) {
FILE: lib/request/complement.js
function findPartialIntersections (line 64) | function findPartialIntersections(requestedPath, optimizedPath, requestT...
function recurse (line 88) | function recurse(requestedPath, optimizedPath, currentTree, depth, rCurr...
function arrayConcatSlice (line 179) | function arrayConcatSlice(a1, a2, start) {
function arrayConcatSlice2 (line 193) | function arrayConcatSlice2(a1, a2, a3, start) {
function arrayConcatElement (line 207) | function arrayConcatElement(a1, element) {
FILE: lib/response/CallResponse.js
function CallResponse (line 10) | function CallResponse(model, callPath, args, suffix, paths) {
FILE: lib/response/InvalidateResponse.js
function InvalidateResponse (line 7) | function InvalidateResponse(model, args) {
FILE: lib/response/ModelResponse.js
function ModelResponse (line 10) | function ModelResponse(subscribe) {
FILE: lib/response/ModelResponseObserver.js
function ModelResponseObserver (line 10) | function ModelResponseObserver(
FILE: lib/response/set/setGroupsIntoCache.js
function pluckPath (line 47) | function pluckPath(pathValue) {
function pluckEnvelopePaths (line 51) | function pluckEnvelopePaths(jsonGraphEnvelope) {
FILE: lib/response/set/setRequestCycle.js
function getJSONGraph (line 110) | function getJSONGraph(model, optimizedPaths) {
function subscribeToFollowupGet (line 120) | function subscribeToFollowupGet(model, observer, requestedPaths, isJSONG...
FILE: lib/schedulers/ASAPScheduler.js
function ASAPScheduler (line 4) | function ASAPScheduler() {
FILE: lib/schedulers/ImmediateScheduler.js
function ImmediateScheduler (line 3) | function ImmediateScheduler() {}
FILE: lib/schedulers/TimeoutScheduler.js
function TimeoutScheduler (line 1) | function TimeoutScheduler(delay) {
FILE: lib/set/setJSONGraphs.js
function setJSONGraphPathSet (line 72) | function setJSONGraphPathSet(
function setReference (line 122) | function setReference(
function setNode (line 179) | function setNode(
FILE: lib/set/setPathMaps.js
function setPathMap (line 69) | function setPathMap(
function setReference (line 123) | function setReference(
function setNode (line 179) | function setNode(
function getKeys (line 226) | function getKeys(pathMap) {
FILE: lib/set/setPathValues.js
function setPathSet (line 68) | function setPathSet(
function setReference (line 115) | function setReference(
function setNode (line 172) | function setNode(
FILE: lib/toEsObservable.js
function FromEsObserverAdapter (line 5) | function FromEsObserverAdapter(esObserver) {
function ToEsSubscriptionAdapter (line 31) | function ToEsSubscriptionAdapter(subscription) {
function toEsObservable (line 40) | function toEsObservable(_self) {
FILE: performance/models/legacy/_.js
function PathEvaluator (line 13) | function PathEvaluator(maxSize, collectRatio, loader, cache, path, now, ...
function noop (line 109) | function noop() {
function defaultNow (line 112) | function defaultNow() {
function identity (line 116) | function identity(x) {
function get (line 120) | function get() {
function set (line 141) | function set() {
function invalidate (line 171) | function invalidate() {
function call (line 192) | function call() {
function bind (line 213) | function bind(path) {
function hardBind (line 223) | function hardBind(path) {
function deferBind (line 245) | function deferBind(path) {
function getContext (line 257) | function getContext() {
function getPath (line 283) | function getPath(path_, cache, parent, bound) {
function getPaths (line 630) | function getPaths(model, paths_, onNext, onError, onCompleted, cache, pa...
function setPath (line 1235) | function setPath(pathOrPBV, valueOrCache, cache, parent, bound) {
function setPaths (line 1980) | function setPaths(pbvs, onNext, onError, onCompleted, cache, parent, bou...
function setPBF (line 2830) | function setPBF(pbf, onNext, onError, onCompleted, cache, parent, bound) {
function invalidatePath (line 4705) | function invalidatePath(path_, cache, parent, bound) {
function invalidatePaths (line 5021) | function invalidatePaths(paths_, onNext, onError, onCompleted, cache, pa...
function pathMapWithObserver (line 5403) | function pathMapWithObserver(paths_, observer_, parent) {
function pathMapWithoutObserver (line 5501) | function pathMapWithoutObserver(paths_, observer_, pathMap) {
function callPath (line 5605) | function callPath(path, onNext, onError, onCompleted, callArgs, suffixes...
function getPathsAsObservable (line 5657) | function getPathsAsObservable() {
function setPathsAsObservable (line 5692) | function setPathsAsObservable() {
function setPBFAsObservable (line 5727) | function setPBFAsObservable() {
function invalidatePathsAsObservable (line 5762) | function invalidatePathsAsObservable() {
function callPathAsObservable (line 5797) | function callPathAsObservable() {
function getPathsAsPromises (line 5832) | function getPathsAsPromises() {
function setPathsAsPromises (line 5837) | function setPathsAsPromises() {
function setPBFAsPromises (line 5842) | function setPBFAsPromises() {
function invalidatePathsAsPromise (line 5847) | function invalidatePathsAsPromise() {
function callPathAsPromise (line 5852) | function callPathAsPromise() {
function toBatched (line 5857) | function toBatched() {
function toIndependent (line 5866) | function toIndependent() {
function toLazy (line 5875) | function toLazy() {
function toEager (line 5884) | function toEager() {
function toProgressive (line 5893) | function toProgressive() {
function toAggregate (line 5902) | function toAggregate() {
function toRemote (line 5911) | function toRemote() {
function toLocal (line 5920) | function toLocal() {
function toRefreshed (line 5929) | function toRefreshed() {
function toCached (line 5938) | function toCached() {
function toMaterialized (line 5947) | function toMaterialized() {
function toDematerialized (line 5956) | function toDematerialized() {
function toRoot (line 5965) | function toRoot() {
function serialize (line 5969) | function serialize(cache) {
function deserialize (line 6009) | function deserialize(cache) {
function stringify (line 6047) | function stringify(obj, replacer, space) {
function flatten (line 6051) | function flatten(obj) {
function collapse (line 6078) | function collapse(pathMap) {
function rangeCollapse (line 6082) | function rangeCollapse(paths) {
function isNumber (line 6103) | function isNumber(val) {
function allUnique (line 6107) | function allUnique(arr) {
function sortLol (line 6119) | function sortLol(lol) {
function createKey (line 6129) | function createKey(list) {
function notPathMapInternalKeys (line 6133) | function notPathMapInternalKeys(key) {
function buildQueries (line 6143) | function buildQueries(root) {
function BatchRequestQueue (line 6192) | function BatchRequestQueue(rootPE) {
function BatchRequest (line 6222) | function BatchRequest(rootPE, queue) {
FILE: performance/models/legacy/macro/_Falcor.js
function now (line 43) | function now() {
function NOOP (line 47) | function NOOP() {}
function ModelResponse (line 60) | function ModelResponse(forEach) {
function noop (line 68) | function noop() {}
function mixin (line 69) | function mixin(self) {
function ImmediateScheduler (line 93) | function ImmediateScheduler() {
function TimeoutScheduler (line 104) | function TimeoutScheduler(delay) {
function pathsToMapWithObservers (line 364) | function pathsToMapWithObservers(path, idx, branch, observer) {
function readyNode (line 401) | function readyNode(branch, key, observer) {
function containsObserver (line 416) | function containsObserver(observers, observer) {
function collapse (line 425) | function collapse(pathMap) {
function rangeCollapse (line 436) | function rangeCollapse(paths) {
function buildQueries (line 458) | function buildQueries(root) {
function notPathMapInternalKeys (line 516) | function notPathMapInternalKeys(key) {
function isNumber (line 527) | function isNumber(val) {
function allUnique (line 535) | function allUnique(arr) {
function sortLol (line 555) | function sortLol(lol) {
function createKey (line 569) | function createKey(list) {
function modelOperation (line 575) | function modelOperation(name) {
function fastCollapse (line 891) | function fastCollapse(paths) {
function convertArgumentsToFromJSONG (line 914) | function convertArgumentsToFromJSONG(args, remoteMessage, boundPath) {
function getOperationsPartitionedByPathIndex (line 937) | function getOperationsPartitionedByPathIndex(requestedPaths, incomingVal...
function getOperationArgGroups (line 989) | function getOperationArgGroups(ops, name, format, values, hasSelector, o...
function appendBoundPathToArgument (line 1046) | function appendBoundPathToArgument(boundPath, argument, type) {
function processOperations (line 1075) | function processOperations(model, operations) {
function not (line 1111) | function not() {
function isPathOrPathValue (line 1121) | function isPathOrPathValue(x) {
function isJSONG (line 1126) | function isJSONG(x) {
function isSeedRequired (line 1130) | function isSeedRequired(format) {
function cloneIfPathOrPathValue (line 1134) | function cloneIfPathOrPathValue(x) {
function Model (line 1147) | function Model(options) {
function simplePathToMap (line 1388) | function simplePathToMap(path, seed) {
function intersect (line 1402) | function intersect(map, pathSet) {
function pathToMap (line 1406) | function pathToMap(path, seed, depth) {
function simplePathInMap (line 1443) | function simplePathInMap(path, map) {
function call (line 1455) | function call(path, args, suffixes, paths, selector) {
function getBoundPath (line 1517) | function getBoundPath(model, path, value, boxed) {
function getPath (line 1532) | function getPath(model, path) {
function getPathMap (line 1644) | function getPathMap(model, map, errorSelector, boundPath) {
function getPathMapsAsJSON (line 2067) | function getPathMapsAsJSON(model, pathMaps, values, errorSelector, bound...
function getPathMapsAsJSONG (line 2498) | function getPathMapsAsJSONG(model, pathMaps, values, errorSelector, boun...
function getPathMapsAsPathMap (line 3059) | function getPathMapsAsPathMap(model, pathMaps, values, errorSelector, bo...
function getPathMapsAsValues (line 3492) | function getPathMapsAsValues(model, pathMaps, values, errorSelector, bou...
function getPathSet (line 3879) | function getPathSet(model, path, boundPath) {
function getPathSetsAsJSON (line 4190) | function getPathSetsAsJSON(model, pathSets, values, errorSelector, bound...
function getPathSetsAsJSONG (line 4625) | function getPathSetsAsJSONG(model, pathSets, values, errorSelector, boun...
function getPathSetsAsPathMap (line 5189) | function getPathSetsAsPathMap(model, pathSets, values, errorSelector, bo...
function getPathSetsAsValues (line 5626) | function getPathSetsAsValues(model, pathSets, values, errorSelector, bou...
function invalidatePathMaps (line 6017) | function invalidatePathMaps(model, pathMaps, values, errorSelector, boun...
function invalidatePathSets (line 6296) | function invalidatePathSets(model, pathSets, values, errorSelector, boun...
function setCache (line 6604) | function setCache(model, map) {
function setJSONG (line 6991) | function setJSONG(model, envelope, errorSelector, boundPath) {
function setJSONGsAsJSON (line 8184) | function setJSONGsAsJSON(model, envelopes, values, errorSelector, boundP...
function setJSONGsAsJSONG (line 9381) | function setJSONGsAsJSONG(model, envelopes, values, errorSelector, bound...
function setJSONGsAsPathMap (line 10720) | function setJSONGsAsPathMap(model, envelopes, values, errorSelector, bou...
function setJSONGsAsValues (line 11921) | function setJSONGsAsValues(model, envelopes, values, errorSelector, boun...
function setPath (line 13076) | function setPath(model, path, value, errorSelector) {
function setPathMap (line 13638) | function setPathMap(model, map, errorSelector, boundPath) {
function setPathMapsAsJSON (line 14522) | function setPathMapsAsJSON(model, pathMaps, values, errorSelector, bound...
function setPathMapsAsJSONG (line 15414) | function setPathMapsAsJSONG(model, pathMaps, values, errorSelector, boun...
function setPathMapsAsPathMap (line 16420) | function setPathMapsAsPathMap(model, pathMaps, values, errorSelector, bo...
function setPathMapsAsValues (line 17314) | function setPathMapsAsValues(model, pathMaps, values, errorSelector, bou...
function setPathSet (line 18163) | function setPathSet(model, path, value, errorSelector, boundPath) {
function setPathSetsAsJSON (line 19041) | function setPathSetsAsJSON(model, pathValues, values, errorSelector, bou...
function setPathSetsAsJSONG (line 19923) | function setPathSetsAsJSONG(model, pathValues, values, errorSelector, bo...
function setPathSetsAsPathMap (line 20934) | function setPathSetsAsPathMap(model, pathValues, values, errorSelector, ...
function setPathSetsAsValues (line 21819) | function setPathSetsAsValues(model, pathValues, values, errorSelector, b...
FILE: performance/reporters/nodeTestReporter.js
function getFileName (line 28) | function getFileName() {
FILE: performance/scripts/transformCSV.js
function isNumber (line 14) | function isNumber(n) {
FILE: performance/testRunner.js
function createSuite (line 5) | function createSuite(testCfg, log, gc) {
function runner (line 36) | function runner(testCfg, env, onBenchmarkComplete, onComplete, log, gc) {
function run (line 47) | function run(suites, env, onBenchmarkComplete, onComplete, log) {
FILE: performance/tests/clone/clone.perf.js
function clone (line 17) | function clone() {
FILE: performance/tests/deref/index.js
function rowTest (line 28) | function rowTest() {
FILE: performance/tests/get/get.core.perf.js
function rowTest (line 28) | function rowTest() {
FILE: performance/tests/get/get.perf.js
function primedCache (line 27) | function primedCache() {
function primedCacheWithPaths (line 33) | function primedCacheWithPaths() {
function toDataSource (line 39) | function toDataSource() {
function batchingRequests (line 53) | function batchingRequests() {
FILE: performance/tests/lru/index.js
function p (line 11) | function p() {
FILE: performance/tests/set/set.json-graph.perf.js
function insertJSONGraphRow (line 25) | function insertJSONGraphRow() {
function getJSONGraphRow (line 36) | function getJSONGraphRow() {
FILE: server.js
function listen (line 9) | function listen(serverPort, launchWindow, cb) {
function coverage (line 20) | function coverage(serverPort, launchWindow) {
FILE: test/CacheGenerator.js
function makeLolomos (line 26) | function makeLolomos(startIdx, count, setModelCreated) {
function makeVideos (line 36) | function makeVideos(startIdx, count, fields, setModelCreated) {
function makeLists (line 54) | function makeLists(listStartIdx, videoStartIdx, count, setModelCreated) {
function makeItem (line 82) | function makeItem(idx, setModelCreated) {
FILE: test/Model.spec.js
function ResponseObservable (line 11) | function ResponseObservable(response) {
method get (line 102) | get() {
method get (line 179) | get() {
method get (line 265) | get() {
method get (line 350) | get() {
function MyModel (line 439) | function MyModel() {
FILE: test/cleanData.js
function convertModelCreatedAtoms (line 22) | function convertModelCreatedAtoms(cache) {
function clean (line 33) | function clean(item, options) {
function convertNodes (line 44) | function convertNodes(parent, fromKey, obj, transform) {
function convert (line 59) | function convert(obj, config) {
function traverseAndConvert (line 77) | function traverseAndConvert(obj) {
function strip (line 102) | function strip(obj, key) {
FILE: test/data/LocalDataSource.js
method setModel (line 24) | setModel(modelOrCache) {
method get (line 31) | get(paths, dsRequestOpts) {
method set (line 69) | set(jsongEnv, dsRequestOpts) {
method call (line 103) | call(path, args, suffixes, paths) {
FILE: test/falcor/call/call.spec.js
function getModel (line 14) | function getModel(newModel, cache) {
FILE: test/falcor/deref/deref.hasValidParentReference.spec.js
function log (line 186) | function log(model) {
FILE: test/falcor/error/error.spec.js
function errorOnCompleted (line 11) | function errorOnCompleted(done) {
function doneOnError (line 17) | function doneOnError(done) {
FILE: test/falcor/get/get.dataSource-and-bind.spec.js
function Cache (line 9) | function Cache() {
function M (line 12) | function M() {
FILE: test/falcor/get/get.dataSource-and-cache.spec.js
function generateErrorSelectorSpy (line 509) | function generateErrorSelectorSpy(expectedPath) {
function assertExpectedErrorPayload (line 523) | function assertExpectedErrorPayload(e, expectedPath) {
function remoteData (line 791) | function remoteData() {
FILE: test/falcor/get/get.dataSource-only.spec.js
method get (line 227) | get(paths) {
method onResults (line 316) | onResults(data) {
FILE: test/falcor/set/set.cache-only.spec.js
function generateErrorSelectorSpy (line 111) | function generateErrorSelectorSpy(expectedPath) {
function assertExpectedErrorPayload (line 129) | function assertExpectedErrorPayload(e, expectedPath) {
FILE: test/falcor/set/set.dataSource-and-bind.spec.js
function Cache (line 11) | function Cache() { return cacheGenerator(0, 2); }
function M (line 12) | function M() { return cacheGenerator(0, 1); }
FILE: test/get-core/get.cache.spec.js
function deepExpectations (line 8) | function deepExpectations(o, expectExpression) {
FILE: test/get-core/values.spec.js
function intersectingTest (line 156) | function intersectingTest(paths) {
FILE: test/getTestRunner.js
function getTestRunner (line 8) | function getTestRunner(data, options) {
function toString (line 122) | function toString(x) {
FILE: test/hardlink/hardlink.add.spec.js
function getTest (line 66) | function getTest(query, output) {
function setTest (line 84) | function setTest(query, output) {
FILE: test/hardlink/hardlink.remove.spec.js
function getTest (line 60) | function getTest(query, output) {
function setTest (line 78) | function setTest(query, output) {
FILE: test/integration/get.spec.js
function setRoutes (line 227) | function setRoutes(routes) {
FILE: test/internal/request/GetRequest.batch.spec.js
method removeRequest (line 29) | removeRequest() {}
method removeRequest (line 69) | removeRequest() {}
method removeRequest (line 109) | removeRequest() {}
method removeRequest (line 146) | removeRequest() {}
method removeRequest (line 185) | removeRequest() {}
FILE: test/internal/request/GetRequest.spec.js
method get (line 46) | get() {
method dispose (line 92) | dispose() {}
method get (line 104) | get() {
method get (line 164) | get() {
function waitOrExpect (line 178) | function waitOrExpect() {
FILE: test/lru/lru.promote.set.spec.js
function getModel (line 231) | function getModel() {
function singleItem (line 237) | function singleItem(model) {
function doubleItem (line 243) | function doubleItem(model) {
function tripleItem (line 252) | function tripleItem(model) {
FILE: test/lru/lru.splice.overwrite.spec.js
function getModel (line 33) | function getModel() {
function testLRU (line 40) | function testLRU(model) {
FILE: test/outputGenerator.js
function getListRef (line 67) | function getListRef(listIndex) {
function getItemObject (line 71) | function getItemObject(listIndex, itemIndex, fields) {
FILE: test/testRunner.js
function validateData (line 86) | function validateData(expected, actual) {
function validateOperation (line 99) | function validateOperation(name, expected, actual, messageSuffix) {
Condensed preview — 367 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,933K chars).
[
{
"path": ".bithoundrc",
"chars": 187,
"preview": "{\n \"ignore\": [\n \"**/node_modules/**\",\n \"build/**\",\n \"coverage/**\",\n \"dist/**\",\n \"macros/**\",\n \"perfor"
},
{
"path": ".editorconfig",
"chars": 244,
"preview": "# http://editorconfig.org\n\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\nend_of_line = lf\ninsert"
},
{
"path": ".eslintrc",
"chars": 4633,
"preview": "{\n \"env\": {\n \"browser\": false,\n \"node\": true,\n \"es6\": false\n },\n \"rules\": {\n // pos"
},
{
"path": ".github/workflows/ci.yml",
"chars": 552,
"preview": "name: CI\n\non:\n push:\n branches: [ master ]\n pull_request:\n branches: [ master ]\n\njobs:\n build:\n runs-on: ubu"
},
{
"path": ".github/workflows/docs.yml",
"chars": 565,
"preview": "name: Docs\n\non:\n push:\n branches: [ master ]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: act"
},
{
"path": ".gitignore",
"chars": 157,
"preview": "node_modules\n.DS_Store\nbin/\nbin2\nout/\ntmp/\nperformance/bin/\nperformance/device/\n!tasks/bin\ncoverage\n.idea\n*.iml\n*.tar.gz"
},
{
"path": ".npmignore",
"chars": 151,
"preview": "test/\n\n.DS_Store\nbin/\nbin2\nout/\ntmp/\nperformance/bin/\nperformance/device/\n!tasks/bin\ncoverage\n.idea\n*.iml\n*.tar.gz\ncTest"
},
{
"path": ".npmrc",
"chars": 36,
"preview": "registry=https://registry.npmjs.com\n"
},
{
"path": ".travis.yml",
"chars": 678,
"preview": "language: node_js\n\nnode_js:\n - \"10\"\n\nbranches:\n only:\n - master\n - 0.x\n - 1.0.0\n\n# Set up key"
},
{
"path": "CHANGELOG.md",
"chars": 6201,
"preview": "# 2.4.1\n## Bugfix\n- Republished to remove an issue with a hash generation of 2.4.0\n\n# 2.4.0\n## Changes\n- [Handling fromP"
},
{
"path": "LICENSE.txt",
"chars": 11344,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "MIGRATIONS.md",
"chars": 8335,
"preview": "# 1.x to 2.x\n\nModels always (usually) onNext\n-------\nWhen starting with the following json graph\n```javascript\n{\n lis"
},
{
"path": "OSSMETADATA",
"chars": 20,
"preview": "osslifecycle=active\n"
},
{
"path": "README.md",
"chars": 6661,
"preview": "<p align=\"center\">\n <img src=\"https://cloud.githubusercontent.com/assets/1016365/8711049/66438ebc-2b03-11e5-8a8a-75934f"
},
{
"path": "all.js",
"chars": 128,
"preview": "var falcor = require(\"./browser.js\");\nvar Router = require(\"falcor-router\");\n\nfalcor.Router = Router;\n\nmodule.exports = "
},
{
"path": "authors.txt",
"chars": 106,
"preview": "Jafar Husain <jhusain@gmail.com>\nPaul Taylor <ptaylor@netflix.com>\nMichael Paulson <mpaulson@netflix.com>\n"
},
{
"path": "bower.json",
"chars": 423,
"preview": "\n{\n \"name\": \"falcor\",\n \"main\": \"./dist/falcor.browser.js\",\n \"ignore\": [\n \"build\", \n \"examples\", \n \"lib\", \n "
},
{
"path": "browser.js",
"chars": 274,
"preview": "var falcor = require(\"./lib\");\nvar jsong = require(\"falcor-json-graph\");\n\nfalcor.atom = jsong.atom;\nfalcor.ref = jsong.r"
},
{
"path": "build/deploy-ghpages.sh",
"chars": 1858,
"preview": "#!/bin/bash\n\nif [ \"$TRAVIS_PULL_REQUEST\" == \"false\" ]; then\n echo -e \"Building and committing dist and docs...\\n\"\n\n TE"
},
{
"path": "build/falcor-jsdoc-template/README.md",
"chars": 1065,
"preview": "### Falcor Website JSDoc Theme\n\nBased on the default JSDoc 3 template, with a completely rewritten nav and a number of o"
},
{
"path": "build/falcor-jsdoc-template/publish.js",
"chars": 21967,
"preview": "/*global env: true */\n'use strict';\n\nvar doop = require('jsdoc/util/doop');\nvar fs = require('jsdoc/fs');\nvar helper = r"
},
{
"path": "build/falcor-jsdoc-template/tmpl/augments.tmpl",
"chars": 229,
"preview": "<?js\n var data = obj;\n var self = this;\n?>\n\n<?js if (data.augments && data.augments.length) { ?>\n <ul><?js data"
},
{
"path": "build/falcor-jsdoc-template/tmpl/container.tmpl",
"chars": 6694,
"preview": "---\nlayout: api-page\ntitle: \"<?js= title ?>\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n <?js\n var self = "
},
{
"path": "build/falcor-jsdoc-template/tmpl/details.tmpl",
"chars": 5437,
"preview": "<?js\nvar data = obj;\nvar self = this;\nvar defaultObjectClass = '';\n\n// Check if the default value is an object or array;"
},
{
"path": "build/falcor-jsdoc-template/tmpl/example.tmpl",
"chars": 62,
"preview": "<?js var data = obj; ?>\n<pre><code><?js= data ?></code></pre>\n"
},
{
"path": "build/falcor-jsdoc-template/tmpl/examples.tmpl",
"chars": 297,
"preview": "<?js\n var data = obj;\n var self = this;\n\n data.forEach(function(example) {\n if (example.caption) {\n ?"
},
{
"path": "build/falcor-jsdoc-template/tmpl/exceptions.tmpl",
"chars": 703,
"preview": "<?js\n var data = obj;\n?>\n<?js if (data.description && data.type && data.type.names) { ?>\n<dl>\n <dt>\n <div c"
},
{
"path": "build/falcor-jsdoc-template/tmpl/layout.tmpl",
"chars": 68,
"preview": "<?js= content ?>\n\n<?js // All of the content is in container.tmpl ?>"
},
{
"path": "build/falcor-jsdoc-template/tmpl/mainpage.tmpl",
"chars": 260,
"preview": "<?js\nvar data = obj;\nvar self = this;\n?>\n\n<?js if (data.kind === 'package') { ?>\n <h3><?js= data.name ?> <?js= data.v"
},
{
"path": "build/falcor-jsdoc-template/tmpl/members.tmpl",
"chars": 1115,
"preview": "<?js\nvar data = obj;\nvar self = this;\n?>\n<section class=\"member-section\">\n <h4 class=\"name section-header members-hea"
},
{
"path": "build/falcor-jsdoc-template/tmpl/method.tmpl",
"chars": 3366,
"preview": "<?js\nvar data = obj;\nvar self = this;\n?>\n<section class=\"method-section\">\n <?js if (data.kind !== 'module') { ?>\n "
},
{
"path": "build/falcor-jsdoc-template/tmpl/navigation-subgroup.tmpl",
"chars": 498,
"preview": "<?js\n var docs = obj.docs;\n var title = obj.title;\n var id = obj.groupId;\n var self = this;\n?>\n<?js if (docs"
},
{
"path": "build/falcor-jsdoc-template/tmpl/navigation.tmpl",
"chars": 3170,
"preview": "<?js\n (function (self) {\n var classDocs = self.find({kind: 'class'})\n var keys = _.keys(classDocs[1])\n "
},
{
"path": "build/falcor-jsdoc-template/tmpl/params.tmpl",
"chars": 3941,
"preview": "<?js\n var params = obj;\n\n /* sort subparams under their parent params (like opts.classname) */\n var parentParam"
},
{
"path": "build/falcor-jsdoc-template/tmpl/properties.tmpl",
"chars": 2906,
"preview": "<?js\n var data = obj;\n var props = data.subprops || data.properties;\n\n /* sort subprops under their parent prop"
},
{
"path": "build/falcor-jsdoc-template/tmpl/returns.tmpl",
"chars": 325,
"preview": "<?js\nvar data = obj || {};\nif (data.description) {\n?>\n<div class=\"param-desc\">\n <?js= description ?>\n</div>\n<?js } ?>"
},
{
"path": "build/falcor-jsdoc-template/tmpl/source.tmpl",
"chars": 205,
"preview": "<?js\n var data = obj.doc;\n?>\n<h2>\n <?js= obj.fileName ?>\n</h2>\n<section>\n <article>\n <pre class=\"prettyp"
},
{
"path": "build/falcor-jsdoc-template/tmpl/tutorial.tmpl",
"chars": 321,
"preview": "<section>\n\n<header>\n <?js if (children.length > 0) { ?>\n <ul><?js\n var self = this;\n children.forEac"
},
{
"path": "build/falcor-jsdoc-template/tmpl/type.tmpl",
"chars": 221,
"preview": "<?js\n var data = obj;\n var self = this;\n data.forEach(function(name, i) { ?>\n<span class=\"param-type\"><?js= sel"
},
{
"path": "build/gulp-build.js",
"chars": 2383,
"preview": "var gulp = require(\"gulp\");\nvar browserify = require(\"browserify\");\nvar license = require(\"gulp-license\");\nvar uglify = "
},
{
"path": "build/gulp-clean.js",
"chars": 464,
"preview": "var del = require(\"del\");\n\nfunction cleanPerf() {\n return del([\"./performance/bin\", \"./performance/out\"]);\n}\n\nfunctio"
},
{
"path": "build/gulp-perf.js",
"chars": 1230,
"preview": "var gulp = require(\"gulp\");\nvar concat = require(\"gulp-concat\");\nvar vinyl = require(\"vinyl-source-stream\");\nvar browser"
},
{
"path": "build/jsdoc.json",
"chars": 126,
"preview": "{\n \"opts\": {\n \"template\": \"falcor-jsdoc-template\"\n },\n \"templates\": {},\n \"plugins\": [\"plugins/markdow"
},
{
"path": "conf.json",
"chars": 40,
"preview": "{\n \"plugins\": [\"plugins/markdown\"]\n}\n"
},
{
"path": "dist/falcor.all.js",
"chars": 571815,
"preview": "/*!\n * Copyright 2020 Netflix, Inc\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not "
},
{
"path": "dist/falcor.browser.js",
"chars": 293057,
"preview": "/*!\n * Copyright 2020 Netflix, Inc\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not "
},
{
"path": "doc/DataSource.html",
"chars": 23726,
"preview": "---\nlayout: api-page\ntitle: \"Class: DataSource\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n\n <section"
},
{
"path": "doc/FromEsObserverAdapter.html",
"chars": 14197,
"preview": "---\nlayout: api-page\ntitle: \"Class: FromEsObserverAdapter\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n"
},
{
"path": "doc/Model.html",
"chars": 64603,
"preview": "---\nlayout: api-page\ntitle: \"Class: Model\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n\n <section>\n\n "
},
{
"path": "doc/Model.js.html",
"chars": 39861,
"preview": "---\nlayout: api-page\ntitle: \"Model.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>\n Mode"
},
{
"path": "doc/ModelResponse.html",
"chars": 27968,
"preview": "---\nlayout: api-page\ntitle: \"Class: ModelResponse\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n\n <sect"
},
{
"path": "doc/ModelResponseObserver.html",
"chars": 14582,
"preview": "---\nlayout: api-page\ntitle: \"Class: ModelResponseObserver\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n"
},
{
"path": "doc/Observable.html",
"chars": 29789,
"preview": "---\nlayout: api-page\ntitle: \"Class: Observable\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n\n <section"
},
{
"path": "doc/Subscription.html",
"chars": 15392,
"preview": "---\nlayout: api-page\ntitle: \"Class: Subscription\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n\n <secti"
},
{
"path": "doc/ToEsSubscriptionAdapter.html",
"chars": 14219,
"preview": "---\nlayout: api-page\ntitle: \"Class: ToEsSubscriptionAdapter\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n "
},
{
"path": "doc/get_getCache.js.html",
"chars": 14905,
"preview": "---\nlayout: api-page\ntitle: \"get/getCache.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>\n "
},
{
"path": "doc/global.html",
"chars": 53759,
"preview": "---\nlayout: api-page\ntitle: \"Global\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n\n <section>\n\n <heade"
},
{
"path": "doc/index.html",
"chars": 12944,
"preview": "---\nlayout: api-page\ntitle: \"Home\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n\n\n <h3> </h3>\n"
},
{
"path": "doc/index.js.html",
"chars": 13765,
"preview": "---\nlayout: api-page\ntitle: \"index.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>\n inde"
},
{
"path": "doc/internal_index.js.html",
"chars": 13454,
"preview": "---\nlayout: api-page\ntitle: \"internal/index.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>"
},
{
"path": "doc/invalidate_invalidatePathMaps.js.html",
"chars": 17702,
"preview": "---\nlayout: api-page\ntitle: \"invalidate/invalidatePathMaps.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n "
},
{
"path": "doc/invalidate_invalidatePathSets.js.html",
"chars": 18124,
"preview": "---\nlayout: api-page\ntitle: \"invalidate/invalidatePathSets.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n "
},
{
"path": "doc/request_GetRequestV2.js.html",
"chars": 24282,
"preview": "---\nlayout: api-page\ntitle: \"request/GetRequestV2.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/request_RequestQueueV2.js.html",
"chars": 18530,
"preview": "---\nlayout: api-page\ntitle: \"request/RequestQueueV2.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/request_complement.js.html",
"chars": 21839,
"preview": "---\nlayout: api-page\ntitle: \"request/complement.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n"
},
{
"path": "doc/response_AssignableDisposable.js.html",
"chars": 14050,
"preview": "---\nlayout: api-page\ntitle: \"response/AssignableDisposable.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n "
},
{
"path": "doc/response_ModelResponse.js.html",
"chars": 17594,
"preview": "---\nlayout: api-page\ntitle: \"response/ModelResponse.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/response_ModelResponseObserver.js.html",
"chars": 15405,
"preview": "---\nlayout: api-page\ntitle: \"response/ModelResponseObserver.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n "
},
{
"path": "doc/response_get_GetResponse.js.html",
"chars": 15815,
"preview": "---\nlayout: api-page\ntitle: \"response/get/GetResponse.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/response_set_SetResponse.js.html",
"chars": 16514,
"preview": "---\nlayout: api-page\ntitle: \"response/set/SetResponse.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/response_set_setGroupsIntoCache.js.html",
"chars": 14827,
"preview": "---\nlayout: api-page\ntitle: \"response/set/setGroupsIntoCache.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n"
},
{
"path": "doc/response_set_setRequestCycle.js.html",
"chars": 18133,
"preview": "---\nlayout: api-page\ntitle: \"response/set/setRequestCycle.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n"
},
{
"path": "doc/set_setJSONGraphs.js.html",
"chars": 20533,
"preview": "---\nlayout: api-page\ntitle: \"set/setJSONGraphs.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<"
},
{
"path": "doc/set_setPathMaps.js.html",
"chars": 20417,
"preview": "---\nlayout: api-page\ntitle: \"set/setPathMaps.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2"
},
{
"path": "doc/set_setPathValues.js.html",
"chars": 19793,
"preview": "---\nlayout: api-page\ntitle: \"set/setPathValues.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<"
},
{
"path": "doc/support_reconstructPath.js.html",
"chars": 13857,
"preview": "---\nlayout: api-page\ntitle: \"support/reconstructPath.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/toEsObservable.js.html",
"chars": 14374,
"preview": "---\nlayout: api-page\ntitle: \"toEsObservable.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>"
},
{
"path": "doc/typedefs_Atom.js.html",
"chars": 14041,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/Atom.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>\n"
},
{
"path": "doc/typedefs_DataSource.js.html",
"chars": 14904,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/DataSource.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/typedefs_JSONEnvelope.js.html",
"chars": 13398,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/JSONEnvelope.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/typedefs_JSONGraph.js.html",
"chars": 14497,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/JSONGraph.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n"
},
{
"path": "doc/typedefs_JSONGraphEnvelope.js.html",
"chars": 14167,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/JSONGraphEnvelope.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n "
},
{
"path": "doc/typedefs_Key.js.html",
"chars": 13282,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/Key.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>\n "
},
{
"path": "doc/typedefs_KeySet.js.html",
"chars": 13234,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/KeySet.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2"
},
{
"path": "doc/typedefs_Observable.js.html",
"chars": 16422,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/Observable.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n "
},
{
"path": "doc/typedefs_Path.js.html",
"chars": 13274,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/Path.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>\n"
},
{
"path": "doc/typedefs_PathSet.js.html",
"chars": 13474,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/PathSet.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h"
},
{
"path": "doc/typedefs_PathValue.js.html",
"chars": 13357,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/PathValue.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n"
},
{
"path": "doc/typedefs_Range.js.html",
"chars": 13594,
"preview": "---\nlayout: api-page\ntitle: \"typedefs/Range.js\"\nid: api\n---\n\n<main class=\"api-documentation-page\">\n \n\n \n \n \n<h2>"
},
{
"path": "examples/datasource/webWorkerSource.js",
"chars": 5489,
"preview": "// In this example we demonstrate the communication between a model source and a server over a web worker\n\n// Below you "
},
{
"path": "gulpfile.js",
"chars": 1091,
"preview": "var gulp = require(\"gulp\");\nvar gulpShell = require(\"gulp-shell\");\nvar eslint = require(\"gulp-eslint\");\n\nvar clean = req"
},
{
"path": "lib/Model.js",
"chars": 26699,
"preview": "var ModelRoot = require(\"./ModelRoot\");\nvar ModelDataSourceAdapter = require(\"./ModelDataSourceAdapter\");\n\nvar RequestQu"
},
{
"path": "lib/ModelDataSourceAdapter.js",
"chars": 654,
"preview": "function ModelDataSourceAdapter(model) {\n this._model = model._materialize().treatErrorsAsValues();\n}\n\nModelDataSourc"
},
{
"path": "lib/ModelRoot.js",
"chars": 1125,
"preview": "var isFunction = require(\"./support/isFunction\");\nvar hasOwn = require(\"./support/hasOwn\");\n\nfunction ModelRoot(o) {\n\n "
},
{
"path": "lib/deref/hasValidParentReference.js",
"chars": 919,
"preview": "module.exports = function fromWhenceYeCame() {\n var reference = this._referenceContainer;\n\n // Always true when th"
},
{
"path": "lib/deref/index.js",
"chars": 2130,
"preview": "var InvalidDerefInputError = require(\"./../errors/InvalidDerefInputError\");\nvar getCachePosition = require(\"./../get/get"
},
{
"path": "lib/deref/sync.js",
"chars": 906,
"preview": "var pathSyntax = require(\"falcor-path-syntax\");\nvar getBoundValue = require(\"./../get/getBoundValue\");\nvar InvalidModelE"
},
{
"path": "lib/errors/BoundJSONGraphModelError.js",
"chars": 760,
"preview": "var applyErrorPrototype = require(\"./applyErrorPrototype\");\n\n/**\n * When a bound model attempts to retrieve JSONGraph it"
},
{
"path": "lib/errors/InvalidDerefInputError.js",
"chars": 718,
"preview": "var applyErrorPrototype = require(\"./applyErrorPrototype\");\n\n/**\n * An invalid deref input is when deref is used with in"
},
{
"path": "lib/errors/InvalidModelError.js",
"chars": 887,
"preview": "var applyErrorPrototype = require(\"./applyErrorPrototype\");\n\n/**\n * An InvalidModelError can only happen when a user bin"
},
{
"path": "lib/errors/InvalidSourceError.js",
"chars": 769,
"preview": "var applyErrorPrototype = require(\"./applyErrorPrototype\");\n\n/**\n * InvalidSourceError happens when a dataSource syncron"
},
{
"path": "lib/errors/MaxRetryExceededError.js",
"chars": 920,
"preview": "var applyErrorPrototype = require(\"./applyErrorPrototype\");\n\n/**\n * A request can only be retried up to a specified limi"
},
{
"path": "lib/errors/NullInPathError.js",
"chars": 963,
"preview": "var applyErrorPrototype = require(\"./applyErrorPrototype\");\n\n/**\n * Does not allow null in path\n *\n * @private\n * @param"
},
{
"path": "lib/errors/applyErrorPrototype.js",
"chars": 458,
"preview": "function applyErrorPrototype(errorType) {\n errorType.prototype = Object.create(Error.prototype, {\n constructor"
},
{
"path": "lib/get/followReference.js",
"chars": 2535,
"preview": "var createHardlink = require(\"./../support/createHardlink\");\nvar onValue = require(\"./../get/onValue\");\nvar isExpired = "
},
{
"path": "lib/get/get.js",
"chars": 3520,
"preview": "var getCachePosition = require(\"./../get/getCachePosition\");\nvar InvalidModelError = require(\"./../errors/InvalidModelEr"
},
{
"path": "lib/get/getBoundValue.js",
"chars": 1150,
"preview": "var getValueSync = require(\"./../get/getValueSync\");\nvar InvalidModelError = require(\"./../errors/InvalidModelError\");\n\n"
},
{
"path": "lib/get/getCache.js",
"chars": 1822,
"preview": "var isInternalKey = require(\"./../support/isInternalKey\");\n\n/**\n * decends and copies the cache.\n */\nmodule.exports = fu"
},
{
"path": "lib/get/getCachePosition.js",
"chars": 715,
"preview": "/**\n * getCachePosition makes a fast walk to the bound value since all bound\n * paths are the most possible optimized pa"
},
{
"path": "lib/get/getValue.js",
"chars": 1100,
"preview": "var ModelResponse = require(\"./../response/ModelResponse\");\nvar pathSyntax = require(\"falcor-path-syntax\");\n\nmodule.expo"
},
{
"path": "lib/get/getValueSync.js",
"chars": 4125,
"preview": "var followReference = require(\"./../get/followReference\");\nvar clone = require(\"./../get/util/clone\");\nvar isExpired = r"
},
{
"path": "lib/get/getVersion.js",
"chars": 392,
"preview": "var getValueSync = require(\"./getValueSync\");\n\nmodule.exports = function _getVersion(model, path) {\n // ultra fast cl"
},
{
"path": "lib/get/index.js",
"chars": 400,
"preview": "var get = require(\"./get\");\nvar walkPath = require(\"./walkPath\");\n\nvar getWithPathsAsPathMap = get(walkPath, false);\nvar"
},
{
"path": "lib/get/onError.js",
"chars": 507,
"preview": "var promote = require(\"./../lru/promote\");\nvar clone = require(\"./../get/util/clone\");\n\nmodule.exports = function onErro"
},
{
"path": "lib/get/onMissing.js",
"chars": 1919,
"preview": "module.exports = function onMissing(model, path, depth,\n outerResults, requestedPath,"
},
{
"path": "lib/get/onValue.js",
"chars": 4049,
"preview": "var promote = require(\"./../lru/promote\");\nvar clone = require(\"./util/clone\");\nvar $ref = require(\"./../types/ref\");\nva"
},
{
"path": "lib/get/onValueType.js",
"chars": 2845,
"preview": "var isExpired = require(\"./util/isExpired\");\nvar $error = require(\"./../types/error\");\nvar onError = require(\"./onError\""
},
{
"path": "lib/get/sync.js",
"chars": 479,
"preview": "var pathSyntax = require(\"falcor-path-syntax\");\nvar getValueSync = require(\"./getValueSync\");\n\nmodule.exports = function"
},
{
"path": "lib/get/util/clone.js",
"chars": 376,
"preview": "// Copies the node\nvar privatePrefix = require(\"./../../internal/privatePrefix\");\n\nmodule.exports = function clone(node)"
},
{
"path": "lib/get/util/isExpired.js",
"chars": 53,
"preview": "module.exports = require(\"../../support/isExpired\");\n"
},
{
"path": "lib/get/util/isMaterialzed.js",
"chars": 103,
"preview": "module.exports = function isMaterialized(model) {\n return model._materialized && !model._source;\n};\n"
},
{
"path": "lib/get/util/isPathValue.js",
"chars": 76,
"preview": "module.exports = function isPathValue(x) {\n return x.path && x.value;\n};\n"
},
{
"path": "lib/get/walkPath.js",
"chars": 5444,
"preview": "var followReference = require(\"./followReference\");\nvar onValueType = require(\"./onValueType\");\nvar onValue = require(\"."
},
{
"path": "lib/index.js",
"chars": 715,
"preview": "\"use strict\";\n\nfunction falcor(opts) {\n return new falcor.Model(opts);\n}\n\n/**\n * A filtering method for keys from a f"
},
{
"path": "lib/internal/absolutePath.js",
"chars": 62,
"preview": "module.exports = require(\"./privatePrefix\") + \"absolutePath\";\n"
},
{
"path": "lib/internal/context.js",
"chars": 57,
"preview": "module.exports = require(\"./privatePrefix\") + \"context\";\n"
},
{
"path": "lib/internal/head.js",
"chars": 54,
"preview": "module.exports = require(\"./privatePrefix\") + \"head\";\n"
},
{
"path": "lib/internal/index.js",
"chars": 386,
"preview": "/**\n * The list of internal keys. Instead of a bunch of little files,\n * have them as one exports. This makes the bund"
},
{
"path": "lib/internal/invalidated.js",
"chars": 61,
"preview": "module.exports = require(\"./privatePrefix\") + \"invalidated\";\n"
},
{
"path": "lib/internal/key.js",
"chars": 53,
"preview": "module.exports = require(\"./privatePrefix\") + \"key\";\n"
},
{
"path": "lib/internal/model-created.js",
"chars": 62,
"preview": "module.exports = require(\"./privatePrefix\") + \"modelCreated\";\n"
},
{
"path": "lib/internal/next.js",
"chars": 54,
"preview": "module.exports = require(\"./privatePrefix\") + \"next\";\n"
},
{
"path": "lib/internal/parent.js",
"chars": 56,
"preview": "module.exports = require(\"./privatePrefix\") + \"parent\";\n"
},
{
"path": "lib/internal/path.js",
"chars": 54,
"preview": "module.exports = require(\"./privatePrefix\") + \"path\";\n"
},
{
"path": "lib/internal/prev.js",
"chars": 54,
"preview": "module.exports = require(\"./privatePrefix\") + \"prev\";\n"
},
{
"path": "lib/internal/privatePrefix.js",
"chars": 90,
"preview": "var reservedPrefix = require(\"./reservedPrefix\");\n\nmodule.exports = reservedPrefix + \"_\";\n"
},
{
"path": "lib/internal/ref-index.js",
"chars": 58,
"preview": "module.exports = require(\"./privatePrefix\") + \"refIndex\";\n"
},
{
"path": "lib/internal/ref.js",
"chars": 53,
"preview": "module.exports = require(\"./privatePrefix\") + \"ref\";\n"
},
{
"path": "lib/internal/refs-length.js",
"chars": 60,
"preview": "module.exports = require(\"./privatePrefix\") + \"refsLength\";\n"
},
{
"path": "lib/internal/reservedPrefix.js",
"chars": 22,
"preview": "module.exports = \"$\";\n"
},
{
"path": "lib/internal/tail.js",
"chars": 54,
"preview": "module.exports = require(\"./privatePrefix\") + \"tail\";\n"
},
{
"path": "lib/internal/version.js",
"chars": 57,
"preview": "module.exports = require(\"./privatePrefix\") + \"version\";\n"
},
{
"path": "lib/invalidate/invalidatePathMaps.js",
"chars": 4560,
"preview": "var createHardlink = require(\"../support/createHardlink\");\nvar __prefix = require(\"./../internal/reservedPrefix\");\n\nvar "
},
{
"path": "lib/invalidate/invalidatePathSets.js",
"chars": 5003,
"preview": "var __ref = require(\"./../internal/ref\");\n\nvar $ref = require(\"./../types/ref\");\n\nvar getBoundValue = require(\"./../get/"
},
{
"path": "lib/lru/collect.js",
"chars": 1731,
"preview": "var removeNode = require(\"./../support/removeNode\");\nvar updateNodeAncestors = require(\"./../support/updateNodeAncestors"
},
{
"path": "lib/lru/promote.js",
"chars": 1573,
"preview": "var EXPIRES_NEVER = require(\"./../values/expires-never\");\n\n// [H] -> Next -> ... -> [T]\n// [T] -> Prev -> ... -> [H]\nmod"
},
{
"path": "lib/lru/splice.js",
"chars": 832,
"preview": "module.exports = function lruSplice(root, object) {\n\n // Its in the cache. Splice out.\n // eslint-disable-next-li"
},
{
"path": "lib/request/GetRequestV2.js",
"chars": 11166,
"preview": "var complement = require(\"./complement\");\nvar flushGetRequest = require(\"./flushGetRequest\");\nvar incrementVersion = req"
},
{
"path": "lib/request/RequestQueueV2.js",
"chars": 5432,
"preview": "var RequestTypes = require(\"./RequestTypes\");\nvar sendSetRequest = require(\"./sendSetRequest\");\nvar GetRequest = require"
},
{
"path": "lib/request/RequestTypes.js",
"chars": 44,
"preview": "module.exports = {\n GetRequest: \"GET\"\n};\n"
},
{
"path": "lib/request/complement.js",
"chars": 8732,
"preview": "var iterateKeySet = require(\"falcor-path-utils\").iterateKeySet;\n\n/**\n * Calculates what paths in requested path sets can"
},
{
"path": "lib/request/flushGetRequest.js",
"chars": 3999,
"preview": "var pathUtils = require(\"falcor-path-utils\");\nvar toTree = pathUtils.toTree;\nvar toPaths = pathUtils.toPaths;\nvar Invali"
},
{
"path": "lib/request/sendSetRequest.js",
"chars": 2701,
"preview": "var setJSONGraphs = require(\"./../set/setJSONGraphs\");\nvar setPathValues = require(\"./../set/setPathValues\");\nvar Invali"
},
{
"path": "lib/response/AssignableDisposable.js",
"chars": 952,
"preview": "/**\n * Will allow for state tracking of the current disposable. Also fulfills the\n * disposable interface.\n * @private\n"
},
{
"path": "lib/response/CallResponse.js",
"chars": 2326,
"preview": "var ModelResponse = require(\"./../response/ModelResponse\");\nvar InvalidSourceError = require(\"./../errors/InvalidSourceE"
},
{
"path": "lib/response/InvalidateResponse.js",
"chars": 1997,
"preview": "var isArray = Array.isArray;\nvar ModelResponse = require(\"./ModelResponse\");\nvar isPathValue = require(\"./../support/isP"
},
{
"path": "lib/response/ModelResponse.js",
"chars": 4504,
"preview": "var ModelResponseObserver = require(\"./ModelResponseObserver\");\nvar $$observable = require(\"symbol-observable\").default;"
},
{
"path": "lib/response/ModelResponseObserver.js",
"chars": 2305,
"preview": "var noop = require(\"./../support/noop\");\n\n/**\n * A ModelResponseObserver conform to the Observable's Observer contract. "
},
{
"path": "lib/response/get/GetResponse.js",
"chars": 2727,
"preview": "var ModelResponse = require(\"./../ModelResponse\");\nvar checkCacheAndReport = require(\"./checkCacheAndReport\");\nvar getRe"
},
{
"path": "lib/response/get/checkCacheAndReport.js",
"chars": 3665,
"preview": "var gets = require(\"./../../get\");\nvar getWithPathsAsJSONGraph = gets.getWithPathsAsJSONGraph;\nvar getWithPathsAsPathMap"
},
{
"path": "lib/response/get/getRequestCycle.js",
"chars": 4465,
"preview": "var checkCacheAndReport = require(\"./checkCacheAndReport\");\nvar MaxRetryExceededError = require(\"./../../errors/MaxRetry"
},
{
"path": "lib/response/get/getWithPaths.js",
"chars": 283,
"preview": "var GetResponse = require(\"./GetResponse\");\n\n/**\n * Performs a get on the cache and if there are missing paths\n * then t"
},
{
"path": "lib/response/get/index.js",
"chars": 818,
"preview": "var pathSyntax = require(\"falcor-path-syntax\");\nvar ModelResponse = require(\"./../ModelResponse\");\nvar GET_VALID_INPUT ="
},
{
"path": "lib/response/get/validInput.js",
"chars": 59,
"preview": "module.exports = {\n path: true,\n pathSyntax: true\n};\n"
},
{
"path": "lib/response/set/SetResponse.js",
"chars": 3423,
"preview": "var ModelResponse = require(\"./../ModelResponse\");\nvar pathSyntax = require(\"falcor-path-syntax\");\nvar isArray = Array.i"
},
{
"path": "lib/response/set/index.js",
"chars": 624,
"preview": "var setValidInput = require(\"./setValidInput\");\nvar validateInput = require(\"./../../support/validateInput\");\nvar SetRes"
},
{
"path": "lib/response/set/setGroupsIntoCache.js",
"chars": 1722,
"preview": "var arrayFlatMap = require(\"./../../support/array-flat-map\");\n\n/**\n * Takes the groups that are created in the SetRespon"
},
{
"path": "lib/response/set/setRequestCycle.js",
"chars": 5037,
"preview": "var emptyArray = [];\nvar AssignableDisposable = require(\"./../AssignableDisposable\");\nvar GetResponse = require(\"./../ge"
},
{
"path": "lib/response/set/setValidInput.js",
"chars": 102,
"preview": "module.exports = {\n pathValue: true,\n pathSyntax: true,\n json: true,\n jsonGraph: true\n};\n\n"
},
{
"path": "lib/schedulers/ASAPScheduler.js",
"chars": 200,
"preview": "var TimeoutScheduler = require(\"./TimeoutScheduler\");\n\n// Retained for backwards compatibility\nfunction ASAPScheduler() "
},
{
"path": "lib/schedulers/ImmediateScheduler.js",
"chars": 354,
"preview": "var empty = {dispose: function() {}};\n\nfunction ImmediateScheduler() {}\n\nImmediateScheduler.prototype.schedule = functio"
},
{
"path": "lib/schedulers/TimeoutScheduler.js",
"chars": 742,
"preview": "function TimeoutScheduler(delay) {\n this.delay = delay;\n}\n\nvar TimerDisposable = function TimerDisposable(id) {\n t"
},
{
"path": "lib/set/index.js",
"chars": 158,
"preview": "module.exports = {\n setPathMaps: require(\"./setPathMaps\"),\n setPathValues: require(\"./setPathValues\"),\n setJSON"
},
{
"path": "lib/set/setJSONGraphs.js",
"chars": 7451,
"preview": "var createHardlink = require(\"./../support/createHardlink\");\nvar $ref = require(\"./../types/ref\");\n\nvar isExpired = requ"
},
{
"path": "lib/set/setPathMaps.js",
"chars": 7321,
"preview": "var createHardlink = require(\"./../support/createHardlink\");\nvar __prefix = require(\"./../internal/reservedPrefix\");\nvar"
},
{
"path": "lib/set/setPathValues.js",
"chars": 6714,
"preview": "var createHardlink = require(\"./../support/createHardlink\");\nvar $ref = require(\"./../types/ref\");\n\nvar getBoundValue = "
},
{
"path": "lib/set/setValue.js",
"chars": 1196,
"preview": "var jsong = require(\"falcor-json-graph\");\nvar ModelResponse = require(\"./../response/ModelResponse\");\nvar isPathValue = "
},
{
"path": "lib/set/sync.js",
"chars": 1103,
"preview": "var pathSyntax = require(\"falcor-path-syntax\");\nvar isPathValue = require(\"./../support/isPathValue\");\nvar setPathValues"
},
{
"path": "lib/support/array-flat-map.js",
"chars": 370,
"preview": "module.exports = function arrayFlatMap(array, selector) {\n var index = -1;\n var i = -1;\n var n = array.length;\n"
},
{
"path": "lib/support/clone.js",
"chars": 560,
"preview": "var privatePrefix = require(\"./../internal/privatePrefix\");\nvar hasOwn = require(\"./../support/hasOwn\");\nvar isArray = A"
},
{
"path": "lib/support/createHardlink.js",
"chars": 498,
"preview": "var __ref = require(\"./../internal/ref\");\n\nmodule.exports = function createHardlink(from, to) {\n\n // create a back re"
},
{
"path": "lib/support/currentCacheVersion.js",
"chars": 183,
"preview": "var version = null;\nexports.setVersion = function setCacheVersion(newVersion) {\n version = newVersion;\n};\nexports.get"
},
{
"path": "lib/support/expireNode.js",
"chars": 336,
"preview": "var splice = require(\"./../lru/splice\");\n\nmodule.exports = function expireNode(node, expired, lru) {\n // eslint-disab"
},
{
"path": "lib/support/getExpires.js",
"chars": 140,
"preview": "var isObject = require(\"./isObject\");\nmodule.exports = function getSize(node) {\n return isObject(node) && node.$expir"
},
{
"path": "lib/support/getSize.js",
"chars": 140,
"preview": "var isObject = require(\"./../support/isObject\");\nmodule.exports = function getSize(node) {\n return isObject(node) && "
},
{
"path": "lib/support/getTimestamp.js",
"chars": 158,
"preview": "var isObject = require(\"./../support/isObject\");\nmodule.exports = function getTimestamp(node) {\n return isObject(node"
},
{
"path": "lib/support/getType.js",
"chars": 234,
"preview": "var isObject = require(\"./../support/isObject\");\n\nmodule.exports = function getType(node, anyType) {\n var type = isOb"
},
{
"path": "lib/support/hasOwn.js",
"chars": 177,
"preview": "var isObject = require(\"./isObject\");\nvar hasOwn = Object.prototype.hasOwnProperty;\n\nmodule.exports = function(obj, prop"
},
{
"path": "lib/support/identity.js",
"chars": 57,
"preview": "module.exports = function identity(x) {\n return x;\n};\n"
},
{
"path": "lib/support/incrementVersion.js",
"chars": 178,
"preview": "var version = 1;\nmodule.exports = function incrementVersion() {\n return version++;\n};\nmodule.exports.getCurrentVersio"
},
{
"path": "lib/support/insertNode.js",
"chars": 649,
"preview": "/* eslint-disable camelcase */\nmodule.exports = function insertNode(node, parent, key, version, optimizedPath) {\n nod"
},
{
"path": "lib/support/isAlreadyExpired.js",
"chars": 329,
"preview": "var now = require(\"./../support/now\");\nvar $now = require(\"./../values/expires-now\");\nvar $never = require(\"./../values/"
},
{
"path": "lib/support/isExpired.js",
"chars": 308,
"preview": "var now = require(\"./../support/now\");\nvar $now = require(\"../values/expires-now\");\nvar $never = require(\"../values/expi"
},
{
"path": "lib/support/isFunction.js",
"chars": 142,
"preview": "var functionTypeof = \"function\";\n\nmodule.exports = function isFunction(func) {\n return Boolean(func) && typeof func ="
},
{
"path": "lib/support/isInternalKey.js",
"chars": 305,
"preview": "var privatePrefix = require(\"./../internal/privatePrefix\");\n\n/**\n * Determined if the key passed in is an internal key.\n"
},
{
"path": "lib/support/isJSONEnvelope.js",
"chars": 161,
"preview": "var isObject = require(\"./../support/isObject\");\n\nmodule.exports = function isJSONEnvelope(envelope) {\n return isObje"
},
{
"path": "lib/support/isJSONGraphEnvelope.js",
"chars": 390,
"preview": "var isArray = Array.isArray;\nvar isObject = require(\"./../support/isObject\");\n\nmodule.exports = function isJSONGraphEnve"
},
{
"path": "lib/support/isObject.js",
"chars": 130,
"preview": "var objTypeof = \"object\";\nmodule.exports = function isObject(value) {\n return value !== null && typeof value === objT"
},
{
"path": "lib/support/isPathInvalidation.js",
"chars": 191,
"preview": "var isObject = require(\"./../support/isObject\");\n\nmodule.exports = function isPathInvalidation(pathValue) {\n return i"
},
{
"path": "lib/support/isPathValue.js",
"chars": 265,
"preview": "var isArray = Array.isArray;\nvar isObject = require(\"./../support/isObject\");\n\nmodule.exports = function isPathValue(pat"
}
]
// ... and 167 more files (download for full content)
About this extraction
This page contains the full source code of the Netflix/falcor GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 367 files (4.5 MB), approximately 1.2M tokens, and a symbol index with 698 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.