gymmonk-schema 0.3.0 → 0.3.1
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/onboarding.d.ts +60 -0
- package/dist/onboarding.d.ts.map +1 -1
- package/dist/onboarding.js +50 -0
- package/dist/onboarding.js.map +1 -1
- package/package.json +1 -1
package/dist/onboarding.d.ts
CHANGED
|
@@ -358,4 +358,64 @@ export declare const ownerOnboardingBodySchema: z.ZodObject<{
|
|
|
358
358
|
}, z.core.$strip>;
|
|
359
359
|
}, z.core.$strip>;
|
|
360
360
|
export type OwnerOnboardingBody = z.infer<typeof ownerOnboardingBodySchema>;
|
|
361
|
+
/**
|
|
362
|
+
* In-progress onboarding draft: the UI-shaped, partially-filled form the client
|
|
363
|
+
* persists so a returning user resumes with their typed data intact. Opaque to
|
|
364
|
+
* the backend by design — the client owns the form shape, and the data is
|
|
365
|
+
* re-validated strictly by the member/owner body schemas at finalize. Keys are
|
|
366
|
+
* form field names; the backend caps the stored size.
|
|
367
|
+
*/
|
|
368
|
+
export declare const onboardingDraftSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
369
|
+
export type OnboardingDraft = z.infer<typeof onboardingDraftSchema>;
|
|
370
|
+
/**
|
|
371
|
+
* The server-persisted onboarding cursor: which role the user picked, how far
|
|
372
|
+
* they reached (`step`, the 1-indexed sub-step of the current form), the gym a
|
|
373
|
+
* member chose, and the drafts. Read on app entry to resume to the exact step.
|
|
374
|
+
* `welcomed` records that the one-time welcome carousel has been seen.
|
|
375
|
+
*/
|
|
376
|
+
export declare const onboardingProgressSchema: z.ZodObject<{
|
|
377
|
+
welcomed: z.ZodBoolean;
|
|
378
|
+
role: z.ZodNullable<z.ZodEnum<{
|
|
379
|
+
owner: "owner";
|
|
380
|
+
member: "member";
|
|
381
|
+
}>>;
|
|
382
|
+
step: z.ZodNumber;
|
|
383
|
+
gymCode: z.ZodOptional<z.ZodString>;
|
|
384
|
+
memberDraft: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
385
|
+
ownerDraft: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
386
|
+
}, z.core.$strip>;
|
|
387
|
+
export type OnboardingProgress = z.infer<typeof onboardingProgressSchema>;
|
|
388
|
+
/** `PUT /onboarding/progress` body — any subset of the cursor, merged server-side. */
|
|
389
|
+
export declare const onboardingProgressUpdateSchema: z.ZodObject<{
|
|
390
|
+
welcomed: z.ZodOptional<z.ZodBoolean>;
|
|
391
|
+
role: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
392
|
+
owner: "owner";
|
|
393
|
+
member: "member";
|
|
394
|
+
}>>>;
|
|
395
|
+
step: z.ZodOptional<z.ZodNumber>;
|
|
396
|
+
gymCode: z.ZodOptional<z.ZodString>;
|
|
397
|
+
memberDraft: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
398
|
+
ownerDraft: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
399
|
+
}, z.core.$strip>;
|
|
400
|
+
export type OnboardingProgressUpdate = z.infer<typeof onboardingProgressUpdateSchema>;
|
|
401
|
+
/**
|
|
402
|
+
* `GET /onboarding/status` response: completion truth (derived from the user's
|
|
403
|
+
* domain data) plus the resume cursor. `onboarded` is authoritative — an owner
|
|
404
|
+
* with an organisation, or a member with a profile, is onboarded regardless of
|
|
405
|
+
* the cursor.
|
|
406
|
+
*/
|
|
407
|
+
export declare const onboardingStatusSchema: z.ZodObject<{
|
|
408
|
+
onboarded: z.ZodBoolean;
|
|
409
|
+
role: z.ZodNullable<z.ZodEnum<{
|
|
410
|
+
owner: "owner";
|
|
411
|
+
member: "member";
|
|
412
|
+
}>>;
|
|
413
|
+
organisationId: z.ZodOptional<z.ZodString>;
|
|
414
|
+
welcomed: z.ZodBoolean;
|
|
415
|
+
step: z.ZodNumber;
|
|
416
|
+
gymCode: z.ZodOptional<z.ZodString>;
|
|
417
|
+
memberDraft: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
418
|
+
ownerDraft: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
419
|
+
}, z.core.$strip>;
|
|
420
|
+
export type OnboardingStatus = z.infer<typeof onboardingStatusSchema>;
|
|
361
421
|
//# sourceMappingURL=onboarding.d.ts.map
|
package/dist/onboarding.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../src/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,oBAAoB;;;EAA8B,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBnC,CAAC;AACL,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAa5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,mEAAmE;AACnE,eAAO,MAAM,6BAA6B;;;iBAGxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC"}
|
|
1
|
+
{"version":3,"file":"onboarding.d.ts","sourceRoot":"","sources":["../src/onboarding.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAcxB,eAAO,MAAM,oBAAoB;;;EAA8B,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAIlE,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAwBnC,CAAC;AACL,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAI9E,2EAA2E;AAC3E,eAAO,MAAM,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAa5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,mEAAmE;AACnE,eAAO,MAAM,6BAA6B;;;iBAGxC,CAAC;AACH,MAAM,MAAM,uBAAuB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,6BAA6B,CAAC,CAAC;AAEpF,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAKpC,CAAC;AACH,MAAM,MAAM,mBAAmB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAI5E;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,wCAAoC,CAAC;AACvE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;;;iBAOnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E,sFAAsF;AACtF,eAAO,MAAM,8BAA8B;;;;;;;;;;iBAS/B,CAAC;AACb,MAAM,MAAM,wBAAwB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,8BAA8B,CAAC,CAAC;AAEtF;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB;;;;;;;;;;;;iBASjC,CAAC;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAC"}
|
package/dist/onboarding.js
CHANGED
|
@@ -71,4 +71,54 @@ export const ownerOnboardingBodySchema = z.object({
|
|
|
71
71
|
center: createCenterBodySchema,
|
|
72
72
|
subscription: onboardingPlanSelectionSchema,
|
|
73
73
|
});
|
|
74
|
+
// ─── Onboarding progress & resume ─────────────────────────────────────────────
|
|
75
|
+
/**
|
|
76
|
+
* In-progress onboarding draft: the UI-shaped, partially-filled form the client
|
|
77
|
+
* persists so a returning user resumes with their typed data intact. Opaque to
|
|
78
|
+
* the backend by design — the client owns the form shape, and the data is
|
|
79
|
+
* re-validated strictly by the member/owner body schemas at finalize. Keys are
|
|
80
|
+
* form field names; the backend caps the stored size.
|
|
81
|
+
*/
|
|
82
|
+
export const onboardingDraftSchema = z.record(z.string(), z.unknown());
|
|
83
|
+
/**
|
|
84
|
+
* The server-persisted onboarding cursor: which role the user picked, how far
|
|
85
|
+
* they reached (`step`, the 1-indexed sub-step of the current form), the gym a
|
|
86
|
+
* member chose, and the drafts. Read on app entry to resume to the exact step.
|
|
87
|
+
* `welcomed` records that the one-time welcome carousel has been seen.
|
|
88
|
+
*/
|
|
89
|
+
export const onboardingProgressSchema = z.object({
|
|
90
|
+
welcomed: z.boolean(),
|
|
91
|
+
role: onboardingRoleSchema.nullable(),
|
|
92
|
+
step: z.number().int().min(0).max(20),
|
|
93
|
+
gymCode: gymCodeSchema.optional(),
|
|
94
|
+
memberDraft: onboardingDraftSchema.optional(),
|
|
95
|
+
ownerDraft: onboardingDraftSchema.optional(),
|
|
96
|
+
});
|
|
97
|
+
/** `PUT /onboarding/progress` body — any subset of the cursor, merged server-side. */
|
|
98
|
+
export const onboardingProgressUpdateSchema = z
|
|
99
|
+
.object({
|
|
100
|
+
welcomed: z.boolean(),
|
|
101
|
+
role: onboardingRoleSchema.nullable(),
|
|
102
|
+
step: z.number().int().min(0).max(20),
|
|
103
|
+
gymCode: gymCodeSchema,
|
|
104
|
+
memberDraft: onboardingDraftSchema,
|
|
105
|
+
ownerDraft: onboardingDraftSchema,
|
|
106
|
+
})
|
|
107
|
+
.partial();
|
|
108
|
+
/**
|
|
109
|
+
* `GET /onboarding/status` response: completion truth (derived from the user's
|
|
110
|
+
* domain data) plus the resume cursor. `onboarded` is authoritative — an owner
|
|
111
|
+
* with an organisation, or a member with a profile, is onboarded regardless of
|
|
112
|
+
* the cursor.
|
|
113
|
+
*/
|
|
114
|
+
export const onboardingStatusSchema = z.object({
|
|
115
|
+
onboarded: z.boolean(),
|
|
116
|
+
role: onboardingRoleSchema.nullable(),
|
|
117
|
+
organisationId: z.string().optional(),
|
|
118
|
+
welcomed: z.boolean(),
|
|
119
|
+
step: z.number().int().min(0),
|
|
120
|
+
gymCode: z.string().optional(),
|
|
121
|
+
memberDraft: onboardingDraftSchema.optional(),
|
|
122
|
+
ownerDraft: onboardingDraftSchema.optional(),
|
|
123
|
+
});
|
|
74
124
|
//# sourceMappingURL=onboarding.js.map
|
package/dist/onboarding.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../src/onboarding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Onboarding submit payloads\n * ============================================\n * The end-of-flow POST bodies. The frontend forms stay flat (three-part DOB,\n * etc.); at submit they map to these structured payloads, which compose the\n * canonical create schemas so the backend can fan out to the right collections.\n *\n * member → member-profile + a pending membership (join a gym by code)\n * owner → organisation + first center + SaaS subscription selection\n *\n * @module gymmonk-schema/onboarding\n */\n\nimport { z } from 'zod';\nimport { createCenterBodySchema, gymCodeSchema } from './center.js';\nimport {\n isoDateSchema,\n optionalEmailSchema,\n optionalTrimmedString,\n phoneSchema,\n} from './common.js';\nimport { bodyMetricsSchema, emergencyContactSchema } from './member-profile.js';\nimport { createOrganisationBodySchema } from './organisation.js';\nimport { addressSchema, bloodGroupSchema, genderSchema, socialLinksSchema } from './shared.js';\n\n// ─── Role ────────────────────────────────────────────────────────────────────\n\nexport const onboardingRoleSchema = z.enum(['owner', 'member']);\nexport type OnboardingRole = z.infer<typeof onboardingRoleSchema>;\n\n// ─── Member onboarding ───────────────────────────────────────────────────────\n\nexport const memberOnboardingBodySchema = z\n .object({\n /** The gym code the member picked at the \"find your gym\" step. */\n gymCode: gymCodeSchema,\n firstName: z.string().trim().min(1, 'First name is required').max(80),\n lastName: optionalTrimmedString(80),\n gender: genderSchema,\n dob: isoDateSchema,\n phone: phoneSchema,\n body: bodyMetricsSchema,\n emergencyContact: emergencyContactSchema,\n bloodGroup: bloodGroupSchema,\n })\n .refine((v) => v.body.heightCm != null && v.body.weightKg != null, {\n message: 'Height and weight are required',\n path: ['body'],\n })\n .refine((v) => v.body.neckCm != null && v.body.waistCm != null, {\n message: 'Neck and waist are required',\n path: ['body'],\n })\n .refine((v) => v.gender !== 'female' || v.body.hipsCm != null, {\n message: 'Hips measurement is required',\n path: ['body', 'hipsCm'],\n });\nexport type MemberOnboardingBody = z.infer<typeof memberOnboardingBodySchema>;\n\n// ─── Owner onboarding ────────────────────────────────────────────────────────\n\n/** The owner's personal basics captured before the organisation/center. */\nexport const ownerBasicsSchema = z.object({\n firstName: z.string().trim().min(1, 'First name is required').max(80),\n lastName: optionalTrimmedString(80),\n gender: genderSchema,\n dob: isoDateSchema.optional(),\n phone: phoneSchema,\n altEmail: optionalEmailSchema,\n website: optionalTrimmedString(200),\n socials: socialLinksSchema,\n /** The owner's personal contact address (step-2 of owner onboarding). */\n address: addressSchema.optional(),\n /** Uploaded profile photo → stored on the shared `User.avatar`. */\n avatarUrl: optionalTrimmedString(2000),\n});\nexport type OwnerBasics = z.infer<typeof ownerBasicsSchema>;\n\n/** The SaaS plan an owner selects at the final onboarding step. */\nexport const onboardingPlanSelectionSchema = z.object({\n planId: z.string().trim().min(1),\n tenureId: z.string().trim().min(1).nullable(),\n});\nexport type OnboardingPlanSelection = z.infer<typeof onboardingPlanSelectionSchema>;\n\nexport const ownerOnboardingBodySchema = z.object({\n owner: ownerBasicsSchema,\n organisation: createOrganisationBodySchema,\n center: createCenterBodySchema,\n subscription: onboardingPlanSelectionSchema,\n});\nexport type OwnerOnboardingBody = z.infer<typeof ownerOnboardingBodySchema>;\n"]}
|
|
1
|
+
{"version":3,"file":"onboarding.js","sourceRoot":"","sources":["../src/onboarding.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * gymmonk-schema — Onboarding submit payloads\n * ============================================\n * The end-of-flow POST bodies. The frontend forms stay flat (three-part DOB,\n * etc.); at submit they map to these structured payloads, which compose the\n * canonical create schemas so the backend can fan out to the right collections.\n *\n * member → member-profile + a pending membership (join a gym by code)\n * owner → organisation + first center + SaaS subscription selection\n *\n * @module gymmonk-schema/onboarding\n */\n\nimport { z } from 'zod';\nimport { createCenterBodySchema, gymCodeSchema } from './center.js';\nimport {\n isoDateSchema,\n optionalEmailSchema,\n optionalTrimmedString,\n phoneSchema,\n} from './common.js';\nimport { bodyMetricsSchema, emergencyContactSchema } from './member-profile.js';\nimport { createOrganisationBodySchema } from './organisation.js';\nimport { addressSchema, bloodGroupSchema, genderSchema, socialLinksSchema } from './shared.js';\n\n// ─── Role ────────────────────────────────────────────────────────────────────\n\nexport const onboardingRoleSchema = z.enum(['owner', 'member']);\nexport type OnboardingRole = z.infer<typeof onboardingRoleSchema>;\n\n// ─── Member onboarding ───────────────────────────────────────────────────────\n\nexport const memberOnboardingBodySchema = z\n .object({\n /** The gym code the member picked at the \"find your gym\" step. */\n gymCode: gymCodeSchema,\n firstName: z.string().trim().min(1, 'First name is required').max(80),\n lastName: optionalTrimmedString(80),\n gender: genderSchema,\n dob: isoDateSchema,\n phone: phoneSchema,\n body: bodyMetricsSchema,\n emergencyContact: emergencyContactSchema,\n bloodGroup: bloodGroupSchema,\n })\n .refine((v) => v.body.heightCm != null && v.body.weightKg != null, {\n message: 'Height and weight are required',\n path: ['body'],\n })\n .refine((v) => v.body.neckCm != null && v.body.waistCm != null, {\n message: 'Neck and waist are required',\n path: ['body'],\n })\n .refine((v) => v.gender !== 'female' || v.body.hipsCm != null, {\n message: 'Hips measurement is required',\n path: ['body', 'hipsCm'],\n });\nexport type MemberOnboardingBody = z.infer<typeof memberOnboardingBodySchema>;\n\n// ─── Owner onboarding ────────────────────────────────────────────────────────\n\n/** The owner's personal basics captured before the organisation/center. */\nexport const ownerBasicsSchema = z.object({\n firstName: z.string().trim().min(1, 'First name is required').max(80),\n lastName: optionalTrimmedString(80),\n gender: genderSchema,\n dob: isoDateSchema.optional(),\n phone: phoneSchema,\n altEmail: optionalEmailSchema,\n website: optionalTrimmedString(200),\n socials: socialLinksSchema,\n /** The owner's personal contact address (step-2 of owner onboarding). */\n address: addressSchema.optional(),\n /** Uploaded profile photo → stored on the shared `User.avatar`. */\n avatarUrl: optionalTrimmedString(2000),\n});\nexport type OwnerBasics = z.infer<typeof ownerBasicsSchema>;\n\n/** The SaaS plan an owner selects at the final onboarding step. */\nexport const onboardingPlanSelectionSchema = z.object({\n planId: z.string().trim().min(1),\n tenureId: z.string().trim().min(1).nullable(),\n});\nexport type OnboardingPlanSelection = z.infer<typeof onboardingPlanSelectionSchema>;\n\nexport const ownerOnboardingBodySchema = z.object({\n owner: ownerBasicsSchema,\n organisation: createOrganisationBodySchema,\n center: createCenterBodySchema,\n subscription: onboardingPlanSelectionSchema,\n});\nexport type OwnerOnboardingBody = z.infer<typeof ownerOnboardingBodySchema>;\n\n// ─── Onboarding progress & resume ─────────────────────────────────────────────\n\n/**\n * In-progress onboarding draft: the UI-shaped, partially-filled form the client\n * persists so a returning user resumes with their typed data intact. Opaque to\n * the backend by design — the client owns the form shape, and the data is\n * re-validated strictly by the member/owner body schemas at finalize. Keys are\n * form field names; the backend caps the stored size.\n */\nexport const onboardingDraftSchema = z.record(z.string(), z.unknown());\nexport type OnboardingDraft = z.infer<typeof onboardingDraftSchema>;\n\n/**\n * The server-persisted onboarding cursor: which role the user picked, how far\n * they reached (`step`, the 1-indexed sub-step of the current form), the gym a\n * member chose, and the drafts. Read on app entry to resume to the exact step.\n * `welcomed` records that the one-time welcome carousel has been seen.\n */\nexport const onboardingProgressSchema = z.object({\n welcomed: z.boolean(),\n role: onboardingRoleSchema.nullable(),\n step: z.number().int().min(0).max(20),\n gymCode: gymCodeSchema.optional(),\n memberDraft: onboardingDraftSchema.optional(),\n ownerDraft: onboardingDraftSchema.optional(),\n});\nexport type OnboardingProgress = z.infer<typeof onboardingProgressSchema>;\n\n/** `PUT /onboarding/progress` body — any subset of the cursor, merged server-side. */\nexport const onboardingProgressUpdateSchema = z\n .object({\n welcomed: z.boolean(),\n role: onboardingRoleSchema.nullable(),\n step: z.number().int().min(0).max(20),\n gymCode: gymCodeSchema,\n memberDraft: onboardingDraftSchema,\n ownerDraft: onboardingDraftSchema,\n })\n .partial();\nexport type OnboardingProgressUpdate = z.infer<typeof onboardingProgressUpdateSchema>;\n\n/**\n * `GET /onboarding/status` response: completion truth (derived from the user's\n * domain data) plus the resume cursor. `onboarded` is authoritative — an owner\n * with an organisation, or a member with a profile, is onboarded regardless of\n * the cursor.\n */\nexport const onboardingStatusSchema = z.object({\n onboarded: z.boolean(),\n role: onboardingRoleSchema.nullable(),\n organisationId: z.string().optional(),\n welcomed: z.boolean(),\n step: z.number().int().min(0),\n gymCode: z.string().optional(),\n memberDraft: onboardingDraftSchema.optional(),\n ownerDraft: onboardingDraftSchema.optional(),\n});\nexport type OnboardingStatus = z.infer<typeof onboardingStatusSchema>;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gymmonk-schema",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Shared Zod schemas, enums and domain types for GymMonk (fitness SaaS) — single source of truth (SSOT) consumed by gymmonk-backend and gymmonk-web-client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|