New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@cap-js/cds-typer

Package Overview
Dependencies
Maintainers
2
Versions
41
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cap-js/cds-typer - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

15

CHANGELOG.md

@@ -7,4 +7,17 @@ # Change Log

## Version 0.4.1 - TBD
## Version 0.5.1 - TBD
## Version 0.5.0 - 2023-07-25
### Changed
- Facilitate strict property checks. Note: `checkJs: true` must be present in the project's _jsconfig.json_ or _tsconfig.json_ respectively for this feature to become effective
### Added
- Support for `array of` syntax
### Fixes
- Generate `string` type for date-related types in CDS definitions
- Generate `Buffer | string` type for the CDS type `LargeBinary`
## Version 0.4.0 - 2023-07-06

@@ -11,0 +24,0 @@ ### Added

58

lib/cli.js

@@ -9,20 +9,18 @@ #!/usr/bin/env node

const path = require('path')
const { EOL } = require('node:os')
const EOL2 = EOL + EOL
const toolName = 'cds-typer'
const flags = {
// FIXME: remove asap
rootDir: {
desc: '[DEPRICATED] use outputDirectory instead',
default: './',
},
outputDirectory: {
desc: 'root directory to write generated files to',
desc: 'Root directory to write the generated files to.',
default: './',
type: 'string'
},
help: {
desc: 'this text',
desc: 'This text.',
},
logLevel: {
desc: `minimum log level`,
desc: `Minimum log level that is printed.`,
allowed: Object.keys(Levels),

@@ -32,9 +30,10 @@ default: Object.keys(Levels).at(-1),

jsConfigPath: {
desc: `Path to where the jsconfig.json should be written. If specified, ${toolName} will create a jsconfig.json file and set it up to restrict property usage in types entities to existing properties only.`,
desc: `Path to where the jsconfig.json should be written.${EOL}If specified, ${toolName} will create a jsconfig.json file and${EOL}set it up to restrict property usage in types entities to${EOL}existing properties only.`,
type: 'string'
},
version: {
desc: 'prints the version of this tool'
desc: 'Prints the version of this tool.'
},
inlineDeclarations: {
desc: 'whether to resolve inline type declarations flat (x_a, x_b, ...) or structured (x: {a, b})',
desc: `Whether to resolve inline type declarations${EOL}flat: (x_a, x_b, ...)${EOL}or structured: (x: {a, b}).`,
allowed: ['flat', 'structured'],

@@ -44,3 +43,3 @@ default: 'structured'

propertiesOptional: {
desc: 'if set to true, properties in entities are always generated as optional (a?: T)',
desc: `If set to true, properties in entities are${EOL}always generated as optional (a?: T).`,
allowed: ['true', 'false'],

@@ -52,36 +51,39 @@ default: 'true'

const hint = () => console.log('Missing or invalid parameter(s). Call with --help for more details.')
const indent = (s, indentation) => s.split(EOL).map(line => `${indentation}${line}`).join(EOL)
const help = () =>
console.log(
'[SYNOPSIS]\n' +
'Call with at least one positional parameter pointing to the (root) CDS file you want to compile.\n' +
'Additionaly, you can use the following parameters:\n' +
const help = () => `SYNOPSIS${EOL2}` +
indent(`cds-typer [cds file | "*"]`, ' ') + EOL2 +
indent(`Generates type information based on a CDS model.${EOL}Call with at least one positional parameter pointing${EOL}to the (root) CDS file you want to compile.`, ' ') + EOL2 +
`OPTIONS${EOL2}` +
Object.entries(flags)
.sort()
.map(([key, value]) => {
let s = `--${key}: ${value.desc}`
let s = indent(`--${key}`, ' ')
if (value.allowed) {
s += ` [allowed: ${value.allowed.join(' | ')}]`
s += `: <${value.allowed.join(' | ')}>`
} else if (value.type) {
s += `: <${value.type}>`
}
if (value.default) {
s += ` (default: ${value.default})`
s += EOL
s += indent(`(default: ${value.default})`, ' ')
}
s += `${EOL2}${indent(value.desc, ' ')}`
return s
}
).join('\n\n')
)
).join(EOL2)
const version = () => console.log(require('../package.json').version)
const version = () => require('../package.json').version
const main = async (args) => {
if ('help' in args.named) {
help()
console.log(help())
process.exit(0)
}
if ('version' in args.named) {
version()
console.log(version())
process.exit(0)
}
if (args.positional.length === 0) {
hint()
console.log(hint())
process.exit(1)

@@ -105,1 +107,5 @@ }

}
function helpToCapire() {
}

@@ -12,2 +12,6 @@ 'use strict'

/**
* @typedef {import('./visitor').CompileParameters} CompileParameters
*/
/**
* Writes the accompanying jsconfig.json file to the specified paths.

@@ -17,2 +21,3 @@ * Tries to merge nicely if an existing file is found.

* @param logger {import('./logging').Logger} logger
* @private
*/

@@ -19,0 +24,0 @@ const writeJsConfig = (path, logger) => {

@@ -43,3 +43,3 @@ 'use strict'

LargeString: 'string',
LargeBinary: 'string',
LargeBinary: 'Buffer | string',
Integer: 'number',

@@ -56,6 +56,7 @@ UInt8: 'number',

Boolean: 'boolean',
Date: 'Date',
DateTime: 'Date',
Time: 'Date',
Timestamp: 'Date',
// note: the date-related types _can_ be Date in some cases, but let's start with string
Date: 'string', // yyyy-mm-dd
DateTime: 'string', // yyyy-mm-dd + time + TZ (precision: seconds
Time: 'string',
Timestamp: 'string', // yyy-mm-dd + time + TZ (ms precision)
//

@@ -217,9 +218,10 @@ Composition: 'Array',

Composition: [createCompositionOfOne, createCompositionOfMany],
array: [createArrayOf, createArrayOf]
}[element.constructor.name] ?? []
if (toOne && toMany) {
const target = typeof element.target === 'string' ? { type: element.target } : element.target
const target = element.items ?? (typeof element.target === 'string' ? { type: element.target } : element.target)
const { singular, plural } = this.resolveAndRequire(target, file).typeInfo.inflection
typeName =
cardinality > 1 ? toMany(plural) : toOne(this.visitor.isSelfReference(element.target) ? 'this' : singular)
cardinality > 1 ? toMany(plural) : toOne(this.visitor.isSelfReference(target) ? 'this' : singular)
file.addImport(baseDefinitions.path)

@@ -264,4 +266,7 @@ }

if (typeInfo.isArray === true) {
typeName = createArrayOf(typeName)
// add fallback inflection. Mainly needed for array-of with builtin types.
// (array-of relies on inflection being present, which is not the case in builtin)
typeInfo.inflection ??= {
singular: typeName,
plural: typeName
}

@@ -353,4 +358,4 @@

if (element?.items) {
// FIXME: builtin = true? arrays are kinda builtin
result.isArray = true
result.isBuiltin = true
this.resolveType(element.items, file)

@@ -357,0 +362,0 @@ //delete element.items

@@ -127,3 +127,3 @@ 'use strict'

// CLASS ASPECT
buffer.add(`export function ${identAspect(clean)}<TBase extends new (...args: any[]) => any>(Base: TBase) {`)
buffer.add(`export function ${identAspect(clean)}<TBase extends new (...args: any[]) => object>(Base: TBase) {`)
buffer.indent()

@@ -322,3 +322,3 @@ buffer.add(`return class ${clean} extends Base {`)

* They need to be detected on CDS level, as the emitted TS types will try to
* refer to refer to types via their alias that hides the aspectification.
* refer to types via their alias that hides the aspectification.
* If we attempt to directly refer to this alias while it has not been fully created,

@@ -325,0 +325,0 @@ * that will result in a TS error.

{
"name": "@cap-js/cds-typer",
"version": "0.4.0",
"version": "0.5.0",
"description": "Generates .ts files for a CDS model to receive code completion in VS Code",
"main": "index.js",
"repository": "github:cap-js/cds-typer",
"homepage": "https://cap.cloud.sap/",

@@ -20,3 +21,10 @@ "keywords": [

"lint": "eslint",
"cli": "node lib/cli.js"
"cli": "node lib/cli.js",
"doc:clean": "rm -rf ./doc",
"doc:prepare": "npm run doc:clean && mkdir -p doc/types",
"doc:typegen": "./node_modules/.bin/tsc ./lib/*.js --skipLibCheck --declaration --allowJs --emitDeclarationOnly --outDir doc/types && cd doc/types && tsc --init",
"doc:html": "npm run doc:typegen && ./node_modules/.bin/typedoc 'doc/types/**/*.d.ts' --entryPointStrategy expand --out doc/html --tsconfig doc/types/tsconfig.json",
"doc:md": "npm run doc:typegen && ./node_modules/.bin/typedoc --plugin typedoc-plugin-markdown 'doc/types/compile.d.ts' --out doc/md --tsconfig doc/types/tsconfig.json",
"doc:cli": "npm run cli -- --help > ./doc/cli.txt",
"doc:full": "npm run doc:prepare && npm run doc:html && npm run doc:cli"
},

@@ -43,2 +51,4 @@ "files": [

"jest": "^29",
"typedoc": "^0.24.8",
"typedoc-plugin-markdown": "^3.15.3",
"typescript": ">=4.6.4"

@@ -45,0 +55,0 @@ },

# CDS type generator for JavaScript
[![REUSE status](https://api.reuse.software/badge/github.com/cap-js/cds-typer)](https://api.reuse.software/info/github.com/cap-js/cds-typer)
![Unit Tests passing](https://github.com/cap-js/cds-typer/actions/workflows/test.yml/badge.svg)
## About this project

@@ -7,168 +10,4 @@

Exhaustive documentation can be found on [CAPire](https://cap.cloud.sap/docs/tools/cds-typer).
## Requirements and Setup
This project is [available as `@cap-js/cds-typer`](https://www.npmjs.com/package/@cap-js/cds-typer) as NPM package.
### Usage
The type generator can either be used as a standalone tool, or as part of of the [CDS VSCode-Extension](https://www.npmjs.com/package/@sap/vscode-cds).
#### Standalone CLI
Assuming you have the following CDS project structure:
```
/home/
├── mybookshop/
│ ├── db/
│ │ └── schema.cds
│ ├── srv/
│ │ └── service.js
```
a typical workflow to generate types for your CDS project could look something like this:
```sh
npx @cap-js/cds-typer /home/mybookshop/db/schema.cds --outputDirectory /home/mybookshop/@types
```
You would then end up with a directory `@types`, which contains your entities and their accompanying types in a directory structure. The directory structure directly reflects the namespaces you have defined your entities in. They have to be imported in any JavaScript-based service handlers you want to have type support in and can replace calls to `cds.entities(...)`:
```js
// srv/service.js
const { Books } = require('my.bookshop')
```
becomes
```js
// srv/service.js
const { Books } = require('../@types/mybookshop')
```
From that point on you should receive code completion from the type system for `Books`.
_Note:_ the above command generates types for the model contained within the mentioned `schema.cds` file. If you have multiple `.cds` files that are included via `using` statements by `schema.cds`, then those files will also be included in the type generation process. If you have `.cds` files that are _not_ in some way included in `schema.cds`, you have to explicitly pass those as positional argument as well, if you want types for them.
_cds-typer_ comes with rudimentary CLI support and a few command line options:
- `--help`: prints all available parameters.
- `--outputDirectory`: specifies the root directory where all generated files should be put. Defaults to the CWD.
- `--jsConfigPath`: specifies the path to the `jsconfig.json` file to generate. Usually your project's root directory. If specified, a config file is created that restricts the usage of types even further:
```js
// generated .ts file
class Book {
title: string;
}
// some hook in your service
SELECT(Books, b => {
b.title // 👍 no problem, property exists
b.numberOfPages // ❌ property does not exist
})
```
With the generated config in place, the language server will display an error, telling you that `numberOfPages` does not exist in this context. Without the config it would just infer it as `any`.
- `--loglevel`: minimum log level that should be printed. Defaults to `NONE`. Available log levels roughly follow [Microsoft's dotnet log levels](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.loglevel?view=dotnet-plat-ext-6.0):
```
TRACE
DEBUG
INFO
WARNING
ERROR
CRITICAL
NONE
```
The utility expects (at least) one path to a `.cds` file as positional parameter which serves as entry point to the model in question, e.g.:
```sh
npx @cap-js/cds-typer ./path/to/my/model/model.cds --outputDirectory /tmp/
```
Note that you can also pass multiple paths or `"*"` as glob pattern (with quotes to circumvent expansion by the shell). This passes the pattern on to the compiler where the [regular resolve strategy](https://cap.cloud.sap/docs/node.js/cds-compile?q=compiler#cds-resolve) is used.
#### From VSCode
Installing the [CDS VSCode Extension](https://www.npmjs.com/package/@sap/vscode-cds) also adds support for generating types for your model from within VSCode. Adding the appropriate facet to your project via `cds add typer` (and installing the added dependencies thereafter) allows you to simply hit save on any `.cds` file that is part of your model to trigger the generation process.
#### Programmatically
The main API for using _cds-typer_ within another project is contained in [`compile.js`](https://github.tools.sap/cap/cds-typer/blob/master/lib/compile.js), specifically:
- `compileFromFile(…)` to parse a `.cds` file. This involves compiling it to CSN first.
- `compileFromCSN(…)` to directly compile from CSN object. This is useful when you already have your CSN available as part of a tool chain. ⚠️ **WARNING**: the application of `cdstyper` may be impure, meaning that it _could_ alter the provided CSN. If you use the typer this way, you may want to apply it as last step of your tool chain.
### Features
#### Plural Types
While CDS encourages the use of plural form for defined entities, their OOP equivalent classes are usually named in singular. _cds-typer_ automatically transforms entity names to singular and adds the plural form for arrays:
```cds
entity Books : cuid {
}
```
becomes
```ts
class Book {
}
class Books extends Array<Book> {}
```
If you need to customise the singular or plural form, or if your entities are already in singular form, you can do so using annotations:
```cds
@singular: 'Mouse'
entity Mice {}
@plural: 'SomeListList'
entity SomeList {}
```
results in
```ts
class Mouse { … }
class Mice extends Array<Mouse> { … }
class SomeList { … }
class SomeListList extends Array<SomeList> { … }
```
### Relation to _cds2types_
This project is inspired by the existing [_cds2types_](https://github.com/mrbandler/cds2types), but differs in a few aspects:
#### Reworked Imports
Instead of one monolithic `.d.ts` file containing all entities in nested namespaces, multiple files are generated where each namespace is represented by a directory structure. This facilicates simpler imports in a more Java-esque style:
```js
const types = require('./cds2types/compiled.d.ts')
console.log(types.sap.cap.bookshop.Books) // a class
```
becomes
```js
const { Books } = require('./cds-typer/sap/cap/bookshop')
console.log(Books) // the same class
```
#### Usable in Javascript Projects
Generated code is usable from within plain Javascript projects. The code generated by _cds2types_ would represent each cds-entity as an interface, which are not visible to Javascript projects. _cds-typer_ uses classes instead.
#### Faster
_cds2types_ takes a detour to create a Typescript AST first and then print out the formatted source files. _cds-typer_ directly walks the linked CSN and creates strings on the fly. Also, file operations are `async`. These two changes speed up _cds-typer_ by around one to two orders of magnitude compared to _cds2types_.
#### Small Footprint
_cds-typer_ tries to keep its dependency footprint as small as possible. Libraries like `typescript` are only needed as dev dependencies.
## Support, Feedback, Contributing

@@ -180,6 +19,6 @@

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](CODE_OF_CONDUCT.md) at all times.
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its [Code of Conduct](https://github.com/cap-js/.github/blob/main/CODE_OF_CONDUCT.md) at all times.
## Licensing
Copyright 2022-2022 SAP SE or an SAP affiliate company and cds-dts-generator contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/cds-dts-generator).
Copyright 2022-2022 SAP SE or an SAP affiliate company and cds-typer contributors. Please see our [LICENSE](LICENSE) for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available [via the REUSE tool](https://api.reuse.software/info/github.com/SAP/cds-dts-generator).
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc