Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
# compiled output
api-docs
index.*.js*
array.*.js*
string.*.js*
index.*.*js*
array.*.*js*
string.*.*js*
types
*.tgz

# in case gh-pages manually managed
index.html
modules.html
interfaces/
classes/
assets/
functions/
.nojekyll

# testing
Expand Down
24 changes: 20 additions & 4 deletions docs/helpers/collection.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,19 @@ collection.random(2); // collection of 2 random elements
collection.random(collection.length); // return the whole collection
```

#### shuffle

The shuffle method returns the collection with the items in a randomised order.

```js
import { Collection } from '@upfrontjs/framework';

const numCollection = new Collection([1, 2, 3, 4, 5]);

numCollection.shuffle(); // Collection[3, 1, 4, 2, 5]
numCollection.shuffle(); // Collection[2, 5, 1, 4, 3]
```

#### isEmpty

The `isEmpty` method determines whether the collection is empty or not.
Expand Down Expand Up @@ -362,17 +375,20 @@ collection.skipWhile(item => item <= 2); // Collection[3, 4, 5]

#### pluck

When all items in the collections are objects then you may use to The `pluck` method to get certain attributes in a collection or multiple attributes in a collection of objects
When all items in the collections are objects then you may use to The `pluck` method to get certain attributes in a collection or multiple attributes in a collection of objects. Similarly to [dataGet](./readme.md#dataget) You may also use dot notation.
```js
import { Collection } from '@upfrontjs/framework';

const collection = new Collection(
{ id: 1, name: 'name1', email: 'test1@email.com' },
{ id: 2, name: 'name2', email: 'test2@email.com' },
{ id: 3, name: 'name3', email: 'test3@email.com' },
{ id: 1, name: 'name1', email: 'test1@email.com', property: { key: 'value1' } },
{ id: 2, name: 'name2', email: 'test2@email.com', property: { key: 'value2' } },
{ id: 3, name: 'name3', email: 'test3@email.com', property: { key: 'value3' } },
);
collection.pluck('name'); // Collection['name1', 'name2', 'name3']
collection.pluck(['id', 'name']); // Collection[{ id: 1, name: 'name1' }, { id: 2, name: 'name2' }, { id: 3, name: 'name3' }]

collection.pluck('property.key'); // Collection['value1', 'value2', 'value3']
collection.pluck(['property.key', 'id']); // Collection[{ id: 1, 'property.key': 'value1' }, { id: 2, 'property.key': 'value2' }, { id: 3, 'property.key': 'value3' }]
```

#### tap
Expand Down
223 changes: 125 additions & 98 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@upfrontjs/framework",
"version": "0.13.0",
"version": "0.14.0",
"description": "Data handling framework complementary to backend model systems.",
"main": "index.min.js",
"module": "index.es.min.js",
Expand Down Expand Up @@ -68,8 +68,9 @@
"test": "jest",
"test:coverage": "npm run test -- --coverage",
"lint": "eslint . --cache --fix --ext .ts",
"build": "rollup -c && tsc --emitDeclarationOnly",
"docs:api": "[ ! -d './types' ] && tsc --emitDeclarationOnly || echo './types folder exists' && npx typedoc",
"emit-declarations": "tsc --declaration --declarationMap --declarationDir ./types --emitDeclarationOnly",
"build": "rollup -c && npm run emit-declarations",
"docs:api": "[ ! -d './types' ] && npm run emit-declarations || echo './types folder exists' && npx typedoc",
"prepare": "husky install",
"commit": "commit"
},
Expand Down
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const commonConfig = {
plugins: [
// it doesn't find the config by default and doesn't emit interface files
// todo - https://github.com/rollup/plugins/pull/791/files#diff-77ceb76f06466d761730b952567396e6b5c292cc4044441cdfdf048b4614881dR83 check those tests
typescript({ tsconfig: './tsconfig.json', incremental: false }),
typescript({ tsconfig: './tsconfig.json' }),
terser({
format: {
comments: (node, comment) => {
Expand Down
7 changes: 5 additions & 2 deletions src/Calliope/Concerns/CallsApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import type Model from '../Model';
import type { QueryParams } from './BuildsQuery';
import BuildsQuery from './BuildsQuery';
import type { Attributes, SimpleAttributes } from './HasAttributes';
import { isObjectLiteral, transformKeys } from '../../Support/function';
import { finish, kebab, plural } from '../../Support/string';
import isObjectLiteral from '../../Support/function/isObjectLiteral';
import transformKeys from '../../Support/function/transformKeys';
import finish from '../../Support/string/finish';
import kebab from '../../Support/string/kebab';
import plural from '../../Support/string/plural';
import type { MaybeArray, StaticToThis } from '../../Support/type';

/**
Expand Down
3 changes: 2 additions & 1 deletion src/Calliope/Concerns/CastsAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import type AttributeCaster from '../../Contracts/AttributeCaster';
import GlobalConfig from '../../Support/GlobalConfig';
import type { Attributes, AttributeKeys } from './HasAttributes';
import InvalidArgumentException from '../../Exceptions/InvalidArgumentException';
import { isUserLandClass, isObjectLiteral } from '../../Support/function';
import isObjectLiteral from '../../Support/function/isObjectLiteral';
import isUserLandClass from '../../Support/function/isUserLandClass';
import type Model from '../Model';

type BuiltInCastType = 'boolean' | 'collection' | 'datetime' | 'number' | 'string';
Expand Down
7 changes: 5 additions & 2 deletions src/Calliope/Concerns/HasAttributes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ import GuardsAttributes from './GuardsAttributes';
import type HasRelations from './HasRelations';
import type Model from '../Model';
import type ModelCollection from '../ModelCollection';
import { isObjectLiteral, transformKeys } from '../../Support/function';
import isObjectLiteral from '../../Support/function/isObjectLiteral';
import transformKeys from '../../Support/function/transformKeys';
import Collection from '../../Support/Collection';
import { camel, pascal, snake } from '../../Support/string';
import camel from '../../Support/string/camel';
import pascal from '../../Support/string/pascal';
import snake from '../../Support/string/snake';
import type { KeysNotMatching, MaybeArray } from '../../Support/type';

// eslint-disable-next-line max-len
Expand Down
5 changes: 4 additions & 1 deletion src/Calliope/Concerns/HasRelations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import InvalidOffsetException from '../../Exceptions/InvalidOffsetException';
import type { Attributes } from './HasAttributes';
import Collection from '../../Support/Collection';
import InvalidArgumentException from '../../Exceptions/InvalidArgumentException';
import { finish, plural, snake, start } from '../../Support/string';
import finish from '../../Support/string/finish';
import plural from '../../Support/string/plural';
import snake from '../../Support/string/snake';
import start from '../../Support/string/start';
import { cloneDeep } from 'lodash';
import type { MaybeArray } from '../../Support/type';

Expand Down
2 changes: 1 addition & 1 deletion src/Calliope/Concerns/HasTimestamps.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import HasRelations from './HasRelations';
import type Model from '../Model';
import InvalidArgumentException from '../../Exceptions/InvalidArgumentException';
import { finish } from '../../Support/string';
import finish from '../../Support/string/finish';
import LogicException from '../../Exceptions/LogicException';

export default class HasTimestamps extends HasRelations {
Expand Down
2 changes: 1 addition & 1 deletion src/Calliope/Concerns/SoftDeletes.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import HasTimestamps from './HasTimestamps';
import type Model from '../Model';
import LogicException from '../../Exceptions/LogicException';
import { finish } from '../../Support/string';
import finish from '../../Support/string/finish';
import type { SimpleAttributes } from './HasAttributes';

export default class SoftDeletes extends HasTimestamps {
Expand Down
5 changes: 3 additions & 2 deletions src/Calliope/Factory/FactoryBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ import InvalidOffsetException from '../../Exceptions/InvalidOffsetException';
import GlobalConfig from '../../Support/GlobalConfig';
import Collection from '../../Support/Collection';
import InvalidArgumentException from '../../Exceptions/InvalidArgumentException';
import { isUserLandClass } from '../../Support/function';
import { plural, singular } from '../../Support/string';
import isUserLandClass from '../../Support/function/isUserLandClass';
import plural from '../../Support/string/plural';
import singular from '../../Support/string/singular';
import type Configuration from '../../Contracts/Configuration';
import type { MaybeArray } from '../../Support/type';

Expand Down
4 changes: 2 additions & 2 deletions src/Calliope/Model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import FactoryBuilder from './Factory/FactoryBuilder';
import type HasFactory from '../Contracts/HasFactory';
import type { Attributes, AttributeKeys, SimpleAttributes } from './Concerns/HasAttributes';
import ModelCollection from './ModelCollection';
import { finish } from '../Support/string';
import finish from '../Support/string/finish';
import type { MaybeArray, StaticToThis } from '../Support/type';
import { cloneDeep } from 'lodash';
import { isObjectLiteral } from '../Support/function';
import isObjectLiteral from '../Support/function/isObjectLiteral';

export default class Model extends SoftDeletes implements HasFactory {
/**
Expand Down
4 changes: 2 additions & 2 deletions src/Services/API.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type ApiCaller from '../Contracts/ApiCaller';
import qs from 'qs';
import { isObjectLiteral } from '../Support/function';
import isObjectLiteral from '../Support/function/isObjectLiteral';
import GlobalConfig from '../Support/GlobalConfig';
import { finish } from '../Support/string';
import finish from '../Support/string/finish';
import InvalidArgumentException from '../Exceptions/InvalidArgumentException';
import type { Method, CustomHeaders } from '../Calliope/Concerns/CallsApi';
import type { ApiResponse } from '../Contracts/HandlesApiResponse';
Expand Down
22 changes: 19 additions & 3 deletions src/Support/Collection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { isEqual, orderBy, uniq } from 'lodash';
import type Arrayable from '../Contracts/Arrayable';
import type Jsonable from '../Contracts/Jsonable';
import LogicException from '../Exceptions/LogicException';
import { isObjectLiteral } from './function';
import dataGet from './function/dataGet';
import isObjectLiteral from './function/isObjectLiteral';
import type { MaybeArray } from './type';
import InvalidOffsetException from '../Exceptions/InvalidOffsetException';

Expand Down Expand Up @@ -168,6 +169,21 @@ export default class Collection<T> implements Jsonable, Arrayable<T>, Iterable<T
return this[randomIndex];
}

/**
* Randomise the order of elements in the collection using the
* {@link https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle#The_modern_algorithm|Durstenfeld algorithm}.
*/
public shuffle(): this {
const items = this.toArray();

for (let i = items.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[items[i], items[j]] = [items[j]!, items[i]!];
}

return this._newInstance(items);
}

/**
* Assert whether the collection
* is empty or not.
Expand Down Expand Up @@ -706,13 +722,13 @@ export default class Collection<T> implements Jsonable, Arrayable<T>, Iterable<T
return this.map((item: Record<string, unknown>) => {
const obj: Record<string, unknown> = {};

properties.forEach(property => obj[property] = item[property]);
properties.forEach(property => obj[property] = dataGet(item, property));

return obj;
});
}

return this.map((item: Record<string, unknown>) => item[properties]);
return this.map((item: Record<string, unknown>) => dataGet(item, properties));
}

/**
Expand Down
1 change: 1 addition & 0 deletions src/Support/array/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as wrap } from './wrap';
40 changes: 20 additions & 20 deletions src/Support/array.ts β†’ src/Support/array/wrap.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import type { MaybeArray } from './type';
/**
* Ensure the given value is an array.
*
* @param {any} value
*
* @return {array};
*/
export function wrap<T>(value?: MaybeArray<T>): T[] {
if (!arguments.length) {
return [];
}
if (!Array.isArray(value)) {
value = [value] as T[];
}
return value;
}
import type { MaybeArray } from '../type';

/**
* Ensure the given value is an array.
*
* @param {any} value
*
* @return {array};
*/
export default function wrap<T>(value?: MaybeArray<T>): T[] {
if (!arguments.length) {
return [];
}

if (!Array.isArray(value)) {
value = [value] as T[];
}

return value;
}
Loading