@memberjunction/lists-base 0.0.1 → 5.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +266 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +48 -0
- package/dist/types.js.map +1 -0
- package/package.json +25 -7
- package/README.md +0 -45
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC","sourcesContent":["export * from './types';\n"]}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @memberjunction/lists-base — public type surface.
|
|
3
|
+
*
|
|
4
|
+
* These types are isomorphic (no runtime, no Node-only or DOM-only APIs) and
|
|
5
|
+
* are the single source of truth shared by:
|
|
6
|
+
* - `@memberjunction/lists` (server-side operations)
|
|
7
|
+
* - `@memberjunction/graphql-dataprovider` (browser client)
|
|
8
|
+
* - Angular UI packages
|
|
9
|
+
*
|
|
10
|
+
* Naming: PascalCase for public members (per MJ convention).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* How a refresh operation reconciles a target list against its source.
|
|
14
|
+
*
|
|
15
|
+
* - `Additive`: only adds new members from the source; never removes.
|
|
16
|
+
* - `Sync`: makes the target exactly equal the source — may remove members
|
|
17
|
+
* that are no longer in the source. This is the only refresh mode that can
|
|
18
|
+
* produce drops, and therefore the only one that requires `ConfirmDrops`.
|
|
19
|
+
*/
|
|
20
|
+
export type ListRefreshMode = 'Additive' | 'Sync';
|
|
21
|
+
/**
|
|
22
|
+
* Discriminated union identifying any source of records that can feed a list
|
|
23
|
+
* operation. The same shape is exported as `AudienceSource` — they are
|
|
24
|
+
* intentionally identical so the audience picker and the list-operations
|
|
25
|
+
* pipeline share a vocabulary.
|
|
26
|
+
*
|
|
27
|
+
* - `list`: an existing MJ List, resolved via its members.
|
|
28
|
+
* - `view`: a User View, resolved via RunView with optional runtime params.
|
|
29
|
+
* - `adhoc`: an arbitrary entity + filter — no persisted view backing it.
|
|
30
|
+
*/
|
|
31
|
+
export type ListSource = {
|
|
32
|
+
kind: 'list';
|
|
33
|
+
listId: string;
|
|
34
|
+
} | {
|
|
35
|
+
kind: 'view';
|
|
36
|
+
viewId: string;
|
|
37
|
+
runtimeParams?: Record<string, unknown>;
|
|
38
|
+
} | {
|
|
39
|
+
kind: 'adhoc';
|
|
40
|
+
entityName: string;
|
|
41
|
+
extraFilter: string;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* `AudienceSource` is the same discriminated union as `ListSource` — same
|
|
45
|
+
* `kind` discriminator, same payload shape — but named after its primary
|
|
46
|
+
* downstream consumer (the Communications module). Defining it as a type
|
|
47
|
+
* alias lets the Angular picker, the SendToAudience helper, and any
|
|
48
|
+
* future audience-aware feature share one vocabulary with the list
|
|
49
|
+
* operations stack without forcing them to import a "list" type.
|
|
50
|
+
*/
|
|
51
|
+
export type AudienceSource = ListSource;
|
|
52
|
+
/**
|
|
53
|
+
* Resolved record set returned by list-source resolution.
|
|
54
|
+
*
|
|
55
|
+
* `RecordIds` are stringified composite-key payloads in the same format used
|
|
56
|
+
* by `MJ: List Detail.RecordID`. For single-column primary keys this is just
|
|
57
|
+
* the ID; for composite keys it is the canonical `Field1|Value1||Field2|…`
|
|
58
|
+
* format.
|
|
59
|
+
*
|
|
60
|
+
* `EntityName` is single-valued — Lists are single-entity by design. If a
|
|
61
|
+
* caller mixes sources of different entities, the operation surfaces an
|
|
62
|
+
* `ENTITY_MISMATCH` warning rather than silently coercing.
|
|
63
|
+
*/
|
|
64
|
+
export interface ResolvedRecordSet {
|
|
65
|
+
EntityName: string;
|
|
66
|
+
RecordIds: string[];
|
|
67
|
+
/** Optional total count when the source is paged or streamed. */
|
|
68
|
+
TotalCount?: number;
|
|
69
|
+
}
|
|
70
|
+
/** Discriminator for set-operations. */
|
|
71
|
+
export type SetOpKind = 'union' | 'intersection' | 'difference';
|
|
72
|
+
/**
|
|
73
|
+
* Category of warning surfaced by a delta or set-op preview. Warnings do not
|
|
74
|
+
* block — `ApplyDelta` enforces the hard rules (drop confirmation, stale
|
|
75
|
+
* tokens, permissions). Use warnings to drive UX hints.
|
|
76
|
+
*/
|
|
77
|
+
export type ListDeltaWarningCode = 'WILL_REMOVE_RECORDS' | 'ENTITY_MISMATCH' | 'EMPTY_SOURCE' | 'EMPTY_TARGET' | 'LARGE_OPERATION';
|
|
78
|
+
/**
|
|
79
|
+
* Single warning attached to a `ListDelta`. `Message` is human-readable;
|
|
80
|
+
* `Code` drives any UI logic that needs to react to a specific class of
|
|
81
|
+
* warning (most importantly `WILL_REMOVE_RECORDS`, which the delta-confirm
|
|
82
|
+
* dialog uses to require explicit acknowledgement).
|
|
83
|
+
*/
|
|
84
|
+
export interface ListDeltaWarning {
|
|
85
|
+
Code: ListDeltaWarningCode;
|
|
86
|
+
Message: string;
|
|
87
|
+
/** Optional structured payload for the UI. */
|
|
88
|
+
Details?: Record<string, unknown>;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Aggregate counts on a `ListDelta`. Always present — clients can render
|
|
92
|
+
* "+N / −M / Unchanged K" summary tiles without re-counting arrays.
|
|
93
|
+
*/
|
|
94
|
+
export interface ListDeltaCounts {
|
|
95
|
+
Add: number;
|
|
96
|
+
Remove: number;
|
|
97
|
+
Unchanged: number;
|
|
98
|
+
SourceTotal: number;
|
|
99
|
+
TargetTotal: number;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Result of a preview call (`ComputeDelta` or `ComputeSetOp`). Never mutates.
|
|
103
|
+
*
|
|
104
|
+
* `DeltaToken` is a server-signed HMAC of `{ targetListId, source signature,
|
|
105
|
+
* mode, timestamp }` with a 5-minute TTL. `ApplyDelta` will reject any token
|
|
106
|
+
* that fails to verify, has expired, or no longer reflects current state
|
|
107
|
+
* (which it detects by re-computing on the server).
|
|
108
|
+
*
|
|
109
|
+
* `TargetListId` is `null` when the operation creates a new list rather than
|
|
110
|
+
* mutating an existing one (e.g. `MaterializeFromView`).
|
|
111
|
+
*/
|
|
112
|
+
export interface ListDelta {
|
|
113
|
+
TargetListId: string | null;
|
|
114
|
+
EntityName: string;
|
|
115
|
+
ToAdd: string[];
|
|
116
|
+
ToRemove: string[];
|
|
117
|
+
Unchanged: string[];
|
|
118
|
+
Counts: ListDeltaCounts;
|
|
119
|
+
Warnings: ListDeltaWarning[];
|
|
120
|
+
DeltaToken: string;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Options for `MaterializeFromView` — creates a new list from a view result.
|
|
124
|
+
*
|
|
125
|
+
* `RememberLineage` controls whether the new list captures the source view
|
|
126
|
+
* ID + filter snapshot. With it `false`, the list is a one-shot copy and
|
|
127
|
+
* cannot be refreshed.
|
|
128
|
+
*
|
|
129
|
+
* `UseSnapshot` controls refresh behaviour when lineage is remembered: when
|
|
130
|
+
* `true`, refreshes re-apply the captured filter snapshot; when `false`,
|
|
131
|
+
* refreshes re-read the live view (default).
|
|
132
|
+
*/
|
|
133
|
+
export interface MaterializeOptions {
|
|
134
|
+
ListName: string;
|
|
135
|
+
CategoryId?: string;
|
|
136
|
+
Description?: string;
|
|
137
|
+
RememberLineage: boolean;
|
|
138
|
+
UseSnapshot: boolean;
|
|
139
|
+
RefreshMode: ListRefreshMode;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Result codes returned by `ApplyDelta` and the high-level convenience
|
|
143
|
+
* operations. Every non-`SUCCESS` code maps to a user-visible failure mode
|
|
144
|
+
* the UI must handle explicitly.
|
|
145
|
+
*/
|
|
146
|
+
export type ApplyResultCode = 'SUCCESS' | 'DROP_NOT_CONFIRMED' | 'STALE_DELTA' | 'INVALID_TOKEN' | 'PERMISSION_DENIED' | 'TARGET_NOT_FOUND' | 'PARTIAL_SUCCESS' | 'UNEXPECTED_ERROR';
|
|
147
|
+
/**
|
|
148
|
+
* Outcome of a mutating list operation. `Counts` reports what actually
|
|
149
|
+
* happened (which may differ from the preview if records were concurrently
|
|
150
|
+
* modified — that case surfaces as `STALE_DELTA` rather than silent skew).
|
|
151
|
+
*/
|
|
152
|
+
export interface ApplyResult {
|
|
153
|
+
Success: boolean;
|
|
154
|
+
ResultCode: ApplyResultCode;
|
|
155
|
+
Message: string;
|
|
156
|
+
/** Populated when `MaterializeFromView` (or similar) creates a new list. */
|
|
157
|
+
CreatedListId?: string;
|
|
158
|
+
TargetListId?: string;
|
|
159
|
+
Counts?: {
|
|
160
|
+
Added: number;
|
|
161
|
+
Removed: number;
|
|
162
|
+
Failed: number;
|
|
163
|
+
};
|
|
164
|
+
Errors?: string[];
|
|
165
|
+
}
|
|
166
|
+
/** Permission level granted to a share recipient. Mirrors the
|
|
167
|
+
* MJResourcePermission `PermissionLevel` field exactly. */
|
|
168
|
+
export type SharePermissionLevel = 'View' | 'Edit' | 'Owner';
|
|
169
|
+
/**
|
|
170
|
+
* Capability flags derived from a permission level. The mapping mirrors
|
|
171
|
+
* the gating rules from mockup 19:
|
|
172
|
+
* - Viewer: hide Add/Remove/Refresh/Edit/Share/Delete/Operations
|
|
173
|
+
* - Editor: hide Delete/Share
|
|
174
|
+
* - Owner: show everything
|
|
175
|
+
* Server-side enforcement remains the source of truth — this is a UX
|
|
176
|
+
* convenience so users don't see buttons they'll be rejected on.
|
|
177
|
+
*/
|
|
178
|
+
export interface ListCapabilities {
|
|
179
|
+
CanRead: boolean;
|
|
180
|
+
CanEdit: boolean;
|
|
181
|
+
CanRefresh: boolean;
|
|
182
|
+
CanShare: boolean;
|
|
183
|
+
CanDelete: boolean;
|
|
184
|
+
CanRunOperations: boolean;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Pure mapping function from a permission level (or `null` for "no access")
|
|
188
|
+
* to a capability flag set. Stateless, no runtime dependencies — safe to use
|
|
189
|
+
* in any context.
|
|
190
|
+
*/
|
|
191
|
+
export declare function CapabilitiesForLevel(level: SharePermissionLevel | null): ListCapabilities;
|
|
192
|
+
/**
|
|
193
|
+
* Target of a direct share: either an MJ user or an MJ role. Discriminated
|
|
194
|
+
* union so the type system enforces exactly one of `userId` / `roleId` is
|
|
195
|
+
* provided (mirrors the `ValidateTypeAndRoleOrUserIDExclusive` rule on
|
|
196
|
+
* `MJResourcePermission`).
|
|
197
|
+
*/
|
|
198
|
+
export type ShareTarget = {
|
|
199
|
+
kind: 'user';
|
|
200
|
+
userId: string;
|
|
201
|
+
} | {
|
|
202
|
+
kind: 'role';
|
|
203
|
+
roleId: string;
|
|
204
|
+
};
|
|
205
|
+
/** Summary of one share row returned by `GetSharesForList`. */
|
|
206
|
+
export interface ListShareSummary {
|
|
207
|
+
PermissionID: string;
|
|
208
|
+
ListID: string;
|
|
209
|
+
Target: ShareTarget;
|
|
210
|
+
PermissionLevel: SharePermissionLevel;
|
|
211
|
+
Status: 'Approved' | 'Requested' | 'Rejected' | 'Revoked';
|
|
212
|
+
SharedByUserID: string | null;
|
|
213
|
+
CreatedAt: Date;
|
|
214
|
+
}
|
|
215
|
+
/** Summary of one List visible to the current user via shares. */
|
|
216
|
+
export interface SharedListSummary {
|
|
217
|
+
ListID: string;
|
|
218
|
+
ListName: string;
|
|
219
|
+
PermissionLevel: SharePermissionLevel;
|
|
220
|
+
SharedByUserID: string | null;
|
|
221
|
+
SharedAt: Date;
|
|
222
|
+
}
|
|
223
|
+
/** Status codes returned by sharing operations. */
|
|
224
|
+
export type ShareResultCode = 'SUCCESS' | 'INVALID_PARAMETER' | 'LIST_NOT_FOUND' | 'INVITATION_NOT_FOUND' | 'INVITATION_EXPIRED' | 'INVITATION_ALREADY_USED' | 'INVITATION_REVOKED' | 'PERMISSION_NOT_FOUND' | 'EMAIL_RECIPIENT_NOT_FOUND' | 'UNEXPECTED_ERROR';
|
|
225
|
+
export interface ShareResult {
|
|
226
|
+
Success: boolean;
|
|
227
|
+
ResultCode: ShareResultCode;
|
|
228
|
+
Message: string;
|
|
229
|
+
PermissionID?: string;
|
|
230
|
+
}
|
|
231
|
+
export interface InviteResult {
|
|
232
|
+
Success: boolean;
|
|
233
|
+
ResultCode: ShareResultCode;
|
|
234
|
+
Message: string;
|
|
235
|
+
InvitationID?: string;
|
|
236
|
+
Token?: string;
|
|
237
|
+
ExpiresAt?: Date;
|
|
238
|
+
}
|
|
239
|
+
export interface AcceptInvitationResult {
|
|
240
|
+
Success: boolean;
|
|
241
|
+
ResultCode: ShareResultCode;
|
|
242
|
+
Message: string;
|
|
243
|
+
PermissionID?: string;
|
|
244
|
+
ListID?: string;
|
|
245
|
+
}
|
|
246
|
+
/** Token validity window — matches the 5-minute requirement in the plan. */
|
|
247
|
+
export declare const TOKEN_TTL_MS: number;
|
|
248
|
+
/** Mode tag baked into the payload — drives drop-guard enforcement. */
|
|
249
|
+
export type DeltaTokenMode = 'Additive' | 'Sync' | 'SetOp';
|
|
250
|
+
/**
|
|
251
|
+
* Canonical payload shape. Kept tiny + versioned so we can evolve the
|
|
252
|
+
* signing scheme without breaking running clients.
|
|
253
|
+
*/
|
|
254
|
+
export interface DeltaTokenPayload {
|
|
255
|
+
v: 1;
|
|
256
|
+
tid: string | null;
|
|
257
|
+
ssig: string;
|
|
258
|
+
m: DeltaTokenMode;
|
|
259
|
+
iat: number;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Reasons a token can fail verification. Mapped 1:1 by the resolver layer
|
|
263
|
+
* onto user-visible `ApplyResultCode` values.
|
|
264
|
+
*/
|
|
265
|
+
export type DeltaTokenError = 'INVALID_TOKEN' | 'EXPIRED_TOKEN';
|
|
266
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @memberjunction/lists-base — public type surface.
|
|
3
|
+
*
|
|
4
|
+
* These types are isomorphic (no runtime, no Node-only or DOM-only APIs) and
|
|
5
|
+
* are the single source of truth shared by:
|
|
6
|
+
* - `@memberjunction/lists` (server-side operations)
|
|
7
|
+
* - `@memberjunction/graphql-dataprovider` (browser client)
|
|
8
|
+
* - Angular UI packages
|
|
9
|
+
*
|
|
10
|
+
* Naming: PascalCase for public members (per MJ convention).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Pure mapping function from a permission level (or `null` for "no access")
|
|
14
|
+
* to a capability flag set. Stateless, no runtime dependencies — safe to use
|
|
15
|
+
* in any context.
|
|
16
|
+
*/
|
|
17
|
+
export function CapabilitiesForLevel(level) {
|
|
18
|
+
if (level === 'Owner') {
|
|
19
|
+
return {
|
|
20
|
+
CanRead: true, CanEdit: true, CanRefresh: true,
|
|
21
|
+
CanShare: true, CanDelete: true, CanRunOperations: true,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
if (level === 'Edit') {
|
|
25
|
+
return {
|
|
26
|
+
CanRead: true, CanEdit: true, CanRefresh: true,
|
|
27
|
+
CanShare: false, CanDelete: false, CanRunOperations: true,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (level === 'View') {
|
|
31
|
+
return {
|
|
32
|
+
CanRead: true, CanEdit: false, CanRefresh: false,
|
|
33
|
+
CanShare: false, CanDelete: false, CanRunOperations: false,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// No access at all — caller should hide the list entirely.
|
|
37
|
+
return {
|
|
38
|
+
CanRead: false, CanEdit: false, CanRefresh: false,
|
|
39
|
+
CanShare: false, CanDelete: false, CanRunOperations: false,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Delta token payload — type surface only. The runtime sign/verify lives
|
|
44
|
+
// server-side in @memberjunction/lists.
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
/** Token validity window — matches the 5-minute requirement in the plan. */
|
|
47
|
+
export const TOKEN_TTL_MS = 5 * 60 * 1000;
|
|
48
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAuMH;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAkC;IACrE,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO;YACL,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI;YAC9C,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,gBAAgB,EAAE,IAAI;SACxD,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI;YAC9C,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI;SAC1D,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO;YACL,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK;YAChD,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK;SAC3D,CAAC;IACJ,CAAC;IACD,2DAA2D;IAC3D,OAAO;QACL,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,KAAK;QACjD,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,KAAK;KAC3D,CAAC;AACJ,CAAC;AAqED,8EAA8E;AAC9E,yEAAyE;AACzE,wCAAwC;AACxC,8EAA8E;AAE9E,4EAA4E;AAC5E,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC","sourcesContent":["/**\n * @memberjunction/lists-base — public type surface.\n *\n * These types are isomorphic (no runtime, no Node-only or DOM-only APIs) and\n * are the single source of truth shared by:\n * - `@memberjunction/lists` (server-side operations)\n * - `@memberjunction/graphql-dataprovider` (browser client)\n * - Angular UI packages\n *\n * Naming: PascalCase for public members (per MJ convention).\n */\n\n// ---------------------------------------------------------------------------\n// List operations — refresh modes, sources, deltas, set-ops, materialize\n// ---------------------------------------------------------------------------\n\n/**\n * How a refresh operation reconciles a target list against its source.\n *\n * - `Additive`: only adds new members from the source; never removes.\n * - `Sync`: makes the target exactly equal the source — may remove members\n * that are no longer in the source. This is the only refresh mode that can\n * produce drops, and therefore the only one that requires `ConfirmDrops`.\n */\nexport type ListRefreshMode = 'Additive' | 'Sync';\n\n/**\n * Discriminated union identifying any source of records that can feed a list\n * operation. The same shape is exported as `AudienceSource` — they are\n * intentionally identical so the audience picker and the list-operations\n * pipeline share a vocabulary.\n *\n * - `list`: an existing MJ List, resolved via its members.\n * - `view`: a User View, resolved via RunView with optional runtime params.\n * - `adhoc`: an arbitrary entity + filter — no persisted view backing it.\n */\nexport type ListSource =\n | { kind: 'list'; listId: string }\n | { kind: 'view'; viewId: string; runtimeParams?: Record<string, unknown> }\n | { kind: 'adhoc'; entityName: string; extraFilter: string };\n\n/**\n * `AudienceSource` is the same discriminated union as `ListSource` — same\n * `kind` discriminator, same payload shape — but named after its primary\n * downstream consumer (the Communications module). Defining it as a type\n * alias lets the Angular picker, the SendToAudience helper, and any\n * future audience-aware feature share one vocabulary with the list\n * operations stack without forcing them to import a \"list\" type.\n */\nexport type AudienceSource = ListSource;\n\n/**\n * Resolved record set returned by list-source resolution.\n *\n * `RecordIds` are stringified composite-key payloads in the same format used\n * by `MJ: List Detail.RecordID`. For single-column primary keys this is just\n * the ID; for composite keys it is the canonical `Field1|Value1||Field2|…`\n * format.\n *\n * `EntityName` is single-valued — Lists are single-entity by design. If a\n * caller mixes sources of different entities, the operation surfaces an\n * `ENTITY_MISMATCH` warning rather than silently coercing.\n */\nexport interface ResolvedRecordSet {\n EntityName: string;\n RecordIds: string[];\n /** Optional total count when the source is paged or streamed. */\n TotalCount?: number;\n}\n\n/** Discriminator for set-operations. */\nexport type SetOpKind = 'union' | 'intersection' | 'difference';\n\n/**\n * Category of warning surfaced by a delta or set-op preview. Warnings do not\n * block — `ApplyDelta` enforces the hard rules (drop confirmation, stale\n * tokens, permissions). Use warnings to drive UX hints.\n */\nexport type ListDeltaWarningCode =\n | 'WILL_REMOVE_RECORDS'\n | 'ENTITY_MISMATCH'\n | 'EMPTY_SOURCE'\n | 'EMPTY_TARGET'\n | 'LARGE_OPERATION';\n\n/**\n * Single warning attached to a `ListDelta`. `Message` is human-readable;\n * `Code` drives any UI logic that needs to react to a specific class of\n * warning (most importantly `WILL_REMOVE_RECORDS`, which the delta-confirm\n * dialog uses to require explicit acknowledgement).\n */\nexport interface ListDeltaWarning {\n Code: ListDeltaWarningCode;\n Message: string;\n /** Optional structured payload for the UI. */\n Details?: Record<string, unknown>;\n}\n\n/**\n * Aggregate counts on a `ListDelta`. Always present — clients can render\n * \"+N / −M / Unchanged K\" summary tiles without re-counting arrays.\n */\nexport interface ListDeltaCounts {\n Add: number;\n Remove: number;\n Unchanged: number;\n SourceTotal: number;\n TargetTotal: number;\n}\n\n/**\n * Result of a preview call (`ComputeDelta` or `ComputeSetOp`). Never mutates.\n *\n * `DeltaToken` is a server-signed HMAC of `{ targetListId, source signature,\n * mode, timestamp }` with a 5-minute TTL. `ApplyDelta` will reject any token\n * that fails to verify, has expired, or no longer reflects current state\n * (which it detects by re-computing on the server).\n *\n * `TargetListId` is `null` when the operation creates a new list rather than\n * mutating an existing one (e.g. `MaterializeFromView`).\n */\nexport interface ListDelta {\n TargetListId: string | null;\n EntityName: string;\n ToAdd: string[];\n ToRemove: string[];\n Unchanged: string[];\n Counts: ListDeltaCounts;\n Warnings: ListDeltaWarning[];\n DeltaToken: string;\n}\n\n/**\n * Options for `MaterializeFromView` — creates a new list from a view result.\n *\n * `RememberLineage` controls whether the new list captures the source view\n * ID + filter snapshot. With it `false`, the list is a one-shot copy and\n * cannot be refreshed.\n *\n * `UseSnapshot` controls refresh behaviour when lineage is remembered: when\n * `true`, refreshes re-apply the captured filter snapshot; when `false`,\n * refreshes re-read the live view (default).\n */\nexport interface MaterializeOptions {\n ListName: string;\n CategoryId?: string;\n Description?: string;\n RememberLineage: boolean;\n UseSnapshot: boolean;\n RefreshMode: ListRefreshMode;\n}\n\n/**\n * Result codes returned by `ApplyDelta` and the high-level convenience\n * operations. Every non-`SUCCESS` code maps to a user-visible failure mode\n * the UI must handle explicitly.\n */\nexport type ApplyResultCode =\n | 'SUCCESS'\n | 'DROP_NOT_CONFIRMED'\n | 'STALE_DELTA'\n | 'INVALID_TOKEN'\n | 'PERMISSION_DENIED'\n | 'TARGET_NOT_FOUND'\n | 'PARTIAL_SUCCESS'\n | 'UNEXPECTED_ERROR';\n\n/**\n * Outcome of a mutating list operation. `Counts` reports what actually\n * happened (which may differ from the preview if records were concurrently\n * modified — that case surfaces as `STALE_DELTA` rather than silent skew).\n */\nexport interface ApplyResult {\n Success: boolean;\n ResultCode: ApplyResultCode;\n Message: string;\n /** Populated when `MaterializeFromView` (or similar) creates a new list. */\n CreatedListId?: string;\n TargetListId?: string;\n Counts?: { Added: number; Removed: number; Failed: number };\n Errors?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Sharing — permission levels, capabilities, share targets, results\n// ---------------------------------------------------------------------------\n\n/** Permission level granted to a share recipient. Mirrors the\n * MJResourcePermission `PermissionLevel` field exactly. */\nexport type SharePermissionLevel = 'View' | 'Edit' | 'Owner';\n\n/**\n * Capability flags derived from a permission level. The mapping mirrors\n * the gating rules from mockup 19:\n * - Viewer: hide Add/Remove/Refresh/Edit/Share/Delete/Operations\n * - Editor: hide Delete/Share\n * - Owner: show everything\n * Server-side enforcement remains the source of truth — this is a UX\n * convenience so users don't see buttons they'll be rejected on.\n */\nexport interface ListCapabilities {\n CanRead: boolean;\n CanEdit: boolean;\n CanRefresh: boolean;\n CanShare: boolean;\n CanDelete: boolean;\n CanRunOperations: boolean;\n}\n\n/**\n * Pure mapping function from a permission level (or `null` for \"no access\")\n * to a capability flag set. Stateless, no runtime dependencies — safe to use\n * in any context.\n */\nexport function CapabilitiesForLevel(level: SharePermissionLevel | null): ListCapabilities {\n if (level === 'Owner') {\n return {\n CanRead: true, CanEdit: true, CanRefresh: true,\n CanShare: true, CanDelete: true, CanRunOperations: true,\n };\n }\n if (level === 'Edit') {\n return {\n CanRead: true, CanEdit: true, CanRefresh: true,\n CanShare: false, CanDelete: false, CanRunOperations: true,\n };\n }\n if (level === 'View') {\n return {\n CanRead: true, CanEdit: false, CanRefresh: false,\n CanShare: false, CanDelete: false, CanRunOperations: false,\n };\n }\n // No access at all — caller should hide the list entirely.\n return {\n CanRead: false, CanEdit: false, CanRefresh: false,\n CanShare: false, CanDelete: false, CanRunOperations: false,\n };\n}\n\n/**\n * Target of a direct share: either an MJ user or an MJ role. Discriminated\n * union so the type system enforces exactly one of `userId` / `roleId` is\n * provided (mirrors the `ValidateTypeAndRoleOrUserIDExclusive` rule on\n * `MJResourcePermission`).\n */\nexport type ShareTarget =\n | { kind: 'user'; userId: string }\n | { kind: 'role'; roleId: string };\n\n/** Summary of one share row returned by `GetSharesForList`. */\nexport interface ListShareSummary {\n PermissionID: string;\n ListID: string;\n Target: ShareTarget;\n PermissionLevel: SharePermissionLevel;\n Status: 'Approved' | 'Requested' | 'Rejected' | 'Revoked';\n SharedByUserID: string | null;\n CreatedAt: Date;\n}\n\n/** Summary of one List visible to the current user via shares. */\nexport interface SharedListSummary {\n ListID: string;\n ListName: string;\n PermissionLevel: SharePermissionLevel;\n SharedByUserID: string | null;\n SharedAt: Date;\n}\n\n/** Status codes returned by sharing operations. */\nexport type ShareResultCode =\n | 'SUCCESS'\n | 'INVALID_PARAMETER'\n | 'LIST_NOT_FOUND'\n | 'INVITATION_NOT_FOUND'\n | 'INVITATION_EXPIRED'\n | 'INVITATION_ALREADY_USED'\n | 'INVITATION_REVOKED'\n | 'PERMISSION_NOT_FOUND'\n | 'EMAIL_RECIPIENT_NOT_FOUND'\n | 'UNEXPECTED_ERROR';\n\nexport interface ShareResult {\n Success: boolean;\n ResultCode: ShareResultCode;\n Message: string;\n PermissionID?: string;\n}\n\nexport interface InviteResult {\n Success: boolean;\n ResultCode: ShareResultCode;\n Message: string;\n InvitationID?: string;\n Token?: string;\n ExpiresAt?: Date;\n}\n\nexport interface AcceptInvitationResult {\n Success: boolean;\n ResultCode: ShareResultCode;\n Message: string;\n PermissionID?: string;\n ListID?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Delta token payload — type surface only. The runtime sign/verify lives\n// server-side in @memberjunction/lists.\n// ---------------------------------------------------------------------------\n\n/** Token validity window — matches the 5-minute requirement in the plan. */\nexport const TOKEN_TTL_MS = 5 * 60 * 1000;\n\n/** Mode tag baked into the payload — drives drop-guard enforcement. */\nexport type DeltaTokenMode = 'Additive' | 'Sync' | 'SetOp';\n\n/**\n * Canonical payload shape. Kept tiny + versioned so we can evolve the\n * signing scheme without breaking running clients.\n */\nexport interface DeltaTokenPayload {\n v: 1;\n tid: string | null;\n ssig: string;\n m: DeltaTokenMode;\n iat: number;\n}\n\n/**\n * Reasons a token can fail verification. Mapped 1:1 by the resolver layer\n * onto user-visible `ApplyResultCode` values.\n */\nexport type DeltaTokenError = 'INVALID_TOKEN' | 'EXPIRED_TOKEN';\n"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/lists-base",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "5.36.0",
|
|
5
|
+
"description": "MemberJunction: Lists — shared TypeScript type surface used by the server-side @memberjunction/lists package, the GraphQL data provider client, and Angular UI consumers. Pure types/interfaces only; no runtime, isomorphic.",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"/dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc && tsc-alias -f",
|
|
13
|
+
"test": "vitest run",
|
|
14
|
+
"test:watch": "vitest",
|
|
15
|
+
"test:coverage": "vitest run --coverage"
|
|
16
|
+
},
|
|
17
|
+
"author": "MemberJunction.com",
|
|
18
|
+
"license": "ISC",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"typescript": "^5.9.3",
|
|
21
|
+
"vitest": "^4.0.18"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/MemberJunction/MJ"
|
|
27
|
+
}
|
|
10
28
|
}
|
package/README.md
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
# @memberjunction/lists-base
|
|
2
|
-
|
|
3
|
-
## ⚠️ IMPORTANT NOTICE ⚠️
|
|
4
|
-
|
|
5
|
-
**This package is created solely for the purpose of setting up OIDC (OpenID Connect) trusted publishing with npm.**
|
|
6
|
-
|
|
7
|
-
This is **NOT** a functional package and contains **NO** code or functionality beyond the OIDC setup configuration.
|
|
8
|
-
|
|
9
|
-
## Purpose
|
|
10
|
-
|
|
11
|
-
This package exists to:
|
|
12
|
-
1. Configure OIDC trusted publishing for the package name `@memberjunction/lists-base`
|
|
13
|
-
2. Enable secure, token-less publishing from CI/CD workflows
|
|
14
|
-
3. Establish provenance for packages published under this name
|
|
15
|
-
|
|
16
|
-
## What is OIDC Trusted Publishing?
|
|
17
|
-
|
|
18
|
-
OIDC trusted publishing allows package maintainers to publish packages directly from their CI/CD workflows without needing to manage npm access tokens. Instead, it uses OpenID Connect to establish trust between the CI/CD provider (like GitHub Actions) and npm.
|
|
19
|
-
|
|
20
|
-
## Setup Instructions
|
|
21
|
-
|
|
22
|
-
To properly configure OIDC trusted publishing for this package:
|
|
23
|
-
|
|
24
|
-
1. Go to [npmjs.com](https://www.npmjs.com/) and navigate to your package settings
|
|
25
|
-
2. Configure the trusted publisher (e.g., GitHub Actions)
|
|
26
|
-
3. Specify the repository and workflow that should be allowed to publish
|
|
27
|
-
4. Use the configured workflow to publish your actual package
|
|
28
|
-
|
|
29
|
-
## DO NOT USE THIS PACKAGE
|
|
30
|
-
|
|
31
|
-
This package is a placeholder for OIDC configuration only. It:
|
|
32
|
-
- Contains no executable code
|
|
33
|
-
- Provides no functionality
|
|
34
|
-
- Should not be installed as a dependency
|
|
35
|
-
- Exists only for administrative purposes
|
|
36
|
-
|
|
37
|
-
## More Information
|
|
38
|
-
|
|
39
|
-
For more details about npm's trusted publishing feature, see:
|
|
40
|
-
- [npm Trusted Publishing Documentation](https://docs.npmjs.com/generating-provenance-statements)
|
|
41
|
-
- [GitHub Actions OIDC Documentation](https://docs.github.com/en/actions/deployment/security-hardening-your-deployments/about-security-hardening-with-openid-connect)
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
|
-
**Maintained for OIDC setup purposes only**
|