storemw-core-client
v1.1.3
Published
TypeScript client library for the StoreMW backend API — service factories, hook-based config, and cross-framework permission checking for React, Next.js, and React Native.
Maintainers
Readme
storemw-core-client
A TypeScript client library for the StoreMW backend API (storemw-core-api). It ships domain-scoped service factories (ItemService, AuthService, UserService, ...) built on a shared HTTP client, a hook-based configuration system, and a portable, cross-framework permission-checking layer — with no server, no database, and no routes of its own; it's purely the client half.
Works identically in React, Next.js, and React Native.
Install
npm install storemw-core-clientaxios is a peer dependency — install it in your own project if it isn't already there:
npm install axiosQuick start
Register your API config once, before calling any service:
import { registerClientConfigHook } from "storemw-core-client"
registerClientConfigHook({
onSetup: () => ({
apiBaseUrl: "https://api.example.com",
customToken: "...", // optional — read dynamically if it can change at runtime
})
})Then call whichever service factories you need:
import { ItemService } from "storemw-core-client"
const itemService = ItemService({ itemType: "product" })
const { data } = await itemService.list({ limit: 20, offset: 0 })onSetup runs fresh on every service call, not once — read tokens dynamically inside it (e.g. from a cookie or storage) rather than capturing a fixed value.
Available services
| Service | Import | Covers |
|---|---|---|
| Auth | AuthService | Login (authLogin) and changePassword. |
| User | UserService | User accounts. |
| Branch User | BranchUserService | Assigning users to branches. |
| User Role | UserRoleService | Access-control roles — CRUD plus assigning existing roles to a user. A role's permissions are a flat permission_keys array on the role itself. |
| Branch | BranchService | Branches. |
| Document | DocumentService | Sales orders, invoices, purchases, warehouse movement, logistics. |
| Item | ItemService | Product catalog — product/item/category/brand/uom. |
| Location | LocationService | Warehouse structure — location/rack/slot/zone. |
| Region | RegionService | Geography reference data — country/state/area. |
| Business | BusinessService | Business/company entity profile. |
| Account | AccountService | Account (tenant/owner) profile. |
| Repository | RepositoryService | Storage repositories — container/package. |
| Util | UtilService | Standalone endpoints: getMasterAccessPolicyCatalogue, getAccountOwnerAccessKey, validateAccessKey. |
All except UtilService follow the same list / get / create / update / remove shape. Every service returns { status, message, data }, and each service factory has its own scoped types exported alongside it.
import { ItemService, itemTargetTypes } from "storemw-core-client"
const itemService = ItemService({ itemType: "product" })
// list — paginated, filterable
const { data: products } = await itemService.list({
limit: 20,
offset: 0,
filters: [{ name: "status", operator: "eq", value: 1 }]
})
// get — single record by id
const { data: product } = await itemService.get({ id: 123, itemType: "product" })
// create
await itemService.create({
itemTargetType: itemTargetTypes.product,
data: { product: { /* ... */ }, item: { /* ... */ } }
})
// update
await itemService.update({ id: 123, data: { /* ... */ } })
// remove — bulk, by id array
await itemService.remove({ ids: [123, 124] })The exact shape of data for create/update is specific to each service/entity — check that service's exported types (CreateItemProps, UpdateLocationProps, etc.) for the real shape.
Filter operators
filters entries are { name, operator, value, group? }. operator is one of filterOperatorTypes:
import { filterOperatorTypes } from "storemw-core-client"| Operator | Meaning |
|---|---|
| filterOperatorTypes.eq | equals |
| filterOperatorTypes.notEq | not equals |
| filterOperatorTypes.contains | LIKE %value% |
| filterOperatorTypes.startsWith | LIKE value% |
| filterOperatorTypes.endsWith | LIKE %value |
| filterOperatorTypes.moreThanEq | >= |
| filterOperatorTypes.lessThanEq | <= |
| filterOperatorTypes.anyOf | WHERE IN |
| filterOperatorTypes.excludeOf | WHERE NOT IN |
| filterOperatorTypes.isNull | IS NULL — no value needed |
| filterOperatorTypes.isNotNull | IS NOT NULL — no value needed |
A filter entry is silently skipped unless value !== undefined, except for isNull/isNotNull, which don't need a value at all.
Error handling (every method throws, it never returns an error object), multi-entity services, and the full reference — run
npx storemw-client-instructionsto sync the complete guide into your repo.
Permission checking
This package includes a portable access-policy system for gating UI by permission, with full TypeScript literal-type safety — no fs, no Node dependency, safe in a browser bundle or React Native.
One-time setup, from your project root — create storemw.config.ts:
import { defineConfig, env } from "storemw-core-client/node"
export default defineConfig({
accessPolicySource: {
url: env("STOREMW_API_BASE_URL"),
userTypes: ["customer"] // optional — sync only the role(s) this app actually needs
}
})Then sync the catalogue:
npx storemw-client-access-policyThis writes two files to storemw/ in your project root, every time you run it:
| File | Purpose |
|---|---|
| access-policy.json | The raw permission catalogue as returned by the backend (or a subset of it, if you set userTypes) — every role, and every scope/module/action each role is allowed. This is the source data; you generally don't import it yourself. |
| access-policy.types.ts | Generated from access-policy.json at sync time. Exports checkPermission, hasEffectivePermission, accessPolicyUserTypes, and the AccessPolicyUserType/AccessPolicyCheck types — this is the file you actually import from in your app. It self-imports its sibling access-policy.json, so you never wire the catalogue up by hand. |
Re-run npx storemw-client-access-policy any time the backend's permission structure changes — both files are fully overwritten on every run, never incrementally updated, so don't hand-edit either one.
Use hasEffectivePermission for real, day-to-day gating against the currently logged-in user's actual granted permissions (from your login API's effective_permission_keys):
import { hasEffectivePermission, accessPolicyUserTypes } from "../storemw/access-policy.types"
const { user_type, effective_permission_keys } = await loginResponse
hasEffectivePermission(user_type, effective_permission_keys, { scope: "item", module: "product", action: "delete" }) // -> true/false
// TypeScript rejects an unknown user type or an invalid scope/module/action combo at compile timecheckPermission(userType, check) is also generated, for the narrower "is this a valid permission for this role at all" question (e.g. an admin permission-matrix UI), independent of who's logged in.
Full usage guide, including the Next.js Server/Client Component pattern, ships locally once you run:
npx storemw-client-instructionsCLI commands
Both are registered in this package's bin field, so they run directly via npx — no setup step, works immediately after npm install, on macOS, Linux, and Windows alike (npm generates the Windows .cmd/.ps1 wrappers automatically).
npx storemw-client-instructions
Copies this package's consumer-facing docs (CLAUDE.md, SERVICES.md, NEXTJS.md) into your own repo, under instructions/storemw-core-client/, and links them into your project's root CLAUDE.md (creating one if you don't have one yet, appending if you do — never inserted twice). Re-run it after upgrading storemw-core-client to pull the latest docs; every run wipes and recreates the destination, so it never leaves stale files behind after a doc rename/removal upstream.
npx storemw-client-access-policy
Fetches the master access policy catalogue from your backend (a public endpoint — no auth token needed) and generates the permission-checking files described above. Requires a storemw.config.ts at your project root first (see "Permission checking"), and the typescript package installed in your project (used to read that config file).
Subpath exports
| Subpath | Contains |
|---|---|
| storemw-core-client | Everything below except /node — services, config, lib, utils, features |
| storemw-core-client/access-policy | isPermissionDefined, isPermissionGranted and their types — the smallest, most isolated import for permission checks (~1.2KB minified vs. ~192KB from the root) |
| storemw-core-client/node | Node-only dev tooling: syncAccessPolicy, loadConfig, defineConfig, env — never import this from browser/Client Component code |
| storemw-core-client/services | Just the service factories |
| storemw-core-client/lib | ApiClient, getApiClient, URL-builder helpers, access policy primitives |
| storemw-core-client/features | registerClientConfigHook |
| storemw-core-client/utils | dayjs/lodash re-export helpers |
Development
npm install # install dependencies
npm run build # tsc && tsc-alias -> dist/
npm run dev # ts-node -r tsconfig-paths/register src/index.ts
npx tsc --noEmit -p tsconfig.json # typecheck onlySee CLAUDE.md for the full internal architecture, conventions, and design rationale.
License
ISC
