{"id":13698515,"url":"https://github.com/SenseNet/sn-client-js","last_synced_at":"2025-05-04T03:31:28.900Z","repository":{"id":57364433,"uuid":"70572475","full_name":"SenseNet/sn-client-js","owner":"SenseNet","description":"A JavaScript client for sensenet ECM that makes it easy to use the REST API of the Content Repository.","archived":true,"fork":false,"pushed_at":"2018-12-10T07:03:06.000Z","size":786,"stargazers_count":11,"open_issues_count":0,"forks_count":2,"subscribers_count":14,"default_branch":"master","last_synced_at":"2024-11-13T03:34:44.492Z","etag":null,"topics":["ecms","javascript","sensenet","typescript"],"latest_commit_sha":null,"homepage":"https://www.sensenet.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SenseNet.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-10-11T08:27:37.000Z","updated_at":"2023-01-28T19:22:30.000Z","dependencies_parsed_at":"2022-09-13T21:00:55.297Z","dependency_job_id":null,"html_url":"https://github.com/SenseNet/sn-client-js","commit_stats":null,"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-client-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-client-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-client-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SenseNet%2Fsn-client-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SenseNet","download_url":"https://codeload.github.com/SenseNet/sn-client-js/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252283607,"owners_count":21723507,"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":["ecms","javascript","sensenet","typescript"],"created_at":"2024-08-02T19:00:48.308Z","updated_at":"2025-05-04T03:31:27.601Z","avatar_url":"https://github.com/SenseNet.png","language":"TypeScript","funding_links":[],"categories":["Components"],"sub_categories":[],"readme":"# sn-client-js\n\n------\n### This package is not under active development. You can find our latest packages in the [sensenset/sn-client](https://github.com/sensenet/sn-client) monorepo.\n------\n\n[![Gitter chat](https://img.shields.io/gitter/room/SenseNet/SN7ClientAPI.svg?style=flat)](https://gitter.im/SenseNet/SN7ClientAPI)\n[![Build status](https://img.shields.io/travis/SenseNet/sn-client-js.svg?style=flat)](https://travis-ci.org/SenseNet/sn-client-js)\n[![Coverage](https://img.shields.io/codecov/c/github/SenseNet/sn-client-js.svg?style=flat)](https://codecov.io/gh/SenseNet/sn-client-js)\n[![Codacy Badge](https://api.codacy.com/project/badge/Grade/b09d599538fa49e9bb1cb92df4042ada)](https://www.codacy.com/app/herflis33/sn-client-js?utm_source=github.com\u0026amp;utm_medium=referral\u0026amp;utm_content=SenseNet/sn-client-js\u0026amp;utm_campaign=Badge_Grade)\n[![NPM version](https://img.shields.io/npm/v/sn-client-js.svg?style=flat)](https://www.npmjs.com/package/sn-client-js)\n[![NPM downloads](https://img.shields.io/npm/dt/sn-client-js.svg?style=flat)](https://www.npmjs.com/package/sn-client-js)\n[![License](https://img.shields.io/github/license/SenseNet/sn-client-js.svg?style=flat)](https://github.com/SenseNet/sn-client-js/LICENSE.txt)\n[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg?style=flat)](https://github.com/semantic-release/semantic-release)\n[![Commitizen friendly](https://img.shields.io/badge/commitizen-friendly-brightgreen.svg?style=flat)](http://commitizen.github.io/cz-cli/)\n[![Greenkeeper badge](https://badges.greenkeeper.io/SenseNet/sn-client-js.svg)](https://greenkeeper.io/)\n\n\u003e sn-client-js has been refactored into several smaller packages within the **[@sensenet](https://www.npmjs.com/search?q=%40sensenet)** scope in NPM, therefore sn-client-js will not be updated. Please switch to the @sensenet scoped packages if possible. You can find more details in this [post](https://community.sensenet.com/blog/2018/02/21/scoped-packages)\n\nThis component lets you work with the [sensenet ECM](https://github.com/SenseNet) Content Repository (create or manage content, execute queries, etc.) by providing a JavaScript client API for the main content operations.\nThe library connects to a sensenet ECM portal's REST API, but hides the underlying HTTP requests. You can work with simple load or create Content operations in JavaScript, instead of\nhaving to construct ajax requests yourself.\n\nIt also provides you the full sensenet Content Type system hierarchy through Typescript classes with all the fields defined in the CTDs and the Content Type schemas with FieldSettings\nso that you can manage Content easy on client-side knowing the related fields and their settings.\n\n\u003e Tested with the following Sense/Net Services version: \n\u003e \n\u003e [![Sense/Net Services](https://img.shields.io/badge/sensenet-7.0.0--beta%20tested-green.svg)](https://github.com/SenseNet/sensenet/releases/tag/v7.0.0-beta3)\n\n## Installation with node and npm\n\nTo install the latest stable version run\n\n```\nnpm install --save sn-client-js\n```\n\n## Usage\n\n### Creating a Repository instance\nYour main entry point in this library is the Repository object. You can create an Instance by the following way:\n\n```ts\nimport { Repository } from 'sn-client-js';\n\nlet repository = new Repository.SnRepository({\n            RepositoryUrl: 'https://my-sensenet-site.com',\n            ODataToken: 'OData.svc',\n            JwtTokenKeyTemplate: 'my-${tokenName}-token-for-${siteName}',\n            JwtTokenPersist: 'expiration',\n\t\t\tDefaultSelect: ['DisplayName', 'Icon'],\n\t\t\tRequiredSelect: ['Id', 'Type', 'Path', 'Name'],\n\t\t\tDefaultMetadata: 'no',\n\t\t\tDefaultInlineCount: 'allpages',\n\t\t\tDefaultExpand: [],\n\t\t\tDefaultTop: 1000\n        });\n```\n - __RepositoryURL__: The component will communicate with your repositoy using the following url. This will fall back to your _window.location.href_, if not specified. To enable your external app to send request against your sensenet portal change your ```Portal.settings```. For further information about cross-origin resource sharing in sensenet check [this](community.sensenet.com/docs/cors/)\narticle.\n - __ODataToken__: Check your Sense/Net portal's web.config and if the ```ODataServiceToken``` is set, you can configure it here for the client side.\n - __JwtTokenKeyTemplate__ - This will be the template how your JWT tokens will be stored (in _local/session storage_ or as a _cookie_). _${tokenName}_ will be replaced with the token's name ('access' or 'refresh'), _${siteName}_ will be replaced with your site's name\n - __JwtTokenPersist__ - You can change how JWT Tokens should be persisted on the client, you can use _'session'_, whitch means the token will be invalidated on browser close, or _'expiration'_, in that case the token expiration property will be used (See [JWT Token docs](http://community.sensenet.com/docs/web-token-authentication/) for further details)\n - __DefaultSelect__ - These fields will be selected by default on each OData request. Can be a field, an array of fields or 'all'\n - __RequiredSelect__ - These fields will always be included in the OData *$select* statement. Also can be a field, an array of fields or 'all'\n - __DefaultMetadata__ - Default *metadata* value for OData requests. Can be 'full', 'minimal' or 'no'\n - __DefaultInlineCount__ - Default *inlinecount* OData parameter. Can be 'allpages' or 'none'\n - __DefaultExpand__ - Default fields to *$expand*, empty by default. Can be a field or an array of fields.\n - __DefaultTop__ - Default value to the odata *$top* parameter\n\n### Create, Save, Update\n\nYou can create a new *content* instance in the following way:\n```ts\nimport { ContentTypes } from 'sn-client-js';\n\nlet myTask = repository.CreateContent({\n\t\tName: 'MyTask',\n\t\tPath: '/Root/MyWorkspace/MyTaskList'\n\t},\n\tContentTypes.Task);\n```\nThe content is not posted to the Reposiory yet, but you can *bind* it to a Create content form and update it's values like this:\n```ts\nmyTask.DueDate = \"2017-09-12T12:00:00Z\";\n```\nYou can always check if a specified content has been saved or not with the  ```content.IsSaved ``` property.\n\nIf you've finished with the editing, you can Save it the following way:\n```ts\nmyTask.Save().subscribe(task=\u003e{\n\tconsole.log('Task saved', task);\n}, error =\u003e console.error);\n```\nOnce the Task has been saved, you can continue working *on the same object reference*, update fields and call ```myTask.Save()``` again, the content will be **updated** in the sensenet ECM Repository.\n\nIf you want to update **a specified field only**, you can do that with an optional Save() parameter (other changed properties will be ignored):\n```ts\nmyTask.Save({DisplayName: 'Updated Task Displayname'}).subscribe(task=\u003e{\n\tconsole.log('Task saved', task);\n}, error =\u003e console.error)\n```\n\n### Load, Reload\nYou can load a content instance from the repository by the following way:\n\n```ts\n//by Path\nrepository.Load('Root/MyWorkspace/MyTaskList/MyTask1').subscribe(loadedTask=\u003e{\n\tconsole.log('Task loaded', loadedTask);\n}, error =\u003e console.error);\n\n//or by Id\nlet myTaskId = 12345\nrepository.Load(myTaskId).subscribe(loadedTask=\u003e{\n\tconsole.log('Task loaded', loadedTask);\n}, error =\u003e console.error);\n\n//you can also specify which fields you want to load or expand\nrepository.Load(myTaskId, {\n\tselect: ['Name', 'DisplayName'],\n\texpand: 'Owner'\n}).subscribe(loadedTask =\u003e {\n\tconsole.log('Task loaded', loadedTask);\n}, error =\u003e console.error);\n```\n\u003e If you *load* or *reload* the same content from the same repository, you will get the same *object reference*\n\nIf you use Schema definition and you need to *reload* a content for a specified action (can be 'view' or 'edit' for now) you can do that with:\n```ts\nmyTask.Reload('view').subscribe(reloadedTask=\u003e{\n\tconsole.log('Task reloaded', reloadedTask);\n}, error =\u003e console.error)\n```\nIf you want to reload only specific *fields* or *references*, you can do that in the following way:\n```ts\nmyTask.ReloadFields('Owner', 'Name', 'ModifiedBy').subscribe(reloadedTask=\u003e{\n\tconsole.log('Fields loaded', reloadedTask);\n}, error =\u003e console.error)\n```\n\n### Reference fields\n\nYou can query reference fields like the following:\n```ts\nmyTask.CreatedBy.GetContent().subscribe(createdBy =\u003e {\n\tconsole.log('Task is created by', createdBy);\n});\n```\n\u003e Reference fields are loaded lazily. This means that if their value isn't loaded yet, it will make an additional HTTP request. If you know exactly what reference fields will be used, call *content.Reload('view' | 'edit')* or content.ReloadFields(...fields) to speed things up.\n\n\n### Delete\nIf you want to delete a content *permanently* (or just move it to the Trash folder), you can simply call:\n```ts\nlet permanently = false;\nmyTask.Delete(permanently).subscribe(()=\u003e{\n\tconsole.log('Moved to trash.');\n}, err=\u003e console.error);\n```\n\n### Tracking changes\nThere are several methods to track the state of content instances\n - **content.IsSaved** - Shows if the content is just created or is saved to the *Repository*\n - **content.IsDirty** - Indicates if some of its fields has changed\n - **content.IsValid** - Indicates if all complusory fields has been filled\n - **content.SavedFields** - Returns an object with the last saved fields\n - **content.GetChanges()** - Returns an object with the changed fields and their new values\n \u003e If the *content* is partially loaded, only their *loaded* fields or references will be tracked.\n\n### Hierarchical content comparison\nAs sensenet ECM stores content in a tree-based repository, there are some methods for hierarchical comparison between content. These methods are:\n - content.IsParentOf(childContent: Content): boolean\n - content.IsChildOf(parentContent: Content): boolean\n - content.IsAncestorOf(descendantContent: Content): boolean\n - content.IsDescendantOf(ancestorContent: Content): boolean\n\n### Repository events\nThere are some Event *Observables* on the **Repository** level which you can subscribe for tracking changes. You can find them on the **repository.Events** namespace. They are:\n - OnContentCreated\n - OnContentCreateFailed\n - OnContentModified\n - OnContentModificationFailed\n - OnContentLoaded\n - OnContentDeleted\n - OnContentDeleteFailed\n - OnContentMoved\n - OnContentMoveFailed\n - OnCustomActionExecuted\n - OnCustomActionFailed\n\n\n### Content Queries\nYou can run queries from a *repository instance* or from a *content instance*. There is a fluent API for creating type safe and valid *Content Queries*\n```ts\nconst query = repository.CreateQuery(q =\u003e \n\tq.TypeIs(ContentTypes.Folder)\n\t\t.And\n\t\t.Equals('DisplayName', 'a*')\n\t\t.Top(10));\n\nquery.Exec()\n\t.subscribe(res =\u003e {\n    \tconsole.log('Folders count: ', res.Count);\n    \tconsole.log('Folders: ', res.Result);\n} \n```\n\n### Get the Schema of the given ContentType\n\n```ts\nlet schema = Content.GetSchema(ContentTypes.GenericContent);\n```\n\n### Read Collection data\n \n```ts\n\nimport { Collection } from 'sn-client-js';\n\nlet collection = new Collection([], repository, ContentTypes.Task);\n\nlet fetchContent = collection.Read('/NewsDemo/External', { select: 'all' }); //gets the list of  the external Articles with their Id, Type and DisplayName fields.\n   fetchContent\n   \t.map(response =\u003e response.d.results)\n    .subscribe({\n    \tnext: response =\u003e {\n     \t\t//do something with the response\n     \t},\n     \terror: error =\u003e console.error('something wrong occurred: ' + error),\n     \tcomplete: () =\u003e console.log('done'),\n\t});\n```\n\n### Delete a Content from a Collection\n \n```ts\nlet deleteContent = myCollection.Remove(3);\n\tdeleteContent\n\t.subscribe({\n\t\tnext: response =\u003e {\n\t\t\t//do something after delete\n\t\t},\n\t\terror: error =\u003e console.error('something wrong occurred: ' + error),\n\t\tcomplete: () =\u003e console.log('done'),\n\t});\n```\n\n## Building sn-client-js from source\n 1. Clone the repository: ```git clone https://github.com/SenseNet/sn-client-js.git```\n 2. Go to the sn-client-js directory: ```cd sn-client-js ```\n 3. Install dependencies: ```npm install```\n 4. Build the project: ```npm run build```\nTo run the linter and building the project, use:\n\n```\nnpm run build\n```\n\n## Running the unit tests\n\nTo execute all unit tests and generate the coverage report, run: ```npm run test```\n\n## Related documents\n* [sn-client-js API reference](http://www.sensenet.com/documentation/sn-client-js/index.html)\n* [sn-redux API reference](http://www.sensenet.com/documentation/sn-redux/index.html)\n* [Todo App with React, Redux and Sense/Net ECM](https://github.com/SenseNet/sn-react-redux-todo-app)\n* [Todo App with Angular, Redux and Sense/Net ECM](https://github.com/blaskodaniel/sn-angular-redux-todo-app)\n* [Todo App with Angular2, Redux and Sense/Net ECM](https://github.com/SenseNet/sn-angular2-redux-todo-app)\n* [Todo App with Aurelia, Redux and Sense/Net ECM](https://github.com/B3zo0/sn7-aurelia-redux-todo-app)\n* [Todo App with Vue, Redux and Sense/Net ECM](https://github.com/SenseNet/sn-vue-redux-todo-app)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSenseNet%2Fsn-client-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FSenseNet%2Fsn-client-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FSenseNet%2Fsn-client-js/lists"}