{"id":21820310,"url":"https://github.com/trademe/ensure","last_synced_at":"2025-04-14T02:44:35.698Z","repository":{"id":20322563,"uuid":"89452082","full_name":"TradeMe/ensure","owner":"TradeMe","description":"Utility decorators for Trade Me","archived":false,"fork":false,"pushed_at":"2024-01-12T00:53:53.000Z","size":602,"stargazers_count":4,"open_issues_count":29,"forks_count":4,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-27T16:49:53.126Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TradeMe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-04-26T07:35:03.000Z","updated_at":"2023-02-08T20:50:00.000Z","dependencies_parsed_at":"2024-11-27T16:46:46.555Z","dependency_job_id":null,"html_url":"https://github.com/TradeMe/ensure","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TradeMe%2Fensure","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TradeMe%2Fensure/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TradeMe%2Fensure/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TradeMe%2Fensure/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TradeMe","download_url":"https://codeload.github.com/TradeMe/ensure/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248812788,"owners_count":21165482,"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-11-27T16:31:17.651Z","updated_at":"2025-04-14T02:44:35.660Z","avatar_url":"https://github.com/TradeMe.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @trademe/ensure - utility decorators for Angular applications.\n\n[![npm version](https://img.shields.io/npm/v/@trademe/ensure.svg)](https://www.npmjs.com/package/@trademe/ensure)\n\n## `@Value`:\n\nThis decorator can be applied to properties on a class to ensure that they conform to guards when they are set. The guards also act as a mechanism for casting values from HTML attributes, which makes for nicer component APIs.\n\n### Example:\n\n```typescript\nimport { Value } from '@trademe/ensure';\n\nexport class MyClass {\n    @Value(isOne) mustBeOne: number;\n    @Value(isString, isLengthFive) verySpecificString: string;\n}\n\nexport function isOne (value: any) {\n    if (value === 1) {\n        return value;\n    }\n    throw new Error();\n}\n\nexport function isString (value: string) {\n    if (typeof value === 'string') {\n        return value;\n    }\n    throw new Error();\n}\n\nexport function isLengthFive (value: string) {\n    if (value.length === 5) {\n        return value;\n    }\n    throw new Error();\n}\n```\n\n### Built in guards:\n\n#### `isNotNull`\n\nEnsure that a value is not `null`. `isNotNull` is special in that it acts when *getting* the value, not setting it.\n\n#### Example:\n\n```typescript\nimport { isNotNull } from '@trademe/ensure';\n\nexport class MyClass {\n    @Value(isNotNull) mustNotBeNull: boolean;\n}\n\nlet instance = new MyClass();\ninstance.mustNotBeNull = true; // works\ninstance.mustNotBeNull = null; // works\nconsole.log(instance.mustNotBeNull): // throws!\n```\n\n#### `isBool`\n\nEnsure that a value is boolean. Also casts from `'true'` or `''` to `true` and `'false'` to `false`.\n\n#### Example:\n\n```typescript\nimport { isBool } from '@trademe/ensure';\n\nexport class MyClass {\n    @Value(isBool) mustBeBoolean: boolean;\n}\n\nlet instance = new MyClass();\ninstance.mustBeBoolean = true; // works\ninstance.mustBeBoolean = 'hello'; // throws!\ninstance.mustBeBoolean = 'false'; // works\nconsole.log(instance.mustBeBoolean) // false\n```\n\n`isBool` is particularly useful for simplifying component APIs when combined with `@Input`.\n\n#### Example:\n\n```typescript\nimport { isBool } from '@trademe/ensure';\n\n@Component({ ... })\nexport class MyComponent {\n    @Input() @Value(isBool) mustBeBoolean: boolean;\n}\n```\n\n```html\n\u003cmy-component\n  mustBeBoolean\u003e\u003c!-- No more pesky =\"true\"! --\u003e\n\u003c/my-component\u003e\n```\n\n#### `isEnum`\n\nEnsure that a value is a valid enum value.\n\n#### Example:\n\n```typescript\nimport { isEnum } from '@trademe/ensure';\n\nexport enum MyEnum {\n    foo,\n    bar\n}\n\nexport class MyClass {\n    @Value(isEnum\u003ctypeof MyEnum\u003e(MyEnum)) mustBeEnum: MyEnum;\n}\n\nlet instance = new MyClass();\ninstance.mustBeEnum = 'foo'; // works\nconsole.log(instance.mustBeEnum); // 0\ninstance.mustBeEnum = 'bar'; // works!\nconsole.log(instance.mustBeEnum); // 1\ninstance.mustBeEnum = 'baz'; // throws!\n```\n\n#### `isNumber`\n\nEnsure that a value is a valid number.\n\n#### Example:\n\n```typescript\nimport { isNumber } from '@trademe/ensure';\n\nexport class MyClass {\n    @Value(isNumber) mustBeNumber: number;\n}\n\nlet instance = new MyClass();\ninstance.mustBeNumber = 5; // works\nconsole.log(instance.mustBeNumber); // 5\ninstance.mustBeNumber = '1.33'; // works!\nconsole.log(instance.mustBeNumber); // 1.33\ninstance.mustBeNumber = 'baz'; // throws!\n```\n\n### Custom guards:\n\nSometimes it is useful to write your own guards. To do that, we provide an `ensure` method, which you need to wrap your rule with:\n\n```typescript\nimport { ensure, EnsureError } from '@trademe/ensure';\n\nexport const isInt = ensure((value: any, key: string): number =\u003e {\n    const num = +parseInt(value, 10);\n    if (isNaN(num)) {\n        throw new EnsureError(`\n            '${key}' must be a number.\n        `);\n    }\n    if (`${num}` !== `${value}`) {\n        throw new EnsureError(`\n            '${key}' must be an integer.\n        `);\n    }\n    return num;\n});\n```\n\nIf you need to do something more complicated, say with arguments, the *inner* function should be wrapped with `ensure`. You can also indicate that a guard should be run when the property is `get` rather than `set`:\n\n```typescript\n\nimport { ensure, EnsureError } from '@trademe/ensure';\n\nexport function isMutuallyExclusive (mutuallyExclusiveKey: string): Function {\n    return ensure((value: any, key: string): any {\n        let mutuallyExclusiveValue = this[mutuallyExclusiveKey];\n        if (mutuallyExclusiveValue != null \u0026\u0026 mutuallyExclusiveValue !== false) {\n            throw new EnsureError(`\n               \"${key}\" and \"${mutuallyExclusiveKey}\" cannot be used at the same time.\n            `);\n        }\n        return value;\n    }, {\n        getter: true\n    });\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrademe%2Fensure","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrademe%2Fensure","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrademe%2Fensure/lists"}