@cimplify/sdk 0.100.2 → 0.100.4

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.
Files changed (55) hide show
  1. package/README.md +17 -0
  2. package/dist/advanced.d.mts +1 -1
  3. package/dist/advanced.d.ts +1 -1
  4. package/dist/advanced.js +20 -20
  5. package/dist/advanced.mjs +1 -1
  6. package/dist/{chunk-6JEKKL3M.js → chunk-3HU5I5VG.js} +23 -4
  7. package/dist/{chunk-YWNJJO2U.mjs → chunk-HSDQWJLA.mjs} +2 -2
  8. package/dist/{chunk-IJI7KMTG.js → chunk-JEVCHTKZ.js} +256 -74
  9. package/dist/{chunk-QRBBSIAY.js → chunk-LMD7B33E.js} +4 -4
  10. package/dist/{chunk-IFAQLFAJ.js → chunk-PNTINRAU.js} +33 -3
  11. package/dist/{chunk-B2YOCOLH.mjs → chunk-RQPXLXB2.mjs} +33 -3
  12. package/dist/{chunk-PJUXAUM2.mjs → chunk-RWR7JF7F.mjs} +210 -28
  13. package/dist/{chunk-TIQLOH2B.mjs → chunk-Z7M6GAHS.mjs} +23 -4
  14. package/dist/{client-D8XcrONA.d.mts → client-BwRAAk4y.d.mts} +26 -2
  15. package/dist/{client-CgXkRu2o.d.ts → client-CPcZIrjC.d.ts} +2 -2
  16. package/dist/{client-LPg_AUUr.d.ts → client-CrPglBBz.d.ts} +26 -2
  17. package/dist/{client-C6wb92AD.d.mts → client-DGrvLiJv.d.mts} +2 -2
  18. package/dist/index.d.mts +2 -2
  19. package/dist/index.d.ts +2 -2
  20. package/dist/index.js +69 -69
  21. package/dist/index.mjs +3 -3
  22. package/dist/lint-rules.json +1 -0
  23. package/dist/lint.d.mts +537 -0
  24. package/dist/lint.d.ts +537 -0
  25. package/dist/lint.js +540 -0
  26. package/dist/lint.mjs +524 -0
  27. package/dist/mock/cli.mjs +33 -3
  28. package/dist/mock/library.js +33 -3
  29. package/dist/mock/library.mjs +33 -3
  30. package/dist/mock/msw.js +33 -3
  31. package/dist/mock/msw.mjs +33 -3
  32. package/dist/react.d.mts +10 -5
  33. package/dist/react.d.ts +10 -5
  34. package/dist/react.js +40 -35
  35. package/dist/react.mjs +14 -9
  36. package/dist/{server--RyVAfPN.d.mts → server-DRAW2OOX.d.mts} +7 -4
  37. package/dist/{server-CNyy47HL.d.ts → server-zyrpzJVn.d.ts} +7 -4
  38. package/dist/server.d.mts +2 -2
  39. package/dist/server.d.ts +2 -2
  40. package/dist/server.js +7 -7
  41. package/dist/server.mjs +2 -2
  42. package/dist/styles.css +1 -1
  43. package/dist/testing/msw.d.mts +1 -1
  44. package/dist/testing/msw.d.ts +1 -1
  45. package/dist/testing/msw.js +2 -2
  46. package/dist/testing/msw.mjs +1 -1
  47. package/dist/testing/suite.d.mts +4 -4
  48. package/dist/testing/suite.d.ts +4 -4
  49. package/dist/testing/suite.js +23 -23
  50. package/dist/testing/suite.mjs +4 -4
  51. package/dist/testing.d.mts +3 -3
  52. package/dist/testing.d.ts +3 -3
  53. package/dist/testing.js +79 -79
  54. package/dist/testing.mjs +5 -5
  55. package/package.json +10 -2
package/dist/lint.js ADDED
@@ -0,0 +1,540 @@
1
+ 'use strict';
2
+
3
+ require('./chunk-OWW5GUSB.js');
4
+ var re2js = require('re2js');
5
+
6
+ // src/lint/types.ts
7
+ var LINT_RULE_SET_SCHEMA_VERSION = 1;
8
+ var MAX_LINT_RULE_MANIFEST_BYTES = 256 * 1024;
9
+ var MAX_RULES = 64;
10
+ var MAX_ARRAY_ITEMS = 64;
11
+ var MAX_TOTAL_REGEX_PATTERNS = 64;
12
+ var MAX_TOTAL_RULE_TERMS = 512;
13
+ var MAX_PATH_SEGMENTS = 8;
14
+ var MAX_NAME_LENGTH = 160;
15
+ var MAX_MESSAGE_LENGTH = 512;
16
+ var MAX_HELP_LENGTH = 1024;
17
+ var MAX_PATTERN_LENGTH = 512;
18
+ var MAX_MODULE_LENGTH = 256;
19
+ var MAX_IDENTIFIER_LENGTH = 128;
20
+ var RULE_ID_PATTERN = /^[a-z][a-z0-9-]*\/[a-z][a-z0-9-]*$/;
21
+ var JAVASCRIPT_IDENTIFIER_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
22
+ var JSX_COMPONENT_IDENTIFIER_PATTERN = /^[A-Z][A-Za-z0-9_$]*$/;
23
+ var NUMERIC_OPERATORS = /* @__PURE__ */ new Set(["+", "-", "*", "/", "%", "**", "<", "<=", ">", ">="]);
24
+ var PRIMITIVE_KINDS = /* @__PURE__ */ new Set([
25
+ "required-result-check",
26
+ "required-wrapper-call",
27
+ "banned-import",
28
+ "banned-call-argument",
29
+ "banned-jsx-element",
30
+ "banned-classname-pattern"
31
+ ]);
32
+ function isRecord(value) {
33
+ return value !== null && typeof value === "object" && !Array.isArray(value);
34
+ }
35
+ function expectRecord(value, label) {
36
+ if (!isRecord(value)) throw new TypeError(`${label} must be an object`);
37
+ return value;
38
+ }
39
+ function expectOnlyKeys(value, label, allowed, required) {
40
+ const allowedSet = new Set(allowed);
41
+ for (const key of Object.keys(value)) {
42
+ if (!allowedSet.has(key)) throw new TypeError(`${label} has unknown property ${key}`);
43
+ }
44
+ for (const key of required) {
45
+ if (!(key in value)) throw new TypeError(`${label} is missing ${key}`);
46
+ }
47
+ }
48
+ function expectString(value, label, maxLength) {
49
+ if (typeof value !== "string" || value.length === 0 || value.length > maxLength) {
50
+ throw new TypeError(`${label} must be a non-empty string of at most ${maxLength} characters`);
51
+ }
52
+ if (value.includes("\0")) throw new TypeError(`${label} cannot contain NUL`);
53
+ return value;
54
+ }
55
+ function expectBoolean(value, label) {
56
+ if (typeof value !== "boolean") throw new TypeError(`${label} must be boolean`);
57
+ return value;
58
+ }
59
+ function expectArray(value, label, options = {}) {
60
+ if (!Array.isArray(value) || value.length > MAX_ARRAY_ITEMS) {
61
+ throw new TypeError(`${label} must be an array of at most ${MAX_ARRAY_ITEMS} items`);
62
+ }
63
+ if (options.nonEmpty && value.length === 0) throw new TypeError(`${label} cannot be empty`);
64
+ return value;
65
+ }
66
+ function expectStringArray(value, label, maxLength = MAX_IDENTIFIER_LENGTH, options = {}) {
67
+ return expectArray(value, label, options).map(
68
+ (item, index) => expectString(item, `${label}[${index}]`, maxLength)
69
+ );
70
+ }
71
+ function expectIntegerArray(value, label) {
72
+ return expectArray(value, label, { nonEmpty: true }).map((item, index) => {
73
+ if (typeof item !== "number" || !Number.isSafeInteger(item) || item < 0 || item > 32) {
74
+ throw new TypeError(`${label}[${index}] must be an integer between 0 and 32`);
75
+ }
76
+ return item;
77
+ });
78
+ }
79
+ function validateSafePattern(value, label) {
80
+ const pattern = expectString(value, label, MAX_PATTERN_LENGTH);
81
+ try {
82
+ re2js.RE2JS.compile(pattern);
83
+ } catch {
84
+ throw new TypeError(`${label} is not a valid linear-time regular expression`);
85
+ }
86
+ return pattern;
87
+ }
88
+ function expectIdentifier(value, label, pattern = JAVASCRIPT_IDENTIFIER_PATTERN) {
89
+ const identifier = expectString(value, label, MAX_IDENTIFIER_LENGTH);
90
+ if (!pattern.test(identifier)) throw new TypeError(`${label} must be a safe identifier`);
91
+ return identifier;
92
+ }
93
+ function validateImportBindings(value, label) {
94
+ for (const [index, item] of expectArray(value, label, { nonEmpty: true }).entries()) {
95
+ const binding = expectRecord(item, `${label}[${index}]`);
96
+ expectOnlyKeys(binding, `${label}[${index}]`, ["source", "imported"], ["source", "imported"]);
97
+ expectString(binding.source, `${label}[${index}].source`, MAX_MODULE_LENGTH);
98
+ expectStringArray(binding.imported, `${label}[${index}].imported`, MAX_IDENTIFIER_LENGTH, {
99
+ nonEmpty: true
100
+ });
101
+ }
102
+ }
103
+ function validateImportSources(value, label) {
104
+ for (const [index, item] of expectArray(value, label, { nonEmpty: true }).entries()) {
105
+ const source = expectRecord(item, `${label}[${index}]`);
106
+ expectOnlyKeys(source, `${label}[${index}]`, ["value", "match"], ["value", "match"]);
107
+ expectString(source.value, `${label}[${index}].value`, MAX_MODULE_LENGTH);
108
+ if (source.match !== "exact" && source.match !== "prefix") {
109
+ throw new TypeError(`${label}[${index}].match must be exact or prefix`);
110
+ }
111
+ }
112
+ }
113
+ function validatePrimitive(value, label) {
114
+ const primitive = expectRecord(value, label);
115
+ if (!PRIMITIVE_KINDS.has(primitive.kind)) {
116
+ throw new TypeError(`${label}.kind is unsupported`);
117
+ }
118
+ switch (primitive.kind) {
119
+ case "required-result-check":
120
+ expectOnlyKeys(
121
+ primitive,
122
+ label,
123
+ ["kind", "factories", "guardProperty", "valueProperty"],
124
+ ["kind", "factories", "guardProperty", "valueProperty"]
125
+ );
126
+ validateImportBindings(primitive.factories, `${label}.factories`);
127
+ expectString(primitive.guardProperty, `${label}.guardProperty`, MAX_IDENTIFIER_LENGTH);
128
+ expectString(primitive.valueProperty, `${label}.valueProperty`, MAX_IDENTIFIER_LENGTH);
129
+ break;
130
+ case "required-wrapper-call": {
131
+ expectOnlyKeys(
132
+ primitive,
133
+ label,
134
+ ["kind", "context", "activationImports", "subjectNamePattern", "wrapper", "operators"],
135
+ ["kind", "context", "activationImports", "subjectNamePattern", "wrapper"]
136
+ );
137
+ if (primitive.context !== "jsx-child" && primitive.context !== "numeric-operation") {
138
+ throw new TypeError(`${label}.context is unsupported`);
139
+ }
140
+ validateImportSources(primitive.activationImports, `${label}.activationImports`);
141
+ validateSafePattern(primitive.subjectNamePattern, `${label}.subjectNamePattern`);
142
+ const wrapper = expectRecord(primitive.wrapper, `${label}.wrapper`);
143
+ if (wrapper.syntax === "jsx") {
144
+ expectOnlyKeys(
145
+ wrapper,
146
+ `${label}.wrapper`,
147
+ ["syntax", "source", "imported", "prop"],
148
+ ["syntax", "source", "imported", "prop"]
149
+ );
150
+ if (primitive.context !== "jsx-child") {
151
+ throw new TypeError(`${label} uses a JSX wrapper outside JSX context`);
152
+ }
153
+ expectString(wrapper.source, `${label}.wrapper.source`, MAX_MODULE_LENGTH);
154
+ expectIdentifier(
155
+ wrapper.imported,
156
+ `${label}.wrapper.imported`,
157
+ JSX_COMPONENT_IDENTIFIER_PATTERN
158
+ );
159
+ expectIdentifier(wrapper.prop, `${label}.wrapper.prop`);
160
+ } else if (wrapper.syntax === "call") {
161
+ expectOnlyKeys(wrapper, `${label}.wrapper`, ["syntax", "imports"], ["syntax", "imports"]);
162
+ if (primitive.context !== "numeric-operation") {
163
+ throw new TypeError(`${label} uses a call wrapper outside numeric context`);
164
+ }
165
+ validateImportBindings(wrapper.imports, `${label}.wrapper.imports`);
166
+ } else {
167
+ throw new TypeError(`${label}.wrapper.syntax is unsupported`);
168
+ }
169
+ if (primitive.operators !== void 0) {
170
+ const operators = expectStringArray(primitive.operators, `${label}.operators`, 4, {
171
+ nonEmpty: true
172
+ });
173
+ if (operators.some((operator) => !NUMERIC_OPERATORS.has(operator))) {
174
+ throw new TypeError(`${label}.operators contains an unsupported operator`);
175
+ }
176
+ }
177
+ break;
178
+ }
179
+ case "banned-import":
180
+ expectOnlyKeys(primitive, label, ["kind", "sources"], ["kind", "sources"]);
181
+ validateImportSources(primitive.sources, `${label}.sources`);
182
+ break;
183
+ case "banned-call-argument":
184
+ expectOnlyKeys(
185
+ primitive,
186
+ label,
187
+ [
188
+ "kind",
189
+ "callees",
190
+ "globalCalleesOnly",
191
+ "argumentIndexes",
192
+ "objectPaths",
193
+ "caseInsensitive"
194
+ ],
195
+ ["kind", "callees", "argumentIndexes", "objectPaths"]
196
+ );
197
+ expectStringArray(primitive.callees, `${label}.callees`, MAX_IDENTIFIER_LENGTH, {
198
+ nonEmpty: true
199
+ });
200
+ if (primitive.globalCalleesOnly !== void 0) {
201
+ expectBoolean(primitive.globalCalleesOnly, `${label}.globalCalleesOnly`);
202
+ }
203
+ expectIntegerArray(primitive.argumentIndexes, `${label}.argumentIndexes`);
204
+ for (const [index, item] of expectArray(primitive.objectPaths, `${label}.objectPaths`, {
205
+ nonEmpty: true
206
+ }).entries()) {
207
+ const segments = expectStringArray(
208
+ item,
209
+ `${label}.objectPaths[${index}]`,
210
+ MAX_IDENTIFIER_LENGTH,
211
+ { nonEmpty: true }
212
+ );
213
+ if (segments.length > MAX_PATH_SEGMENTS) {
214
+ throw new TypeError(
215
+ `${label}.objectPaths[${index}] exceeds ${MAX_PATH_SEGMENTS} segments`
216
+ );
217
+ }
218
+ }
219
+ if (primitive.caseInsensitive !== void 0) {
220
+ expectBoolean(primitive.caseInsensitive, `${label}.caseInsensitive`);
221
+ }
222
+ break;
223
+ case "banned-jsx-element":
224
+ expectOnlyKeys(primitive, label, ["kind", "elements"], ["kind", "elements"]);
225
+ expectStringArray(primitive.elements, `${label}.elements`, MAX_IDENTIFIER_LENGTH, {
226
+ nonEmpty: true
227
+ });
228
+ break;
229
+ case "banned-classname-pattern":
230
+ expectOnlyKeys(primitive, label, ["kind", "patterns", "replacements"], ["kind", "patterns"]);
231
+ for (const [index, pattern] of expectArray(primitive.patterns, `${label}.patterns`, {
232
+ nonEmpty: true
233
+ }).entries()) {
234
+ validateSafePattern(pattern, `${label}.patterns[${index}]`);
235
+ }
236
+ if (primitive.replacements !== void 0) {
237
+ for (const [index, item] of expectArray(
238
+ primitive.replacements,
239
+ `${label}.replacements`
240
+ ).entries()) {
241
+ const replacement = expectRecord(item, `${label}.replacements[${index}]`);
242
+ expectOnlyKeys(
243
+ replacement,
244
+ `${label}.replacements[${index}]`,
245
+ ["from", "to"],
246
+ ["from", "to"]
247
+ );
248
+ expectString(replacement.from, `${label}.replacements[${index}].from`, 256);
249
+ expectString(replacement.to, `${label}.replacements[${index}].to`, 256);
250
+ }
251
+ }
252
+ break;
253
+ default:
254
+ throw new TypeError(`${label}.kind is unsupported`);
255
+ }
256
+ return primitive;
257
+ }
258
+ function validateFix(value, label, primitive) {
259
+ const fix = expectRecord(value, label);
260
+ expectOnlyKeys(fix, label, ["kind"], ["kind"]);
261
+ if (fix.kind === "wrap-jsx-expression") {
262
+ if (primitive.kind !== "required-wrapper-call" || primitive.context !== "jsx-child" || primitive.wrapper.syntax !== "jsx") {
263
+ throw new TypeError(`${label} is incompatible with its primitive`);
264
+ }
265
+ } else if (fix.kind === "replace-classname") {
266
+ if (primitive.kind !== "banned-classname-pattern") {
267
+ throw new TypeError(`${label} is incompatible with its primitive`);
268
+ }
269
+ } else if (fix.kind === "remove-object-property") {
270
+ if (primitive.kind !== "banned-call-argument") {
271
+ throw new TypeError(`${label} is incompatible with its primitive`);
272
+ }
273
+ } else {
274
+ throw new TypeError(`${label}.kind is unsupported`);
275
+ }
276
+ return fix;
277
+ }
278
+ function validatedRule(value, label) {
279
+ const rule = expectRecord(value, label);
280
+ expectOnlyKeys(
281
+ rule,
282
+ label,
283
+ ["id", "severity", "message", "help", "primitive", "fix"],
284
+ ["id", "severity", "message", "help", "primitive"]
285
+ );
286
+ const id = expectString(rule.id, `${label}.id`, MAX_IDENTIFIER_LENGTH);
287
+ if (!RULE_ID_PATTERN.test(id)) throw new TypeError(`${label}.id is invalid`);
288
+ if (rule.severity !== "error" && rule.severity !== "warning") {
289
+ throw new TypeError(`${label}.severity must be error or warning`);
290
+ }
291
+ expectString(rule.message, `${label}.message`, MAX_MESSAGE_LENGTH);
292
+ expectString(rule.help, `${label}.help`, MAX_HELP_LENGTH);
293
+ const primitive = validatePrimitive(rule.primitive, `${label}.primitive`);
294
+ if (rule.fix !== void 0) validateFix(rule.fix, `${label}.fix`, primitive);
295
+ return rule;
296
+ }
297
+ function deepFreeze(value, seen = /* @__PURE__ */ new WeakSet()) {
298
+ if (value === null || typeof value !== "object" || seen.has(value)) return value;
299
+ seen.add(value);
300
+ for (const nested of Object.values(value)) deepFreeze(nested, seen);
301
+ return Object.freeze(value);
302
+ }
303
+ function validateLintRule(value) {
304
+ return deepFreeze(validatedRule(value, "lint rule"));
305
+ }
306
+ function validateLintRuleSet(value) {
307
+ const candidate = expectRecord(value, "lint rule set");
308
+ expectOnlyKeys(
309
+ candidate,
310
+ "lint rule set",
311
+ ["schemaVersion", "name", "rules"],
312
+ ["schemaVersion", "name", "rules"]
313
+ );
314
+ if (candidate.schemaVersion !== LINT_RULE_SET_SCHEMA_VERSION) {
315
+ throw new TypeError(
316
+ `unsupported lint rule schema ${String(candidate.schemaVersion)}; expected ${LINT_RULE_SET_SCHEMA_VERSION}`
317
+ );
318
+ }
319
+ const name = expectString(candidate.name, "lint rule set.name", MAX_NAME_LENGTH);
320
+ if (!name.trim()) throw new TypeError("lint rule set.name cannot be blank");
321
+ if (!Array.isArray(candidate.rules) || candidate.rules.length > MAX_RULES) {
322
+ throw new TypeError(`lint rule set.rules must contain at most ${MAX_RULES} rules`);
323
+ }
324
+ const ids = /* @__PURE__ */ new Set();
325
+ let regexPatterns = 0;
326
+ let ruleTerms = 0;
327
+ for (const [index, value2] of candidate.rules.entries()) {
328
+ const rule = validatedRule(value2, `rules[${index}]`);
329
+ if (ids.has(rule.id)) throw new TypeError(`lint rule set contains duplicate id ${rule.id}`);
330
+ ids.add(rule.id);
331
+ const primitive = rule.primitive;
332
+ switch (primitive.kind) {
333
+ case "required-result-check":
334
+ ruleTerms += primitive.factories.length;
335
+ ruleTerms += primitive.factories.reduce((sum, factory) => sum + factory.imported.length, 0);
336
+ break;
337
+ case "required-wrapper-call":
338
+ regexPatterns += 1;
339
+ ruleTerms += primitive.activationImports.length;
340
+ if (primitive.wrapper.syntax === "call") {
341
+ ruleTerms += primitive.wrapper.imports.length;
342
+ ruleTerms += primitive.wrapper.imports.reduce(
343
+ (sum, pattern) => sum + pattern.imported.length,
344
+ 0
345
+ );
346
+ }
347
+ ruleTerms += primitive.operators?.length ?? 0;
348
+ break;
349
+ case "banned-import":
350
+ ruleTerms += primitive.sources.length;
351
+ break;
352
+ case "banned-call-argument":
353
+ ruleTerms += primitive.callees.length + primitive.argumentIndexes.length;
354
+ ruleTerms += primitive.objectPaths.reduce((sum, objectPath) => sum + objectPath.length, 0);
355
+ break;
356
+ case "banned-jsx-element":
357
+ ruleTerms += primitive.elements.length;
358
+ break;
359
+ case "banned-classname-pattern":
360
+ regexPatterns += primitive.patterns.length;
361
+ ruleTerms += (primitive.replacements?.length ?? 0) * 2;
362
+ break;
363
+ }
364
+ }
365
+ if (regexPatterns > MAX_TOTAL_REGEX_PATTERNS) {
366
+ throw new TypeError(
367
+ `lint rule set exceeds ${MAX_TOTAL_REGEX_PATTERNS} total regular expressions`
368
+ );
369
+ }
370
+ if (ruleTerms > MAX_TOTAL_RULE_TERMS) {
371
+ throw new TypeError(`lint rule set exceeds ${MAX_TOTAL_RULE_TERMS} total match terms`);
372
+ }
373
+ let serialized;
374
+ try {
375
+ serialized = JSON.stringify(candidate);
376
+ } catch {
377
+ throw new TypeError("lint rule set must be JSON-serializable data");
378
+ }
379
+ if (new TextEncoder().encode(serialized).byteLength > MAX_LINT_RULE_MANIFEST_BYTES) {
380
+ throw new TypeError(`lint rule set exceeds ${MAX_LINT_RULE_MANIFEST_BYTES} UTF-8 bytes`);
381
+ }
382
+ return deepFreeze(candidate);
383
+ }
384
+
385
+ // src/lint/define.ts
386
+ function defineLintRule(rule) {
387
+ return validateLintRule(rule);
388
+ }
389
+ function defineLintRuleSet(options) {
390
+ return validateLintRuleSet({
391
+ schemaVersion: LINT_RULE_SET_SCHEMA_VERSION,
392
+ name: options.name,
393
+ rules: [...options.rules]
394
+ });
395
+ }
396
+
397
+ // src/lint/rules.ts
398
+ var MONEY_NAME_PATTERN = "(?:^|_)(?:price|amount|subtotal|total|tax|fee|discount|cost)(?:$|_)";
399
+ var SDK_CLIENT_FACTORIES = [
400
+ { source: "@cimplify/sdk", imported: ["createCimplifyClient"] },
401
+ { source: "@cimplify/sdk/server", imported: ["getServerClient"] }
402
+ ];
403
+ var SDK_MODULES = [{ value: "@cimplify/sdk", match: "prefix" }];
404
+ var PARSE_PRICE_IMPORTS = [
405
+ { source: "@cimplify/sdk", imported: ["parsePrice"] },
406
+ { source: "@cimplify/sdk/utils", imported: ["parsePrice"] }
407
+ ];
408
+ var TAILWIND_COLOR_SCALE = "(?:slate|gray|zinc|neutral|stone|red|orange|amber|yellow|lime|green|emerald|teal|cyan|sky|blue|indigo|violet|purple|fuchsia|pink|rose)-(?:50|100|200|300|400|500|600|700|800|900|950)";
409
+ var COLOR_UTILITY = "(?:accent|bg|border|caret|decoration|divide|fill|from|outline|placeholder|ring|shadow|stroke|text|to|via)";
410
+ var checkResultOkRule = defineLintRule({
411
+ id: "sdk/check-result-ok",
412
+ severity: "error",
413
+ message: "Check `result.ok` before reading `result.value`.",
414
+ help: "Cimplify SDK calls return Result values. Handle the error branch before using the value.",
415
+ primitive: {
416
+ kind: "required-result-check",
417
+ factories: SDK_CLIENT_FACTORIES,
418
+ guardProperty: "ok",
419
+ valueProperty: "value"
420
+ }
421
+ });
422
+ var renderPriceComponentRule = defineLintRule({
423
+ id: "sdk/render-price-component",
424
+ severity: "error",
425
+ message: "Render money with the SDK `Price` component.",
426
+ help: "`Price` applies the active business currency and locale consistently.",
427
+ primitive: {
428
+ kind: "required-wrapper-call",
429
+ context: "jsx-child",
430
+ activationImports: SDK_MODULES,
431
+ subjectNamePattern: MONEY_NAME_PATTERN,
432
+ wrapper: {
433
+ syntax: "jsx",
434
+ source: "@cimplify/sdk/react",
435
+ imported: "Price",
436
+ prop: "amount"
437
+ }
438
+ },
439
+ fix: { kind: "wrap-jsx-expression" }
440
+ });
441
+ var parsePriceBeforeMathRule = defineLintRule({
442
+ id: "sdk/parse-price-before-math",
443
+ severity: "error",
444
+ message: "Call `parsePrice` before using a money value in numeric operations.",
445
+ help: "Money arrives over the wire as a decimal string; implicit coercion can produce incorrect comparisons and totals.",
446
+ primitive: {
447
+ kind: "required-wrapper-call",
448
+ context: "numeric-operation",
449
+ activationImports: SDK_MODULES,
450
+ subjectNamePattern: MONEY_NAME_PATTERN,
451
+ wrapper: { syntax: "call", imports: PARSE_PRICE_IMPORTS },
452
+ operators: ["+", "-", "*", "/", "%", "**", "<", "<=", ">", ">="]
453
+ }
454
+ });
455
+ var noReactQueryRule = defineLintRule({
456
+ id: "sdk/no-react-query",
457
+ severity: "error",
458
+ message: "Use Cimplify SDK hooks instead of React Query.",
459
+ help: "Use the SDK hooks and their provider-owned cache so cart, catalogue, and account state stay coherent.",
460
+ primitive: {
461
+ kind: "banned-import",
462
+ sources: [
463
+ { value: "react-query", match: "exact" },
464
+ { value: "@tanstack/react-query", match: "prefix" }
465
+ ]
466
+ }
467
+ });
468
+ var noCookieInCacheKeyRule = defineLintRule({
469
+ id: "sdk/no-cookie-in-cache-key",
470
+ severity: "error",
471
+ message: "Remove the Cookie header from this cacheable request.",
472
+ help: "Cookie-bearing requests bypass the shared cache by design. Keep personalized cart/account reads in a client island.",
473
+ primitive: {
474
+ kind: "banned-call-argument",
475
+ callees: ["fetch", "Request"],
476
+ globalCalleesOnly: true,
477
+ argumentIndexes: [1],
478
+ objectPaths: [["headers", "cookie"]],
479
+ caseInsensitive: true
480
+ },
481
+ fix: { kind: "remove-object-property" }
482
+ });
483
+ var noRawImgRule = defineLintRule({
484
+ id: "ui/no-raw-img",
485
+ severity: "warning",
486
+ message: "Use `next/image` instead of a raw `<img>` element.",
487
+ help: "The storefront image loader supplies responsive sizes, modern formats, and intrinsic dimensions.",
488
+ primitive: { kind: "banned-jsx-element", elements: ["img"] }
489
+ });
490
+ var themeTokensOnlyRule = defineLintRule({
491
+ id: "ui/theme-tokens-only",
492
+ severity: "warning",
493
+ message: "Use storefront theme tokens instead of hard-coded color utilities.",
494
+ help: "Define palette changes in `app/globals.css` and consume semantic utilities such as `bg-background` and `text-foreground`.",
495
+ primitive: {
496
+ kind: "banned-classname-pattern",
497
+ patterns: [
498
+ `^${COLOR_UTILITY}-${TAILWIND_COLOR_SCALE}$`,
499
+ `^${COLOR_UTILITY}-(?:black|white)$`,
500
+ `^${COLOR_UTILITY}-\\[(?:#|rgba?\\(|hsla?\\(|oklch\\(|oklab\\(|lab\\(|lch\\(|color:)`
501
+ ],
502
+ replacements: [
503
+ { from: "bg-white", to: "bg-background" },
504
+ { from: "bg-black", to: "bg-foreground" },
505
+ { from: "text-black", to: "text-foreground" },
506
+ { from: "border-black", to: "border-foreground" },
507
+ { from: "border-white", to: "border-background" }
508
+ ]
509
+ },
510
+ fix: { kind: "replace-classname" }
511
+ });
512
+ var starterLintRuleSet = defineLintRuleSet({
513
+ name: "@cimplify/sdk/starter",
514
+ rules: [
515
+ checkResultOkRule,
516
+ renderPriceComponentRule,
517
+ parsePriceBeforeMathRule,
518
+ noReactQueryRule,
519
+ noCookieInCacheKeyRule,
520
+ noRawImgRule,
521
+ themeTokensOnlyRule
522
+ ]
523
+ });
524
+ var starterLintRules = starterLintRuleSet.rules;
525
+
526
+ exports.LINT_RULE_SET_SCHEMA_VERSION = LINT_RULE_SET_SCHEMA_VERSION;
527
+ exports.MAX_LINT_RULE_MANIFEST_BYTES = MAX_LINT_RULE_MANIFEST_BYTES;
528
+ exports.checkResultOkRule = checkResultOkRule;
529
+ exports.defineLintRule = defineLintRule;
530
+ exports.defineLintRuleSet = defineLintRuleSet;
531
+ exports.noCookieInCacheKeyRule = noCookieInCacheKeyRule;
532
+ exports.noRawImgRule = noRawImgRule;
533
+ exports.noReactQueryRule = noReactQueryRule;
534
+ exports.parsePriceBeforeMathRule = parsePriceBeforeMathRule;
535
+ exports.renderPriceComponentRule = renderPriceComponentRule;
536
+ exports.starterLintRuleSet = starterLintRuleSet;
537
+ exports.starterLintRules = starterLintRules;
538
+ exports.themeTokensOnlyRule = themeTokensOnlyRule;
539
+ exports.validateLintRule = validateLintRule;
540
+ exports.validateLintRuleSet = validateLintRuleSet;