{"id":13839459,"url":"https://github.com/strongloop/strong-remoting","last_synced_at":"2025-04-12T23:29:18.745Z","repository":{"id":8451090,"uuid":"10045175","full_name":"strongloop/strong-remoting","owner":"strongloop","description":"Communicate between objects in servers, mobile apps, and other servers.","archived":false,"fork":false,"pushed_at":"2024-05-02T08:46:28.000Z","size":2228,"stargazers_count":105,"open_issues_count":4,"forks_count":92,"subscribers_count":46,"default_branch":"master","last_synced_at":"2024-05-17T21:03:03.404Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"www.strongloop.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/strongloop.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGES.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-05-14T01:53:04.000Z","updated_at":"2024-05-30T01:30:14.161Z","dependencies_parsed_at":"2024-05-30T01:30:12.407Z","dependency_job_id":"5a269e94-0260-4ba2-ba7b-9d7ca985fc99","html_url":"https://github.com/strongloop/strong-remoting","commit_stats":{"total_commits":584,"total_committers":76,"mean_commits":7.684210526315789,"dds":0.7688356164383562,"last_synced_commit":"baa3a5baaae0a1a883dfbe7eddc26982ca071959"},"previous_names":[],"tags_count":140,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strongloop%2Fstrong-remoting","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strongloop%2Fstrong-remoting/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strongloop%2Fstrong-remoting/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/strongloop%2Fstrong-remoting/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/strongloop","download_url":"https://codeload.github.com/strongloop/strong-remoting/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248646629,"owners_count":21139042,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T17:00:27.127Z","updated_at":"2025-04-12T23:29:18.718Z","avatar_url":"https://github.com/strongloop.png","language":"JavaScript","funding_links":[],"categories":["Core"],"sub_categories":[],"readme":"# strong-remoting\n\n**⚠️ LoopBack 3 is in Maintenance LTS mode, only critical bugs and critical\nsecurity fixes will be provided. (See\n[Module Long Term Support Policy](#module-long-term-support-policy) below.)**\n\nWe urge all LoopBack 3 users to migrate their applications to LoopBack 4 as\nsoon as possible. Refer to our\n[Migration Guide](https://loopback.io/doc/en/lb4/migration-overview.html)\nfor more information on how to upgrade.\n\nIf you are building directly on top of strong-remoting without LoopBack,\nthen please [open a new GitHub issue](https://github.com/strongloop/strong-remoting/issues/new)\nto discuss the specifics.\n\n## Overview\n\nObjects (and, therefore, data) in Node applications commonly need to be accessible by other Node processes, browsers, and even mobile clients.   Strong remoting:\n\n * Makes local functions remotable, exported over adapters.\n * Supports multiple transports, including custom transports.\n * Manages serialization to JSON and deserialization from JSON.\n * Supports multiple client SDKs, including mobile clients.\n\n\u003cdiv class=\"gh-only\"\u003e\nAlso see the \u003ca href=\"http://loopback.io/doc/en/lb2/Strong-Remoting.html\"\u003eofficial StrongLoop documentation\u003c/a\u003e.\u003c/div\u003e\n\n### Client SDK support\n\nFor higher-level transports, such as REST and Socket.IO, existing clients will work well. If you want to be able to swap out your transport, use one of our supported clients. The same adapter model available on the server applies to clients, so you can switch transports on both the server and all clients without changing your application-specific code.\n\n## Module Long Term Support Policy\n\nThis module adopts the [Module Long Term Support (LTS)](http://github.com/CloudNativeJS/ModuleLTS) policy, with the following End Of Life (EOL) dates:\n\n| Version           | Status          | Published | EOL      |\n| ----------------- | --------------- | --------- | -------- |\n| strong-remoting@3 | Maintenance LTS | Dec 2016  | Dec 2020 |\n| strong-remoting@2 | End-of-Life     | Jul 2014  | Apr 2019 |\n\nLearn more about our LTS plan in [docs](https://loopback.io/doc/en/contrib/Long-term-support.html).\n\n## Installation\n\n```sh\n$ npm install strong-remoting\n```\n\n## Quick start\n\nThe following example illustrates how to set up a basic strong-remoting server with a single remote method, user.greet.\n\n```js\n// Create a collection of remote objects.\nvar remoting = require('../');\nvar SharedClass = remoting.SharedClass\nvar remotes = remoting.create();\n\n// define a class-like object (or constructor)\nfunction User() {\n\n}\n\nUser.greet = function (fn) {\n  fn(null, 'hello, world!');\n}\n\n// create a shared class to allow strong-remoting to map\n// http requests to method invocations on your class\nvar userSharedClass = new SharedClass('user', User);\n\n// Tell strong-remoting about your greet method\nuserSharedClass.defineMethod('greet', {\n  isStatic: true, // not an instance method\n  returns: [{\n    arg: 'msg',\n    type: 'string' // define the type of the callback arguments\n  }]\n});\n// Expose it over the REST transport.\nrequire('http')\n  .createServer(remotes.handler('rest'))\n  .listen(3000);\n```\n\nThen, invoke `User.greet()` easily with `curl` (or any HTTP client)!\n\n    $ curl http://localhost:3000/user/greet?str=hello\n\nResult:\n\n```\n{\n  \"msg\": \"hello world\"\n}\n```\n\n## Concepts\n\n### Remote objects\n\nMost Node applications expose a remotely-available API.  Strong-remoting enables you to build your app in vanilla JavaScript and export remote objects over the network the same way you export functions from a module. Since they're just plain JavaScript objects, you can always invoke methods on your remote objects locally in JavaScript, whether from tests or other, local objects.\n\n### Remote object collections\n\nCollections that are the result of require('strong-remoting').create() are responsible for binding their remote objects to transports, allowing you to swap out the underlying transport without changing any of your application-specific code.\n\n### Adapters\n\nAdapters provide the transport-specific mechanisms to make remote objects (and collections thereof) available over their transport. The REST adapter, for example, handles an HTTP server and facilitates mapping your objects to RESTful resources. Other adapters, on the other hand, might provide a less opinionated, RPC-style network interface. Your application code doesn't need to know what adapter it's using.\n\n### Hooks\n\nHooks enable you to run code before remote objects are constructed or methods on those objects are invoked. For example, you can prevent actions based on context (HTTP request, user credentials, and so on).\n\n```js\n// Do something before any hook is executed\nremotes.authorization = function(ctx, next) {\n  if(checkContext(ctx)) {\n    // allow\n    next();\n  } else {\n    // deny\n    var err = new Error('denied!');\n    err.statusCode = 401;\n    next(err);\n  }\n}\n\n// Do something before our `user.greet` example, earlier.\nremotes.before('user.greet', function (ctx, next) {\n  if((ctx.req.param('password') || '').toString() !== '1234') {\n    next(new Error('Bad password!'));\n  } else {\n    next();\n  }\n});\n\n// Do something before any `user` method.\nremotes.before('user.*', function (ctx, next) {\n  console.log('Calling a user method.');\n  next();\n});\n\n// Do something before a `dog` instance method.\nremotes.before('dog.prototype.*', function (ctx, next) {\n  var dog = this;\n  console.log('Calling a method on \"%s\".', dog.name);\n  next();\n});\n\n// Do something after the `speak` instance method.\n// NOTE: you cannot cancel a method after it has been called.\nremotes.after('dog.prototype.speak', function (ctx, next) {\n  console.log('After speak!');\n  next();\n});\n\n// Do something before all methods.\nremotes.before('**', function (ctx, next, method) {\n  console.log('Calling:', method.name);\n  next();\n});\n\n// Modify all returned values named `result`.\nremotes.after('**', function (ctx, next) {\n  ctx.result += '!!!';\n  next();\n});\n```\n\nHooks accept an asynchronous handler function that is called for every request. This handler function signals the completion either by accepting a callback argument or returning a promise.  For example:\n\n```js\n// accepting a callback argument\nremotes.after('dog.prototype.speak', function(ctx, next) {\n  console.log('After speak!');\n  next();\n});\n\n// returning a promise\nremotes.after('dog.prototype.speak', function(ctx) {\n  console.log('After speak!');\n  return Promise.resolve();\n});\n```\n\nSee the before-after example for more info.\n\n### Streams\n\nStrong-remoting supports methods that expect or return Readable and Writeable streams. This enables you to stream raw binary data such as files over the network without writing transport-specific behavior.\n\nFor example, the following code exposes a method of the `fs` Remote Object, `fs.createReadStream`, over the REST adapter:\n\n```js\n// Create a Collection.\nvar remotes = require('strong-remoting').create();\n\n// Share some fs module code.\nvar fs = remotes.exports.fs = require('fs');\n\n// Specifically export the `createReadStream` function.\nfs.createReadStream.shared = true;\n\n// Describe the arguments.\nfs.createReadStream.accepts = {arg: 'path', type: 'string'};\n\n// Describe the stream destination.\nfs.createReadStream.http = {\n  // Pipe the returned `Readable` stream to the response's `Writable` stream.\n  pipe: {\n    dest: 'res'\n  }\n};\n\n// Expose the Collection over the REST Adapter.\nrequire('http')\n  .createServer(remotes.handler('rest'))\n  .listen(3000);\n```\n\nThen you can invoke `fs.createReadStream()` using curl as follows:\n\n```sh\n$ curl http://localhost:3000/fs/createReadStream?path=some-file.txt\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrongloop%2Fstrong-remoting","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstrongloop%2Fstrong-remoting","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstrongloop%2Fstrong-remoting/lists"}