@proveanything/smartlinks 2.0.50 → 2.0.52
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/api/sequence.d.ts +3 -0
- package/dist/api/sequence.js +3 -0
- package/dist/docs/API_SUMMARY.md +83 -3
- package/dist/docs/comms.md +17 -1
- package/dist/docs/containers.md +33 -1
- package/dist/docs/overview.md +1 -1
- package/dist/docs/sequences.md +6 -0
- package/dist/docs/server-functions.md +86 -3
- package/dist/openapi.yaml +106 -1
- package/dist/testing/index.d.ts +38 -0
- package/dist/testing/index.js +140 -7
- package/dist/types/appManifest.d.ts +89 -2
- package/dist/types/comms.d.ts +22 -0
- package/docs/API_SUMMARY.md +83 -3
- package/docs/comms.md +17 -1
- package/docs/containers.md +33 -1
- package/docs/overview.md +1 -1
- package/docs/sequences.md +6 -0
- package/docs/server-functions.md +86 -3
- package/openapi.yaml +106 -1
- package/package.json +1 -1
- package/scripts/doctor.mjs +59 -4
package/openapi.yaml
CHANGED
|
@@ -19218,16 +19218,113 @@ components:
|
|
|
19218
19218
|
AppDataHandle:
|
|
19219
19219
|
type: object
|
|
19220
19220
|
properties: {}
|
|
19221
|
+
AppRecordClaimResult:
|
|
19222
|
+
type: object
|
|
19223
|
+
properties:
|
|
19224
|
+
record:
|
|
19225
|
+
type: object
|
|
19226
|
+
additionalProperties: true
|
|
19227
|
+
created:
|
|
19228
|
+
type: boolean
|
|
19229
|
+
conflict:
|
|
19230
|
+
type: string
|
|
19231
|
+
enum:
|
|
19232
|
+
- singleton
|
|
19233
|
+
- customId
|
|
19234
|
+
required:
|
|
19235
|
+
- record
|
|
19236
|
+
- created
|
|
19237
|
+
ServerFunctionCounters:
|
|
19238
|
+
type: object
|
|
19239
|
+
properties: {}
|
|
19240
|
+
ResolvedTag:
|
|
19241
|
+
type: object
|
|
19242
|
+
properties:
|
|
19243
|
+
id:
|
|
19244
|
+
type: string
|
|
19245
|
+
claimSetId:
|
|
19246
|
+
type: string
|
|
19247
|
+
code:
|
|
19248
|
+
type: string
|
|
19249
|
+
required:
|
|
19250
|
+
- id
|
|
19251
|
+
- claimSetId
|
|
19252
|
+
- code
|
|
19253
|
+
ContactUpsertDetails:
|
|
19254
|
+
type: object
|
|
19255
|
+
properties:
|
|
19256
|
+
email:
|
|
19257
|
+
type: string
|
|
19258
|
+
phone:
|
|
19259
|
+
type: string
|
|
19260
|
+
firstName:
|
|
19261
|
+
type: string
|
|
19262
|
+
lastName:
|
|
19263
|
+
type: string
|
|
19264
|
+
displayName:
|
|
19265
|
+
type: string
|
|
19266
|
+
company:
|
|
19267
|
+
type: string
|
|
19268
|
+
locale:
|
|
19269
|
+
type: string
|
|
19270
|
+
timezone:
|
|
19271
|
+
type: string
|
|
19272
|
+
customFields:
|
|
19273
|
+
type: object
|
|
19274
|
+
additionalProperties:
|
|
19275
|
+
type: object
|
|
19276
|
+
additionalProperties: true
|
|
19277
|
+
ServerFunctionInteractionEvent:
|
|
19278
|
+
type: object
|
|
19279
|
+
properties:
|
|
19280
|
+
interactionId:
|
|
19281
|
+
type: string
|
|
19282
|
+
contactId:
|
|
19283
|
+
type: string
|
|
19284
|
+
outcome:
|
|
19285
|
+
type: string
|
|
19286
|
+
metadata:
|
|
19287
|
+
type: object
|
|
19288
|
+
additionalProperties: true
|
|
19289
|
+
productId:
|
|
19290
|
+
type: string
|
|
19291
|
+
proofId:
|
|
19292
|
+
type: string
|
|
19293
|
+
variantId:
|
|
19294
|
+
type: string
|
|
19295
|
+
batchId:
|
|
19296
|
+
type: string
|
|
19297
|
+
eventType:
|
|
19298
|
+
type: string
|
|
19299
|
+
required:
|
|
19300
|
+
- interactionId
|
|
19221
19301
|
ServerFunctionSl:
|
|
19222
19302
|
type: object
|
|
19223
19303
|
properties:
|
|
19224
|
-
appRecords:
|
|
19304
|
+
appRecords:
|
|
19305
|
+
type: object
|
|
19306
|
+
additionalProperties: true
|
|
19307
|
+
counters:
|
|
19308
|
+
$ref: "#/components/schemas/ServerFunctionCounters"
|
|
19309
|
+
tags:
|
|
19310
|
+
type: object
|
|
19311
|
+
additionalProperties: true
|
|
19312
|
+
contacts:
|
|
19313
|
+
type: object
|
|
19314
|
+
additionalProperties: true
|
|
19315
|
+
interactions:
|
|
19316
|
+
type: object
|
|
19317
|
+
additionalProperties: true
|
|
19225
19318
|
products: {}
|
|
19226
19319
|
attestations: {}
|
|
19227
19320
|
appData:
|
|
19228
19321
|
$ref: "#/components/schemas/AppDataHandle"
|
|
19229
19322
|
required:
|
|
19230
19323
|
- appRecords
|
|
19324
|
+
- counters
|
|
19325
|
+
- tags
|
|
19326
|
+
- contacts
|
|
19327
|
+
- interactions
|
|
19231
19328
|
- products
|
|
19232
19329
|
- attestations
|
|
19233
19330
|
- appData
|
|
@@ -23658,14 +23755,22 @@ components:
|
|
|
23658
23755
|
properties:
|
|
23659
23756
|
email:
|
|
23660
23757
|
type: string
|
|
23758
|
+
templateId:
|
|
23759
|
+
type: string
|
|
23661
23760
|
topics:
|
|
23662
23761
|
type: array
|
|
23663
23762
|
items:
|
|
23664
23763
|
type: string
|
|
23665
23764
|
firstName:
|
|
23666
23765
|
type: string
|
|
23766
|
+
fields:
|
|
23767
|
+
type: object
|
|
23768
|
+
additionalProperties: true
|
|
23769
|
+
appId:
|
|
23770
|
+
type: string
|
|
23667
23771
|
required:
|
|
23668
23772
|
- email
|
|
23773
|
+
- templateId
|
|
23669
23774
|
CommsSignupResponse:
|
|
23670
23775
|
type: object
|
|
23671
23776
|
properties:
|
package/package.json
CHANGED
package/scripts/doctor.mjs
CHANGED
|
@@ -168,16 +168,26 @@ if (meta.cssBaseline) {
|
|
|
168
168
|
for (const c of ['sl-mobile-admin']) baseSet.add(c);
|
|
169
169
|
// Class usage lives in compiled markup strings — present in every bundle regardless
|
|
170
170
|
// of module format, so scan both umd + esm across all surfaces.
|
|
171
|
+
// `sl-…` NOT preceded by a word char or hyphen: a class name, never a CSS custom property
|
|
172
|
+
// (`var(--sl-color-accent)`, `--sl-widget-accent`) — those are theme tokens, not classes.
|
|
173
|
+
// Classes the app defines itself (`.sl-foo {…}` in its own CSS) aren't missing either.
|
|
171
174
|
const used = new Set();
|
|
175
|
+
const defined = new Set();
|
|
172
176
|
for (const [, block] of surfaces) {
|
|
173
|
-
for (const p of [block?.files?.js?.umd, block?.files?.js?.esm]) {
|
|
174
|
-
if (!p) continue;
|
|
177
|
+
for (const p of [block?.files?.js?.umd, block?.files?.js?.esm, block?.files?.css]) {
|
|
178
|
+
if (!p || typeof p !== 'string') continue;
|
|
175
179
|
const bp = resolveBundle(p);
|
|
176
180
|
if (!bp) continue;
|
|
177
|
-
|
|
181
|
+
const text = readFileSync(bp, 'utf8');
|
|
182
|
+
for (const m of text.matchAll(/(?<![\w-])sl-[a-z0-9-]+/g)) used.add(m[0]);
|
|
183
|
+
for (const m of text.matchAll(/\.(sl-[a-z0-9-]+)/g)) defined.add(m[1]);
|
|
178
184
|
}
|
|
179
185
|
}
|
|
180
|
-
const
|
|
186
|
+
const ownSl = [...defined].filter((c) => !baseSet.has(c)).sort();
|
|
187
|
+
if (ownSl.length) {
|
|
188
|
+
warnings.push(`the app's own classes use the platform's sl- prefix: ${ownSl.join(', ')} — rename them (e.g. drop the "sl-") so they can't collide with a future baseline class.`);
|
|
189
|
+
}
|
|
190
|
+
const unknown = [...used].filter((c) => !baseSet.has(c) && !defined.has(c)).sort();
|
|
181
191
|
if (used.size === 0) {
|
|
182
192
|
console.log(`${DIM}cssBaseline (${baseline.version}) — declared; no sl-* classes found in the bundles.${RESET}`);
|
|
183
193
|
} else if (unknown.length === 0) {
|
|
@@ -238,6 +248,51 @@ if (meta.respectsHostTheme) {
|
|
|
238
248
|
}
|
|
239
249
|
}
|
|
240
250
|
|
|
251
|
+
// ---- containers: a router of their own must be isolated from the host's ------------------------
|
|
252
|
+
// Since R5, react-router-dom is SHARED with the host, so a container that wraps itself in a
|
|
253
|
+
// MemoryRouter/HashRouter/BrowserRouter inside the host's router throws "You cannot render a <Router>
|
|
254
|
+
// inside another <Router>" — unless it resets the parent's router context first (docs/containers.md →
|
|
255
|
+
// "Pages that read their context from the URL"). Heuristic on the built bundle names; WARN-only.
|
|
256
|
+
{
|
|
257
|
+
const block = manifest.containers;
|
|
258
|
+
for (const p of [block?.files?.js?.esm, block?.files?.js?.umd]) {
|
|
259
|
+
if (!p) continue;
|
|
260
|
+
const bp = resolveBundle(p);
|
|
261
|
+
if (!bp) continue;
|
|
262
|
+
const text = readFileSync(bp, 'utf8');
|
|
263
|
+
const routers = ['MemoryRouter', 'HashRouter', 'BrowserRouter'].filter((r) => new RegExp(`\\b${r}\\b`).test(text));
|
|
264
|
+
if (!routers.length) { console.log(`${GREEN}✓${RESET} containers ${DIM}— no router of their own (the host's is used)${RESET}`); break; }
|
|
265
|
+
if (/UNSAFE_LocationContext/.test(text)) { console.log(`${GREEN}✓${RESET} containers ${DIM}— own ${routers.join('/')} isolated from the host's router${RESET}`); break; }
|
|
266
|
+
console.log(`${YELLOW}⚠${RESET} containers — ${routers.join('/')} without isolating it from the host's router`);
|
|
267
|
+
warnings.push(`containers bundle renders its own ${routers.join('/')} but never resets the host's router context — inside an R5 host that throws "You cannot render a <Router> inside another <Router>". Wrap it in UNSAFE_LocationContext.Provider + UNSAFE_NavigationContext.Provider value={null} (docs/containers.md), or drop the router and use the host's.`);
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// ---- package.json scripts point at files that exist ------------------------------------------
|
|
273
|
+
// An upgrade that copies a script LINE but not the script FILE breaks every build at that step
|
|
274
|
+
// (e.g. `postbuild: node scripts/smartlinks-deploy.mjs` with no scripts/smartlinks-deploy.mjs).
|
|
275
|
+
// WARN — the doctor runs inside the build, and a skipped hook (Forge builds skip pre/post) is harmless.
|
|
276
|
+
try {
|
|
277
|
+
const pkg = JSON.parse(readFileSync(join(appDir, 'package.json'), 'utf8'));
|
|
278
|
+
const missing = [];
|
|
279
|
+
for (const [name, cmd] of Object.entries(pkg.scripts || {})) {
|
|
280
|
+
if (typeof cmd !== 'string') continue;
|
|
281
|
+
for (const m of cmd.matchAll(/(?:^|[;&|]\s*|\s)(?:node|tsx|ts-node|bash|sh)\s+(?:-{1,2}[\w-]+(?:=\S+)?\s+)*((?:\.{1,2}\/)?[\w./-]+\.(?:mjs|cjs|js|ts|sh))\b/g)) {
|
|
282
|
+
if (!existsSync(join(appDir, m[1]))) missing.push(`"${name}" runs ${m[1]}`);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (missing.length) {
|
|
286
|
+
console.log(`${YELLOW}⚠${RESET} package.json scripts — ${missing.length} point${missing.length === 1 ? 's' : ''} at a file that doesn't exist:`);
|
|
287
|
+
for (const x of missing) console.log(` ${YELLOW}${x}${RESET}`);
|
|
288
|
+
warnings.push(`package.json ${missing.join('; ')} — but the file is missing. Add the file, or remove the script (a pre/post hook like postbuild fails every \`npm run build\` without it).`);
|
|
289
|
+
} else {
|
|
290
|
+
console.log(`${GREEN}✓${RESET} package.json scripts ${DIM}— every script file they run exists${RESET}`);
|
|
291
|
+
}
|
|
292
|
+
} catch {
|
|
293
|
+
/* no package.json — not an npm app */
|
|
294
|
+
}
|
|
295
|
+
|
|
241
296
|
console.log('');
|
|
242
297
|
for (const w of warnings) console.log(`${YELLOW}⚠ ${w}${RESET}`);
|
|
243
298
|
|