@cocreate/utils

中文文档
2.0.3发布于 2026/11/07AGPL-3.0ES Module近 30 天下载 6378

A simple utils component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.

原始使用文档
文档目录20 节
  1. Docs & Demo
  2. CDN
  3. NPM
  4. yarn
  5. Module Usage
  6. ESM (tree-shaking)
  7. ESM subpath imports
  8. CommonJS (Node)
  9. Rendering values in strings
  10. Querying and Sorting
  11. Querying
  12. Multi-field sorting
  13. Storage-native sorting
  14. Pagination
  15. Build
  16. Leading $this selector
  17. Resolve property names
  18. Assign nested AST results
  19. Browser globals in AST
  20. Synchronous and asynchronous callbacks

CoCreate-utils

A simple utils component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API. Take it for a spin in our playground!

minified gzip brotli GitHub latest release License Hiring

CoCreate-utils

Docs & Demo

For a complete guide and working demo refer to the doumentation

CDN

<script src="https://cdn.CoCreateJS.com/utils/latest/CoCreate-utils.min.js"></script>
<script src="https://cdn.CoCreateJS.com/utils/latest/CoCreate-utils.min.css"></script>

NPM

$ npm i @cocreate/utils

yarn

$ yarn install @cocreate/utils

Module Usage

ESM (tree-shaking)

import { uid, ObjectId } from "@cocreate/utils";

ESM subpath imports

import { getValueFromObject } from "@cocreate/utils/getValueFromObject";
import { queryElements } from "@cocreate/utils/queryElements";

CommonJS (Node)

const { uid, ObjectId } = require("@cocreate/utils");
const { getValueFromObject } = require("@cocreate/utils/getValueFromObject");

Rendering values in strings

renderValue resolves CoCreate double-curly values and AST expressions. It can run without a DOM node when the expression reads from the supplied data. It resolves nested values from the innermost placeholder outward, while callers with their own nested scopes can pass a custom resolveValue callback.

import { renderValue } from "@cocreate/utils";

const html = await renderValue(
    undefined,
    {
        data: { ready: "<ready>" },
        object: { status: "ready" },
        module: { name: "utils" }
    },
    "<p>{{data.{{object.status}}}} {{$data.module.name}}</p>",
    undefined,
    undefined,
    undefined,
    undefined,
    { escapeOutput: true }
);

The optional escapeOutput option escapes resolved values for HTML string output. DOM renderers can omit it because the DOM handles text and attribute escaping when values are assigned.

Querying and Sorting

CoCreate exposes one data-object API across MongoDB, IndexedDB, MySQL, and other storage providers. MongoDB query and sort behavior is the canonical contract. A storage wrapper may use its native query engine or indexes as an optimization, but it must return the same logical result.

The shared helpers are available from @cocreate/utils:

import { queryData, searchData, sortData } from "@cocreate/utils";

Querying

queryData(object, query) evaluates a MongoDB-style query against one object. Keys may use dot notation to address nested values.

const matches = queryData(
    {
        status: "active",
        profile: { score: 82 },
        tags: ["customer", "priority"]
    },
    {
        status: "active",
        "profile.score": { $gte: 80 },
        tags: { $in: ["priority"] }
    }
);

Queries can combine conditions using $and, $or, and $nor. Supported field operators include equality and inequality comparisons, membership, array matching, existence, regular expressions, type checks, and modulus checks. Storage wrappers should translate these conditions to their native query language when equivalent behavior is available and use the shared helper as the compatibility fallback.

searchData(object, search) performs text-oriented matching across an object. It is separate from structured queryData filtering and can be applied after a record satisfies the structured query.

Multi-field sorting

sortData(data, sort) applies sort fields in their declared order:

const sorted = sortData(records, [
    { key: "status", direction: "asc" },
    { key: "updated.on", direction: "desc" },
    { key: "_id", direction: "desc" }
]);

The first field is the primary sort. The second field is compared only when the primary values are equal, and each later field breaks ties left by all preceding fields. A missing secondary or tertiary value does not exclude the record.

Sorting follows MongoDB conventions:

  • Keys support dot notation, including nested values such as updated.on.
  • A missing field is treated as null for comparison.
  • Null and missing values sort before ordinary values in ascending order and after them in descending order.
  • Values of different types follow MongoDB's BSON comparison order.
  • Array and object comparisons should follow MongoDB behavior where the corresponding JavaScript representation permits it.
  • Equivalent sort keys do not imply a stable order. Include _id as the final field when deterministic pagination or rendering is required.

Storage-native sorting

Storage wrappers should prefer native sorting when it produces the canonical result:

  • MongoDB can use its native sort directly.
  • IndexedDB can use one cursor over a compound index when every indexed field is present and all fields use the same direction.
  • SQL wrappers can translate the sort to ORDER BY while explicitly matching MongoDB's null ordering.
  • Mixed directions, optional IndexedDB index fields, or incompatible native type ordering must use the shared comparator as a fallback.

IndexedDB compound indexes omit records that do not contain every indexed field. Therefore, an optional secondary or tertiary field must not be placed in the only cursor used to collect results unless the wrapper also collects the omitted records. Falling back to sortData preserves the unified behavior.

Pagination

Filtering and the complete canonical ordering must be established before index and limit are applied. Paginating an incompletely sorted result set can return different records across storage providers.

For cursor pagination, include _id as the final sort key and build the next range from all sort-key values plus _id. This provides a deterministic boundary when multiple records share the same preceding values.

Build

# Build UMD + ESM + CJS
npm run build

# Build only module outputs
npm run build:modules

# Build only UMD bundle
npm run build:umd

Table of Contents

Announcements

All updates to this library are documented in our CHANGELOG and releases. You may also subscribe to email for releases and breaking changes.

Roadmap

If you are interested in the future direction of this project, please take a look at our open issues and pull requests. We would love to hear your feedback.

About

CoCreate-utils is guided and supported by the CoCreate Developer Experience Team.

Please Email the Developer Experience Team here in case of any queries.

CoCreate-utils is maintained and funded by CoCreate. The names and logos for CoCreate are trademarks of CoCreate, LLC.

How to Contribute

We encourage contribution to our libraries (you might even score some nifty swag), please see our CONTRIBUTING guide for details.

We want this library to be community-driven, and CoCreate led. We need your help to realize this goal. To help make sure we are building the right things in the right order, we ask that you create issues and pull requests or merely upvote or comment on existing issues or pull requests.

We appreciate your continued support, thank you!

License

This software is dual-licensed under the GNU Affero General Public License version 3 (AGPLv3) and a commercial license.

  • Open Source Use: For open-source projects and non-commercial use, this software is available under the AGPLv3. The AGPLv3 allows you to freely use, modify, and distribute this software, provided that all modifications and derivative works are also licensed under the AGPLv3. For the full license text, see the LICENSE file.

  • Commercial Use: For-profit companies and individuals intending to use this software for commercial purposes must obtain a commercial license. The commercial license is available when you sign up for an API key on our website. This license permits proprietary use and modification of the software without the copyleft requirements of the AGPLv3. It is ideal for integrating this software into proprietary commercial products and applications.

If you have not purchased a commercial license and intend to use this software for commercial purposes, you are required to sign up for an API key on our website.

Leading $this selector

Start a query branch with $this to return the current element, or attach a CSS selector to test that element with matches() before continuing:

click-query="$this:checked $closest .api-type-filter input:checked[]"
click-query="$this.active[aria-pressed='true'] $parent .target"

$this#id, $this.class, $this[attribute], and pseudo-classes all match the current element, rather than descendants. A failed match stops only that comma-separated branch. Bare $this returns the current element without a test. Whitespace after the attached selector starts the remaining query; whitespace inside quoted attributes or parentheses remains part of the test. $this is supported only at the beginning of a branch. Existing traversal operators and descendant selectors continue normally after it.

Resolve property names

import { resolveProperty } from "@cocreate/utils";

const key = resolveProperty(element, "textcontent"); // "textContent"
if (key !== undefined) element[key] = "Updated";

resolveProperty(object, name) returns the original string key matching a name without case sensitivity, or undefined when no match exists. It searches own and inherited properties, including non-enumerable properties, without reading getters. Distinct keys must be unique ignoring case: myMethod and mymethod on the same object or its prototype chain cause a TypeError, even if one is an exact match. Overrides using the same spelling are allowed. The caller chooses whether to read, assign, or invoke the resolved member.

Assign nested AST results

A dotted operator key identifies a property on an existing scoped object. When that member is not a function, AST evaluates the nested value, assigns the result to the property, and returns that result:

await astAsync({
    node: element,
    sandbox: { $this: element, $ExamplePlugin: ExamplePlugin },
    executeAST: {
        "$this.myInstance": { "$ExamplePlugin": ["$this", {}] }
    }
});

This works in both astSync and astAsync, including multiple sibling keys, nested paths, numeric array indices, and items[] appends. AST resolves the root from its sandbox or registry and delegates writes to dotNotationToObject. The root object must exist; missing parent objects are created by the shared helper. Its conventions apply: undefined deletes a property, and assigning undefined to an indexed array entry splices that entry out. Existing callable members retain method invocation semantics. A string such as "$this.myInstance" still reads a value; ordinary keys still store values in the AST result and scope. Returned results are not automatically assigned to the host element by the plugin loader.

Browser globals in AST

In browser evaluations, $window reads the browser window and $CoCreate reads its current window.CoCreate namespace. Both support dotted property reads, assignment keys, and method calls in astSync and astAsync:

astSync({ executeAST: "$window.location.origin" });
astSync({ executeAST: "$CoCreate" });
await astAsync({ executeAST: { "$window.exampleSettings": { enabled: true } } });

The globals resolve at evaluation time, so CoCreate may load after AST. OperatorJS expressions can also use $($window.innerWidth) and $($CoCreate.someProperty), or the browser's normal window and CoCreate names inside $().

Synchronous and asynchronous callbacks

$function creates a synchronous callback in both astSync and astAsync. Creating the callback does not execute its body. Wrap it in $async to create an asynchronous callback whose body uses astAsync and returns a Promise:

{
    "$async": {
        "$function": {
            "params": ["value"],
            "body": { "$await": "$value" }
        }
    }
}

Both forms preserve the surrounding scope, parameters, and optional bind. $await requires asynchronous evaluation; a synchronous callback rejects it. A synchronous callback can still return a Promise directly without awaiting it. Async configuration evaluation does not change a callback's declaration.

版本与发布记录

@cocreate/utils 共发布 294 个版本,首次发布于 2021/03/30;过去 12 个月发布了 22 个版本。

版本发布日期距今
2.0.3latest2026/11/073 天前
2.0.22026/11/073 天前
2.0.12026/11/064 天前
2.0.02026/11/037 天前
1.57.02026/10/2120 天前
1.54.02026/08/043 个月前

关于 @cocreate/utils 的常见问题

@cocreate/utils 是什么?

A simple utils component in vanilla javascript. Easily configured using HTML5 attributes and/or JavaScript API.

如何安装 @cocreate/utils?

在项目目录运行 npm install @cocreate/utils,或使用 pnpm add / yarn add / bun add。

@cocreate/utils 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/cocreate__utils 是否存在。

@cocreate/utils 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@cocreate/utils 可以商用吗?

@cocreate/utils 使用 AGPL-3.0 许可。最严格的 Copyleft:除分发外,通过网络向用户提供基于它的服务也需要开源对应源码。闭源 SaaS 使用前务必评估。以上为概括,不构成法律意见,请以许可原文为准。

@cocreate/utils 的下载量有多少?

根据 npm 官方下载统计,@cocreate/utils 在 2026/10/10 – 2026/11/08 这 30 天内被下载 6,378 次,日均约 213 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cocreate/utils 还在维护吗?

最新版本 2.0.3 发布于 2026/11/07(3 天前);至今共发布 294 个版本,其中过去 12 个月发布了 22 个;首次发布于 2021/03/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。