diff --git a/.circleci/config.yml b/.circleci/config.yml index ddfd9d42..4383e827 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,13 +11,19 @@ jobs: - run: name: Configure NPM repository access command: sed -i -e "s|\${GITHUB_PERSONAL_ACCESS_TOKEN}|$GITHUB_PERSONAL_ACCESS_TOKEN|g" npmrc-env && mv npmrc-env .npmrc + - restore_cache: - key: v1-dep-{{ .Branch }}-{{ checksum "package.json" }} + key: v1-dep-npm-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }} - run: - name: Run npm ci - command: npm ci + name: Install node dependencies + command: | + if [[ ! -d node_modules ]]; then + npm ci --loglevel warn --yes + else + echo "package.json and package-lock.json unchanged. Using cache." + fi - save_cache: - key: v1-dep-{{ .Branch }}-{{ checksum "package.json" }} + key: v1-dep-npm-{{ checksum "package.json" }}-{{ checksum "package-lock.json" }} paths: - node_modules diff --git a/package-lock.json b/package-lock.json index 5baccdce..acb88d79 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@etops/ottoman", - "version": "1.0.8", + "version": "1.0.9", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -1046,8 +1046,8 @@ "optional": true }, "ink-docstrap": { - "version": "git+https://github.com/brett19/docstrap.git#9c9b2ab545259179e0d7216ae8d641fc64640d75", - "from": "git+https://github.com/brett19/docstrap.git#master", + "version": "git+ssh://git@github.com/brett19/docstrap.git#9c9b2ab545259179e0d7216ae8d641fc64640d75", + "from": "ink-docstrap@git+https://github.com/brett19/docstrap.git#master", "dev": true, "requires": { "moment": "~2.6.0" @@ -2267,6 +2267,12 @@ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "typescript": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz", + "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==", + "dev": true + }, "uglify-js": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.10.0.tgz", diff --git a/package.json b/package.json index 50ad816c..e2e78230 100644 --- a/package.json +++ b/package.json @@ -7,12 +7,14 @@ "json", "document" ], + "types": "./types/index.d.ts", "main": "./lib/ottoman", "license": "Apache2", "name": "@etops/ottoman", "scripts": { "test": "istanbul cover ./node_modules/mocha/bin/_mocha -- test/*.test.js", - "lint": "eslint ./lib" + "lint": "eslint ./lib", + "regen-types": "tsc" }, "publishConfig": { "registry": "https://npm.pkg.github.com" @@ -32,11 +34,12 @@ "ink-docstrap": "git+https://github.com/brett19/docstrap.git#master", "istanbul": "~0.4.5", "jsdoc": "~3.3.0-alpha9", - "mocha": "~5.2.0" + "mocha": "~5.2.0", + "typescript": "4.0.2" }, "repository": { "type": "git", "url": "http://github.com/etops/node-ottoman.git" }, - "version": "1.0.8" + "version": "1.0.9" } diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..210ede38 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "include": [ + "./lib" + ], + "compilerOptions": { + "target": "es6", + "module": "commonjs", + "allowJs": true, + "declaration": true, + "emitDeclarationOnly": true, + "outDir": "types" + } +} diff --git a/types/autofns.d.ts b/types/autofns.d.ts new file mode 100644 index 00000000..f7a7d806 --- /dev/null +++ b/types/autofns.d.ts @@ -0,0 +1,2 @@ +declare function autogenUuid(): any; +export { autogenUuid as uuid }; diff --git a/types/cbstoreadapter.d.ts b/types/cbstoreadapter.d.ts new file mode 100644 index 00000000..4aa116c1 --- /dev/null +++ b/types/cbstoreadapter.d.ts @@ -0,0 +1,45 @@ +export = CbStoreAdapter; +/** + * The Couchbase store adapter implements an Ottoman StoreAdapter suitable + * for using Ottoman with Couchbase Server. + * @param bucket + * @constructor + */ +declare function CbStoreAdapter(bucket: any, cb: any): void; +declare class CbStoreAdapter { + /** + * The Couchbase store adapter implements an Ottoman StoreAdapter suitable + * for using Ottoman with Couchbase Server. + * @param bucket + * @constructor + */ + constructor(bucket: any, cb: any); + couchbase: any; + bucket: any; + ddocs: {}; + gsis: {}; + debug: boolean; + isNotFoundError(err: any): boolean; + get(key: string, callback: any): void; + store(key: string, data: any, cas: any, callback: any): void; + remove(key: any, cas: any, callback: any): void; + private _createViewIndex; + private _createN1qlIndex; + createIndex(type: string, modelName: string, name: string, fields: string[], callback: any): void; + private _ensureMrIndices; + private _ensureGsiIndices; + ensureIndices(callback: any): void; + private _searchViewIndex; + private _searchN1qlIndex; + searchIndex(type: string, modelName: string, name: string, options: any, callback: any): void; + count(type: string, modelName: string, options: { + filter: any; + }, callback: any): void; + find(type: string, modelName: string, options: { + filter: any; + limit: number; + skip: number; + sort: string | string[]; + namespace: string; + }, callback: any): void; +} diff --git a/types/index.d.ts b/types/index.d.ts new file mode 100644 index 00000000..7d01fd43 --- /dev/null +++ b/types/index.d.ts @@ -0,0 +1,7 @@ +import ottoman from "./ottoman"; + +// based on https://www.typescriptlang.org/docs/handbook/declaration-files/dts-from-js.html +// to get a head start with the typing and not to deviate from original ottoman v1 +declare module "@etops/ottoman" { + export default ottoman; +} diff --git a/types/mockstoreadapter.d.ts b/types/mockstoreadapter.d.ts new file mode 100644 index 00000000..cb767c5f --- /dev/null +++ b/types/mockstoreadapter.d.ts @@ -0,0 +1,17 @@ +export = MockStoreAdapter; +declare function MockStoreAdapter(): void; +declare class MockStoreAdapter { + data: {}; + indexes: {}; + debug: boolean; + clear(): void; + isNotFoundError(err: any): boolean; + get(key: any, callback: any): void; + store(key: any, data: any, cas: any, callback: any): void; + remove(key: any, cas: any, callback: any): void; + createIndex(type: any, modelName: any, name: any, fields: any, callback: any): void; + ensureIndices(callback: any): void; + searchIndex(type: any, modelName: any, name: any, options: any, callback: any): void; + count(type: any, modelName: any, options: any, callback: any): void; + find(type: any, modelName: any, options: any, callback: any): void; +} diff --git a/types/modelinstance.d.ts b/types/modelinstance.d.ts new file mode 100644 index 00000000..7642a951 --- /dev/null +++ b/types/modelinstance.d.ts @@ -0,0 +1,44 @@ +export = ModelInstance; +/** + * Constructs a new model instance and for models with a default constructor, + * applies the data in object passed to the instance. + * + * @param {Object} data + * @constructor + */ +declare function ModelInstance(...args: any[]): void; +declare class ModelInstance { + /** + * Constructs a new model instance and for models with a default constructor, + * applies the data in object passed to the instance. + * + * @param {Object} data + * @constructor + */ + constructor(...args: any[]); + $: {}; + loaded(): boolean; + id(): string; + private _toCoo; + toCoo(): any; + toJSON(): any; + private inspect; + save(callback: Function): void; + load(...args: any[]): void; + remove(callback: Function): void; +} +declare namespace ModelInstance { + function fromData(data: any): ModelInstance; + function applyData(mdlInst: ModelInstance, data: any): void; + function create(data: any, callback: Function, ...args: any[]): void; + function namePath(typeOnly: any): string; + function loadAll(items: ModelInstance[], callback: Function): void; + function find(filter: any, options?: any, callback: Function): void; + function count(filter: any, options?: any, callback: Function): void; + function getById(id: string, options: any, callback: Function): void; + function refByKey(key: string): ModelInstance; + function plugin(pluginFn: any, options: any): ModelInstance; + function ref(id: string): ModelInstance; + function pre(event: "load" | "validate" | "save" | "remove", handler: Function): any; + function post(event: "load" | "validate" | "save" | "remove", fn: Function): any; +} diff --git a/types/ottoman.d.ts b/types/ottoman.d.ts new file mode 100644 index 00000000..af440662 --- /dev/null +++ b/types/ottoman.d.ts @@ -0,0 +1,71 @@ +export = ottoman; +declare var ottoman: Ottoman; +/** + * The core manager class for the ODM. + * + * @constructor + */ +declare function Ottoman(options: any): void; +declare class Ottoman { + /** + * The core manager class for the ODM. + * + * @constructor + */ + constructor(options: any); + namespace: any; + store: any; + models: any; + types: any; + delayedBind: {}; + plugins: any[]; + bucket: any; + plugin(pluginFn: any, options: any): Ottoman; + nsPrefix(): string; + isTypeDef(type: any): boolean; + isModel(model: any): boolean; + typeByName(type: string): import("./modelinstance") | TypeDef | any; + typeByNameAndNamespace(type: string, namespace: string): import("./modelinstance") | TypeDef | any; + private _parseFieldType; + private _makeField; + private _createSchema; + private _findModelsByRefDocIndex; + private _findModelsByDefIndex; + private _findModelByIndex; + private _countModels; + private _normFilter; + private _findModels; + private _findModelsByQuery; + private _buildModel; + private _delayBind; + private _buildAndRegisterModel; + _applyPlugins(model: any): Ottoman; + private _buildAndRegisterTypeDef; + type(name: string, options: any): TypeDef; + model(name: string, schemaDef: any, options: { + index: any; + queries: any; + id: string; + store: import("./storeadapter"); + }): any; + validate(mdlInst: import("./modelinstance"), callback: any): void; + _ensureModelIndices(model: any, callback: any): void; + ensureIndices(callback: Function): void; + getModel(name: string, prefixed: boolean): any; + fromCoo(data: any, type: string): import("./modelinstance"); + toCoo(obj: import("./modelinstance")): any; +} +declare namespace Ottoman { + const loadAll: (items: import("./modelinstance")[], callback: Function) => void; +} +/** + * The data definition for a typedef object. Typedef's are + * simply aliases for other types. + * + * @constructor + * @private + * @ignore + */ +declare function TypeDef(): void; +declare class TypeDef { +} diff --git a/types/ottopath.d.ts b/types/ottopath.d.ts new file mode 100644 index 00000000..7963c90d --- /dev/null +++ b/types/ottopath.d.ts @@ -0,0 +1,4 @@ +export function parse(pathStr: any): any; +export function query(pathObj: any, value: any): void; +export function stringifyExpression(exprObj: any): any; +export function stringify(pathObj: any): string; diff --git a/types/schema.d.ts b/types/schema.d.ts new file mode 100644 index 00000000..f4c7bbe5 --- /dev/null +++ b/types/schema.d.ts @@ -0,0 +1,141 @@ +export = Schema; +declare function Schema(context: any): void; +declare class Schema { + constructor(context: any); + context: any; + name: string; + fields: any[]; + idField: string; + indices: any[]; + indexFns: any[]; + queryFns: any[]; + preHandlers: {}; + postHandlers: {}; + namePath(typeOnly: any): string; + _validate(mdlInst: any): void; + validate(mdlInst: any, callback: any): void; + indexName(fields: any): string; + refKeyPrefix(fields: any): string; + refKey(fields: any, values: any): string; + refKeys(mdl: any): string[]; + addIndex(index: any): void; + addDefIndexFn(name: any, indexDef: any): void; + addRefDocIndexFn(name: any, indexDef: any): void; + addIndexFn(name: any, indexDef: any): void; + _tryAddDefQueryFn(name: any, queryDef: any): void; + addQueryFn(name: any, queryDef: any): void; + addField(field: any): void; + setIdField(path: any): void; + fieldVal(mdl: any, name: any): any; + field(name: any): any; + fieldType(path: any): Schema; + applyDataToObject(obj: any, data: any): void; + applyUserDataToObject(obj: any, data: any): void; + applyDefaultsToObject(obj: any): void; + applyPropsToObj(obj: any): void; + execPreHandlers(event: any, mdlInst: any, callback: any): void; + execPostHandlers(event: any, mdlInst: any, callback: any): void; + addPreHandler(event: any, callback: any): void; + addPostHandler(event: any, fn: any): void; +} +declare namespace Schema { + export function coreTypeByName(type: any): any; + export function isCoreType(type: any): boolean; + export { stringCoreType as StringType }; + export { numberCoreType as NumberType }; + export { integerCoreType as IntegerType }; + export { boolCoreType as BooleanType }; + export { dateCoreType as DateType }; + export { mixedCoreType as MixedType }; + export { SchemaField as Field }; + export { ModelRef }; + export { ListField }; + export { FieldGroup }; + export { SchemaIndex as Index }; + export { ViewQueryFn }; + export { RefDocIndexFn }; + export { RefDocIndex }; + /** + * A validator function validates a Schema field to ensure it + * matches the expected traits. + */ + export type Validator = Function; +} +declare var stringCoreType: CoreType; +declare var numberCoreType: CoreType; +declare var integerCoreType: CoreType; +declare var boolCoreType: CoreType; +declare var dateCoreType: CoreType; +declare var mixedCoreType: CoreType; +declare function SchemaField(): void; +declare class SchemaField { + name: string; + type: any; + readonly: boolean; + default: any; + validator: any; +} +declare function ModelRef(name: any): void; +declare class ModelRef { + constructor(name: any); + name: any; + inspect(): string; +} +declare function ListField(type: any): void; +declare class ListField { + constructor(type: any); + type: any; + inspect(): string; +} +declare function FieldGroup(): void; +declare class FieldGroup { + fields: any[]; + create(): {}; +} +declare function SchemaIndex(): void; +declare class SchemaIndex { + type: any; + schema: any; + fields: any[]; +} +declare function ViewQueryFn(): void; +declare class ViewQueryFn { + type: any; + name: any; + of: string; + field: any; + consistency: number; +} +declare function RefDocIndexFn(): void; +declare class RefDocIndexFn { + type: string; + consistency: number; +} +declare function RefDocIndex(): void; +declare class RefDocIndex { + type: string; +} +/** + * A validator function validates a Schema field to ensure it + * matches the expected traits. + * + * @typedef {function} Schema.Validator + * + * @param {*} value + * The value of the property being validated. + */ +declare function CoreType(type: any): void; +declare class CoreType { + /** + * A validator function validates a Schema field to ensure it + * matches the expected traits. + * + * @typedef {function} Schema.Validator + * + * @param {*} value + * The value of the property being validated. + */ + constructor(type: any); + type: any; + inspect(): string; +} diff --git a/types/storeadapter.d.ts b/types/storeadapter.d.ts new file mode 100644 index 00000000..ef6a56b9 --- /dev/null +++ b/types/storeadapter.d.ts @@ -0,0 +1,22 @@ +export = StoreAdapter; +/** + * A store adapter is the low-level provider of database functionality for + * Ottoman's internal storage system. + * + * @constructor + */ +declare function StoreAdapter(): void; +declare class StoreAdapter { +} +declare namespace StoreAdapter { + export { SearchConsistency, StoreAdapter }; +} +declare namespace SearchConsistency { + const NONE: number; + const LOCAL: number; + const GLOBAL: number; +} +/** + * ~GetCallback + */ +type StoreAdapter = (err: Error, value: any, cas: any) => any;