founder-schema 0.18.0 → 0.19.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/README.md +64 -3
- package/dist/core/common.d.ts +7 -13
- package/dist/core/common.d.ts.map +1 -1
- package/dist/core/common.js +7 -11
- package/dist/core/common.js.map +1 -1
- package/dist/core/limits.d.ts +25 -0
- package/dist/core/limits.d.ts.map +1 -1
- package/dist/core/limits.js +25 -0
- package/dist/core/limits.js.map +1 -1
- package/dist/core/validation.d.ts +13 -0
- package/dist/core/validation.d.ts.map +1 -1
- package/dist/core/validation.js +13 -0
- package/dist/core/validation.js.map +1 -1
- package/dist/domains/location/areas.d.ts +331 -0
- package/dist/domains/location/areas.d.ts.map +1 -0
- package/dist/domains/location/areas.js +238 -0
- package/dist/domains/location/areas.js.map +1 -0
- package/dist/domains/location/india.d.ts +31 -123
- package/dist/domains/location/india.d.ts.map +1 -1
- package/dist/domains/location/india.js +98 -64
- package/dist/domains/location/india.js.map +1 -1
- package/dist/domains/onboarding/onboarding-answers.d.ts +9 -12
- package/dist/domains/onboarding/onboarding-answers.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding-answers.js +11 -18
- package/dist/domains/onboarding/onboarding-answers.js.map +1 -1
- package/dist/domains/onboarding/onboarding.d.ts +110 -88
- package/dist/domains/onboarding/onboarding.d.ts.map +1 -1
- package/dist/domains/onboarding/onboarding.js +14 -19
- package/dist/domains/onboarding/onboarding.js.map +1 -1
- package/dist/domains/profile/founder-profile.d.ts +57 -41
- package/dist/domains/profile/founder-profile.d.ts.map +1 -1
- package/dist/domains/profile/founder-profile.js +12 -4
- package/dist/domains/profile/founder-profile.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/core/validation.js
CHANGED
|
@@ -143,6 +143,19 @@ export const VALIDATION_MESSAGE = {
|
|
|
143
143
|
* Its own key, so the refusal does not carry all 36 names as its message.
|
|
144
144
|
*/
|
|
145
145
|
stateRequired: 'stateRequired',
|
|
146
|
+
/** A location picked without its district (0.19.0: state, district, then locality). */
|
|
147
|
+
districtRequired: 'districtRequired',
|
|
148
|
+
/**
|
|
149
|
+
* A pick that does not say its locality: a locality's id, or `null` for the
|
|
150
|
+
* whole district (0.19.0). Worded as the choice it is.
|
|
151
|
+
*/
|
|
152
|
+
localityRequired: 'localityRequired',
|
|
153
|
+
/**
|
|
154
|
+
* An area id the tree does not have, or not where the pick puts it (a
|
|
155
|
+
* district outside the chosen state, a locality outside the district):
|
|
156
|
+
* "choose it again" (0.19.0).
|
|
157
|
+
*/
|
|
158
|
+
areaNotListed: 'areaNotListed',
|
|
146
159
|
};
|
|
147
160
|
/**
|
|
148
161
|
* Which part of the request an issue is about.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — How a validation failure is described, on both sides\n *\n * TWO RULES, and they are what let the web client show any error, its own or\n * the server's, on the right field in the member's language:\n *\n * 1. A CUSTOM MESSAGE IS A KEY, NEVER A SENTENCE. Where a schema needs its own\n * message (a refine, a regex), the message is one of `VALIDATION_MESSAGE`,\n * such as `phoneInvalid`. The client turns the key into text in English or\n * Hindi. Before 0.2.0 these were English sentences, so a Hindi screen showed\n * an English error, and a client that wanted to translate one had to match\n * on the wording.\n *\n * Plain bounds carry NO custom message. `.min(1)` and `.max(80)` produce\n * Zod's own `too_small` / `too_big` issues, which already say which bound\n * and what it was (`minimum`, `maximum`, `origin`), and the client words\n * them from those. A hand-written \"at most 80 characters\" would only\n * restate the number in one language.\n *\n * 2. THE SERVER SENDS EVERY ISSUE, IN THIS SHAPE. A 400 answers with\n * `error.details.issues`, built by `toValidationIssues`, so the client can\n * put each one under its field. Until 0.2.0 the backend sent only the\n * first issue's message, with no path at all.\n *\n * ⚠️ `toValidationIssues` COPIES A WHITELIST OF FIELDS, it never spreads an\n * issue. Zod can carry the rejected `input` on an issue, and these bodies hold a\n * date of birth and a phone number. Echoing them into an error response sends\n * them back to the client, into logs and into any proxy in between. A test\n * proves `input` never survives.\n *\n * @module founder-schema/core/validation\n */\n\nimport { z } from 'zod';\n\n/**\n * Every custom message a schema in this package can produce. Each is a\n * translation key the clients define in every language they ship.\n *\n * ⚠️ Append only, and add the translation in the same change. Renaming one\n * shows the raw key to every member until each client ships the new name.\n */\nexport const VALIDATION_MESSAGE = {\n /** Not a 24-hex Mongo id. */\n invalidId: 'invalidId',\n /** Handle: wrong characters, or a dot in the wrong place. */\n usernameInvalid: 'usernameInvalid',\n /** Not a 10-digit Indian mobile number. */\n phoneInvalid: 'phoneInvalid',\n /** Not a `YYYY-MM-DD` date. */\n dateInvalid: 'dateInvalid',\n /** A date that does not exist, such as 30 February. */\n dobInvalid: 'dobInvalid',\n /** Under the minimum age. */\n dobUnderAge: 'dobUnderAge',\n /** Over the sanity ceiling: almost always a mistyped year. */\n dobTooOld: 'dobTooOld',\n /** A founding year after this year. */\n foundedYearFuture: 'foundedYearFuture',\n /** A request body over the server's size limit (0.18.0: it answered in English). On `body`. */\n bodyTooLarge: 'bodyTooLarge',\n /** A request body that is not valid JSON (0.18.0: it answered in English). On `body`. */\n bodyNotJson: 'bodyNotJson',\n /** The same option twice in one vote (0.18.0). */\n pollVoteDuplicate: 'pollVoteDuplicate',\n /** The same uploaded image attached twice to one post. */\n mediaDuplicate: 'mediaDuplicate',\n /** A post with neither text nor media. */\n postEmpty: 'postEmpty',\n /** Two poll options with the same label. */\n pollOptionsDuplicate: 'pollOptionsDuplicate',\n /** An empty string sent to clear a patch field; clearing is `null`. */\n clearWithNull: 'clearWithNull',\n /** Not a plain http(s) URL on a real domain (`javascript:`, `localhost`, an IP...). */\n urlInvalid: 'urlInvalid',\n /** A handle this product keeps for itself (`admin`, `support`...). */\n usernameReserved: 'usernameReserved',\n /** Agreed to a version of the guidelines that is not the current one. */\n guidelinesOutdated: 'guidelinesOutdated',\n /** An MPIN that is not exactly six digits. */\n mpinInvalid: 'mpinInvalid',\n /** The MPIN and its confirmation differ. */\n mpinMismatch: 'mpinMismatch',\n /** Switching to a staff role without the MPIN. */\n mpinRequired: 'mpinRequired',\n /** The same role twice in one list. */\n rolesDuplicate: 'rolesDuplicate',\n /** An ask (\"testers wanted\") on a post or poll that names no product. */\n askWithoutProduct: 'askWithoutProduct',\n /** An App Store link that is not on apps.apple.com. */\n appStoreLinkHost: 'appStoreLinkHost',\n /** A Play Store link that is not on play.google.com. */\n playStoreLinkHost: 'playStoreLinkHost',\n /** A GitHub link that is not on github.com. */\n githubLinkHost: 'githubLinkHost',\n /** A demo video that is not a YouTube link. Video is shared, never uploaded. */\n videoLinkHost: 'videoLinkHost',\n /** The same screenshot twice in one gallery. */\n screenshotsDuplicate: 'screenshotsDuplicate',\n /** The same platform twice in one list. */\n platformsDuplicate: 'platformsDuplicate',\n /** The same topic twice in one list (0.9.0). */\n topicsDuplicate: 'topicsDuplicate',\n /** A post or poll in a community naming a product or an ask (0.9.0): community content carries neither. */\n communityWithProduct: 'communityWithProduct',\n /** The same capability twice in one list (0.9.0). */\n capabilitiesDuplicate: 'capabilitiesDuplicate',\n /** Not a GSTIN: 15 characters in its pattern, with a check character that adds up (0.12.0). */\n gstinInvalid: 'gstinInvalid',\n /** A GSTIN registered in another state than the one chosen: the state is the GSTIN's own (0.12.0). */\n gstinStateMismatch: 'gstinStateMismatch',\n /** A GSTIN without the legal name and address a B2B invoice must carry (0.12.0). */\n gstinNeedsNameAndAddress: 'gstinNeedsNameAndAddress',\n /** A coupon code with characters other than letters, digits and hyphens (0.12.0). */\n couponCodeInvalid: 'couponCodeInvalid',\n /** A coupon window that ends before it starts (0.12.0). */\n couponWindowInvalid: 'couponWindowInvalid',\n /** The same item twice in a coupon's list of what it applies to (0.12.0). */\n couponTargetsDuplicate: 'couponTargetsDuplicate',\n /** A paid purchase without the buyer's state: the invoice's place of supply (0.12.0). */\n billingStateRequired: 'billingStateRequired',\n /**\n * The guidelines not agreed to at all: the tick box left empty (0.17.0).\n * Distinct from `guidelinesOutdated`, which is agreement to an OLDER text;\n * \"the guidelines have changed\" is the wrong thing to tell someone who has\n * not ticked the box yet.\n */\n guidelinesRequired: 'guidelinesRequired',\n /**\n * The photo cannot be used (0.17.0): it is not the member's processed avatar\n * upload any more, most often because it expired before it was saved. Sent\n * by the server on the photo field with `UPLOAD_NOT_ATTACHABLE`.\n */\n photoUnavailable: 'photoUnavailable',\n /** A business type or registration with no business to describe (0.17.0). */\n ventureRequired: 'ventureRequired',\n /** A state that is not one of India's states and union territories (0.17.0). */\n stateUnknown: 'stateUnknown',\n /** The same goal twice in one list (0.17.0). */\n goalsDuplicate: 'goalsDuplicate',\n /** The same skill twice in one list (0.17.0). */\n skillsDuplicate: 'skillsDuplicate',\n /**\n * A location with no state (0.17.0): India's places are chosen state first.\n * Its own key, so the refusal does not carry all 36 names as its message.\n */\n stateRequired: 'stateRequired',\n} as const;\nexport type ValidationMessageKey = (typeof VALIDATION_MESSAGE)[keyof typeof VALIDATION_MESSAGE];\n\n/**\n * Which part of the request an issue is about.\n *\n * ONE PATH CONVENTION: `path` is ALWAYS relative to this part, so a body field\n * reads `['venture', 'name']` with `location: 'body'`, never\n * `['body', 'venture', 'name']`. A form maps body issues straight onto its\n * fields without stripping a prefix, and a client that sees `query` or\n * `params` knows the problem is the URL, not anything the member typed.\n */\nexport const REQUEST_PART_VALUES = ['body', 'query', 'params'] as const;\nexport const requestPartSchema = z.enum(REQUEST_PART_VALUES);\nexport type RequestPart = z.infer<typeof requestPartSchema>;\n\n/**\n * One problem with one field, as it crosses the wire.\n *\n * `code` is Zod's issue code (`too_small`, `too_big`, `invalid_type`,\n * `invalid_format`, `custom`...). `message` is either one of\n * `VALIDATION_MESSAGE` or, for a plain bound, Zod's own English text, which the\n * client ignores in favour of `code` plus `minimum` / `maximum`.\n */\nexport const validationIssueSchema = z.object({\n /** Set by the server on every issue it sends; absent on a client's own parse. */\n location: requestPartSchema.optional(),\n /**\n * Where the problem is, RELATIVE TO `location`: `['venture', 'name']`,\n * `['options', 2, 'label']`, `['contentId']`.\n */\n path: z.array(z.union([z.string(), z.number()])),\n code: z.string(),\n message: z.string(),\n /** `too_small`: the bound that was missed. */\n minimum: z.number().optional(),\n /** `too_big`: the bound that was passed. */\n maximum: z.number().optional(),\n /** What was measured: `string`, `array`, `number`... */\n origin: z.string().optional(),\n /** `invalid_format`: which format, e.g. `url`, `regex`, `email`. */\n format: z.string().optional(),\n});\nexport type ValidationIssue = z.infer<typeof validationIssueSchema>;\n\n/** The loosest shape this needs from a Zod issue, so it works across 4.x. */\ninterface ZodIssueLike {\n path: readonly PropertyKey[];\n code: string;\n message: string;\n minimum?: unknown;\n maximum?: unknown;\n origin?: unknown;\n format?: unknown;\n}\n\nconst toNumber = (v: unknown): number | undefined =>\n typeof v === 'number' ? v : typeof v === 'bigint' ? Number(v) : undefined;\n\n/**\n * A Zod error as the wire shape. Use this on the server for every 400, and on\n * the client to treat its own errors and the server's the same way.\n *\n * `location` is stamped on every issue when given; the server always gives it.\n *\n * Copies a WHITELIST of fields (see the module note). A path segment that is a\n * symbol, which JSON cannot carry, becomes its description.\n */\nexport function toValidationIssues(\n error: { issues: readonly ZodIssueLike[] },\n location?: RequestPart,\n): ValidationIssue[] {\n return error.issues.map((issue) => {\n const out: ValidationIssue = {\n ...(location ? { location } : {}),\n path: issue.path.map((p) =>\n typeof p === 'number' ? p : typeof p === 'string' ? p : String(p.description ?? ''),\n ),\n code: issue.code,\n message: issue.message,\n };\n const minimum = toNumber(issue.minimum);\n const maximum = toNumber(issue.maximum);\n if (minimum !== undefined) out.minimum = minimum;\n if (maximum !== undefined) out.maximum = maximum;\n if (typeof issue.origin === 'string') out.origin = issue.origin;\n if (typeof issue.format === 'string') out.format = issue.format;\n return out;\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/core/validation.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * founder-schema — How a validation failure is described, on both sides\n *\n * TWO RULES, and they are what let the web client show any error, its own or\n * the server's, on the right field in the member's language:\n *\n * 1. A CUSTOM MESSAGE IS A KEY, NEVER A SENTENCE. Where a schema needs its own\n * message (a refine, a regex), the message is one of `VALIDATION_MESSAGE`,\n * such as `phoneInvalid`. The client turns the key into text in English or\n * Hindi. Before 0.2.0 these were English sentences, so a Hindi screen showed\n * an English error, and a client that wanted to translate one had to match\n * on the wording.\n *\n * Plain bounds carry NO custom message. `.min(1)` and `.max(80)` produce\n * Zod's own `too_small` / `too_big` issues, which already say which bound\n * and what it was (`minimum`, `maximum`, `origin`), and the client words\n * them from those. A hand-written \"at most 80 characters\" would only\n * restate the number in one language.\n *\n * 2. THE SERVER SENDS EVERY ISSUE, IN THIS SHAPE. A 400 answers with\n * `error.details.issues`, built by `toValidationIssues`, so the client can\n * put each one under its field. Until 0.2.0 the backend sent only the\n * first issue's message, with no path at all.\n *\n * ⚠️ `toValidationIssues` COPIES A WHITELIST OF FIELDS, it never spreads an\n * issue. Zod can carry the rejected `input` on an issue, and these bodies hold a\n * date of birth and a phone number. Echoing them into an error response sends\n * them back to the client, into logs and into any proxy in between. A test\n * proves `input` never survives.\n *\n * @module founder-schema/core/validation\n */\n\nimport { z } from 'zod';\n\n/**\n * Every custom message a schema in this package can produce. Each is a\n * translation key the clients define in every language they ship.\n *\n * ⚠️ Append only, and add the translation in the same change. Renaming one\n * shows the raw key to every member until each client ships the new name.\n */\nexport const VALIDATION_MESSAGE = {\n /** Not a 24-hex Mongo id. */\n invalidId: 'invalidId',\n /** Handle: wrong characters, or a dot in the wrong place. */\n usernameInvalid: 'usernameInvalid',\n /** Not a 10-digit Indian mobile number. */\n phoneInvalid: 'phoneInvalid',\n /** Not a `YYYY-MM-DD` date. */\n dateInvalid: 'dateInvalid',\n /** A date that does not exist, such as 30 February. */\n dobInvalid: 'dobInvalid',\n /** Under the minimum age. */\n dobUnderAge: 'dobUnderAge',\n /** Over the sanity ceiling: almost always a mistyped year. */\n dobTooOld: 'dobTooOld',\n /** A founding year after this year. */\n foundedYearFuture: 'foundedYearFuture',\n /** A request body over the server's size limit (0.18.0: it answered in English). On `body`. */\n bodyTooLarge: 'bodyTooLarge',\n /** A request body that is not valid JSON (0.18.0: it answered in English). On `body`. */\n bodyNotJson: 'bodyNotJson',\n /** The same option twice in one vote (0.18.0). */\n pollVoteDuplicate: 'pollVoteDuplicate',\n /** The same uploaded image attached twice to one post. */\n mediaDuplicate: 'mediaDuplicate',\n /** A post with neither text nor media. */\n postEmpty: 'postEmpty',\n /** Two poll options with the same label. */\n pollOptionsDuplicate: 'pollOptionsDuplicate',\n /** An empty string sent to clear a patch field; clearing is `null`. */\n clearWithNull: 'clearWithNull',\n /** Not a plain http(s) URL on a real domain (`javascript:`, `localhost`, an IP...). */\n urlInvalid: 'urlInvalid',\n /** A handle this product keeps for itself (`admin`, `support`...). */\n usernameReserved: 'usernameReserved',\n /** Agreed to a version of the guidelines that is not the current one. */\n guidelinesOutdated: 'guidelinesOutdated',\n /** An MPIN that is not exactly six digits. */\n mpinInvalid: 'mpinInvalid',\n /** The MPIN and its confirmation differ. */\n mpinMismatch: 'mpinMismatch',\n /** Switching to a staff role without the MPIN. */\n mpinRequired: 'mpinRequired',\n /** The same role twice in one list. */\n rolesDuplicate: 'rolesDuplicate',\n /** An ask (\"testers wanted\") on a post or poll that names no product. */\n askWithoutProduct: 'askWithoutProduct',\n /** An App Store link that is not on apps.apple.com. */\n appStoreLinkHost: 'appStoreLinkHost',\n /** A Play Store link that is not on play.google.com. */\n playStoreLinkHost: 'playStoreLinkHost',\n /** A GitHub link that is not on github.com. */\n githubLinkHost: 'githubLinkHost',\n /** A demo video that is not a YouTube link. Video is shared, never uploaded. */\n videoLinkHost: 'videoLinkHost',\n /** The same screenshot twice in one gallery. */\n screenshotsDuplicate: 'screenshotsDuplicate',\n /** The same platform twice in one list. */\n platformsDuplicate: 'platformsDuplicate',\n /** The same topic twice in one list (0.9.0). */\n topicsDuplicate: 'topicsDuplicate',\n /** A post or poll in a community naming a product or an ask (0.9.0): community content carries neither. */\n communityWithProduct: 'communityWithProduct',\n /** The same capability twice in one list (0.9.0). */\n capabilitiesDuplicate: 'capabilitiesDuplicate',\n /** Not a GSTIN: 15 characters in its pattern, with a check character that adds up (0.12.0). */\n gstinInvalid: 'gstinInvalid',\n /** A GSTIN registered in another state than the one chosen: the state is the GSTIN's own (0.12.0). */\n gstinStateMismatch: 'gstinStateMismatch',\n /** A GSTIN without the legal name and address a B2B invoice must carry (0.12.0). */\n gstinNeedsNameAndAddress: 'gstinNeedsNameAndAddress',\n /** A coupon code with characters other than letters, digits and hyphens (0.12.0). */\n couponCodeInvalid: 'couponCodeInvalid',\n /** A coupon window that ends before it starts (0.12.0). */\n couponWindowInvalid: 'couponWindowInvalid',\n /** The same item twice in a coupon's list of what it applies to (0.12.0). */\n couponTargetsDuplicate: 'couponTargetsDuplicate',\n /** A paid purchase without the buyer's state: the invoice's place of supply (0.12.0). */\n billingStateRequired: 'billingStateRequired',\n /**\n * The guidelines not agreed to at all: the tick box left empty (0.17.0).\n * Distinct from `guidelinesOutdated`, which is agreement to an OLDER text;\n * \"the guidelines have changed\" is the wrong thing to tell someone who has\n * not ticked the box yet.\n */\n guidelinesRequired: 'guidelinesRequired',\n /**\n * The photo cannot be used (0.17.0): it is not the member's processed avatar\n * upload any more, most often because it expired before it was saved. Sent\n * by the server on the photo field with `UPLOAD_NOT_ATTACHABLE`.\n */\n photoUnavailable: 'photoUnavailable',\n /** A business type or registration with no business to describe (0.17.0). */\n ventureRequired: 'ventureRequired',\n /** A state that is not one of India's states and union territories (0.17.0). */\n stateUnknown: 'stateUnknown',\n /** The same goal twice in one list (0.17.0). */\n goalsDuplicate: 'goalsDuplicate',\n /** The same skill twice in one list (0.17.0). */\n skillsDuplicate: 'skillsDuplicate',\n /**\n * A location with no state (0.17.0): India's places are chosen state first.\n * Its own key, so the refusal does not carry all 36 names as its message.\n */\n stateRequired: 'stateRequired',\n /** A location picked without its district (0.19.0: state, district, then locality). */\n districtRequired: 'districtRequired',\n /**\n * A pick that does not say its locality: a locality's id, or `null` for the\n * whole district (0.19.0). Worded as the choice it is.\n */\n localityRequired: 'localityRequired',\n /**\n * An area id the tree does not have, or not where the pick puts it (a\n * district outside the chosen state, a locality outside the district):\n * \"choose it again\" (0.19.0).\n */\n areaNotListed: 'areaNotListed',\n} as const;\nexport type ValidationMessageKey = (typeof VALIDATION_MESSAGE)[keyof typeof VALIDATION_MESSAGE];\n\n/**\n * Which part of the request an issue is about.\n *\n * ONE PATH CONVENTION: `path` is ALWAYS relative to this part, so a body field\n * reads `['venture', 'name']` with `location: 'body'`, never\n * `['body', 'venture', 'name']`. A form maps body issues straight onto its\n * fields without stripping a prefix, and a client that sees `query` or\n * `params` knows the problem is the URL, not anything the member typed.\n */\nexport const REQUEST_PART_VALUES = ['body', 'query', 'params'] as const;\nexport const requestPartSchema = z.enum(REQUEST_PART_VALUES);\nexport type RequestPart = z.infer<typeof requestPartSchema>;\n\n/**\n * One problem with one field, as it crosses the wire.\n *\n * `code` is Zod's issue code (`too_small`, `too_big`, `invalid_type`,\n * `invalid_format`, `custom`...). `message` is either one of\n * `VALIDATION_MESSAGE` or, for a plain bound, Zod's own English text, which the\n * client ignores in favour of `code` plus `minimum` / `maximum`.\n */\nexport const validationIssueSchema = z.object({\n /** Set by the server on every issue it sends; absent on a client's own parse. */\n location: requestPartSchema.optional(),\n /**\n * Where the problem is, RELATIVE TO `location`: `['venture', 'name']`,\n * `['options', 2, 'label']`, `['contentId']`.\n */\n path: z.array(z.union([z.string(), z.number()])),\n code: z.string(),\n message: z.string(),\n /** `too_small`: the bound that was missed. */\n minimum: z.number().optional(),\n /** `too_big`: the bound that was passed. */\n maximum: z.number().optional(),\n /** What was measured: `string`, `array`, `number`... */\n origin: z.string().optional(),\n /** `invalid_format`: which format, e.g. `url`, `regex`, `email`. */\n format: z.string().optional(),\n});\nexport type ValidationIssue = z.infer<typeof validationIssueSchema>;\n\n/** The loosest shape this needs from a Zod issue, so it works across 4.x. */\ninterface ZodIssueLike {\n path: readonly PropertyKey[];\n code: string;\n message: string;\n minimum?: unknown;\n maximum?: unknown;\n origin?: unknown;\n format?: unknown;\n}\n\nconst toNumber = (v: unknown): number | undefined =>\n typeof v === 'number' ? v : typeof v === 'bigint' ? Number(v) : undefined;\n\n/**\n * A Zod error as the wire shape. Use this on the server for every 400, and on\n * the client to treat its own errors and the server's the same way.\n *\n * `location` is stamped on every issue when given; the server always gives it.\n *\n * Copies a WHITELIST of fields (see the module note). A path segment that is a\n * symbol, which JSON cannot carry, becomes its description.\n */\nexport function toValidationIssues(\n error: { issues: readonly ZodIssueLike[] },\n location?: RequestPart,\n): ValidationIssue[] {\n return error.issues.map((issue) => {\n const out: ValidationIssue = {\n ...(location ? { location } : {}),\n path: issue.path.map((p) =>\n typeof p === 'number' ? p : typeof p === 'string' ? p : String(p.description ?? ''),\n ),\n code: issue.code,\n message: issue.message,\n };\n const minimum = toNumber(issue.minimum);\n const maximum = toNumber(issue.maximum);\n if (minimum !== undefined) out.minimum = minimum;\n if (maximum !== undefined) out.maximum = maximum;\n if (typeof issue.origin === 'string') out.origin = issue.origin;\n if (typeof issue.format === 'string') out.format = issue.format;\n return out;\n });\n}\n"]}
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where a member is and where they live: Jansathi's location model (0.19.0)
|
|
3
|
+
* =========================================================================
|
|
4
|
+
*
|
|
5
|
+
* The user, 2026-10-21: Founder Circle takes Jansathi's location drawer
|
|
6
|
+
* (state, then district, then locality, from `master_db.areas`) and its whole
|
|
7
|
+
* location model ("just copy paste things from jansathi"). The plan, with the
|
|
8
|
+
* Jansathi analysis it copies: founder-circle/LOCATION-PLAN-2026-10-21.md.
|
|
9
|
+
*
|
|
10
|
+
* Two axes, as in Jansathi, never mixed:
|
|
11
|
+
* - the DECLARED location (where the member lives): picked in the drawer, or
|
|
12
|
+
* filled from GPS by the member, then saved. A client sends AREA IDS only
|
|
13
|
+
* (`locationPickSchema`); the server reads the names, the public city and
|
|
14
|
+
* the coordinates from `master_db`, so no client can store a place the area
|
|
15
|
+
* tree does not have.
|
|
16
|
+
* - the GPS axis (where the member is): the daily sync and "Use my location"
|
|
17
|
+
* send a fix (`geolocationFixSchema`); the server keeps it, the area it
|
|
18
|
+
* falls in, and the last `LOCATION_HISTORY_MAX` of each. Nothing on this
|
|
19
|
+
* axis is ever shown to another member.
|
|
20
|
+
*
|
|
21
|
+
* Area ids are master_db's ObjectIds: stable for the life of the area tree.
|
|
22
|
+
*
|
|
23
|
+
* @module domains/location/areas
|
|
24
|
+
*/
|
|
25
|
+
import { z } from 'zod';
|
|
26
|
+
/** The levels of `master_db.areas` a member's location can name. */
|
|
27
|
+
export declare const AREA_TYPE_VALUES: readonly ["COUNTRY", "STATE", "DISTRICT", "SUB_DISTRICT", "BLOCK", "GRAM_PANCHAYAT", "VILLAGE", "URBAN_BODY", "URBAN_WARD"];
|
|
28
|
+
export declare const areaTypeSchema: z.ZodEnum<{
|
|
29
|
+
COUNTRY: "COUNTRY";
|
|
30
|
+
STATE: "STATE";
|
|
31
|
+
DISTRICT: "DISTRICT";
|
|
32
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
33
|
+
BLOCK: "BLOCK";
|
|
34
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
35
|
+
VILLAGE: "VILLAGE";
|
|
36
|
+
URBAN_BODY: "URBAN_BODY";
|
|
37
|
+
URBAN_WARD: "URBAN_WARD";
|
|
38
|
+
}>;
|
|
39
|
+
export type AreaType = z.infer<typeof areaTypeSchema>;
|
|
40
|
+
/**
|
|
41
|
+
* The drawer's third step lists these, everything below a district that a
|
|
42
|
+
* member can live in: Jansathi's `LOCALITY_TYPE_TO_ADMIN_KEY`, each one a
|
|
43
|
+
* stored level. Jansathi's drawer also lists HAMLET and LOCALITY and then
|
|
44
|
+
* refuses them on save (no stored level); here they are never offered.
|
|
45
|
+
* RURAL_WARD is not offered either (Jansathi neither): it has no point.
|
|
46
|
+
*/
|
|
47
|
+
export declare const LOCALITY_AREA_TYPES: readonly ["SUB_DISTRICT", "BLOCK", "GRAM_PANCHAYAT", "VILLAGE", "URBAN_BODY", "URBAN_WARD"];
|
|
48
|
+
export type LocalityAreaType = (typeof LOCALITY_AREA_TYPES)[number];
|
|
49
|
+
/** How a locality row names its level (Jansathi's `addressForm.areaTypes`). */
|
|
50
|
+
export declare const LOCALITY_TYPE_LABEL: Record<LocalityAreaType, string>;
|
|
51
|
+
/**
|
|
52
|
+
* An urban body's kind, as the area builder writes it (reform-backend's
|
|
53
|
+
* `URBAN_BODY_TYPES`, LGD). Read leniently: a kind added there later shows as
|
|
54
|
+
* "Town or city" rather than breaking the list.
|
|
55
|
+
*/
|
|
56
|
+
export declare const URBAN_BODY_TYPE_VALUES: readonly ["Municipal Corporation", "Municipality", "Notified Area Council", "Town Panchayat", "Nagar Panchayat", "Municipal Council", "NCT Municipal Council", "City Municipal Council", "Town Municipal Council", "Cantonment Board"];
|
|
57
|
+
/** One area as a list row and as part of a place: what a client may show. */
|
|
58
|
+
export declare const areaOptionSchema: z.ZodObject<{
|
|
59
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
60
|
+
name: z.ZodString;
|
|
61
|
+
type: z.ZodEnum<{
|
|
62
|
+
COUNTRY: "COUNTRY";
|
|
63
|
+
STATE: "STATE";
|
|
64
|
+
DISTRICT: "DISTRICT";
|
|
65
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
66
|
+
BLOCK: "BLOCK";
|
|
67
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
68
|
+
VILLAGE: "VILLAGE";
|
|
69
|
+
URBAN_BODY: "URBAN_BODY";
|
|
70
|
+
URBAN_WARD: "URBAN_WARD";
|
|
71
|
+
}>;
|
|
72
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
73
|
+
within: z.ZodOptional<z.ZodString>;
|
|
74
|
+
}, z.core.$strip>;
|
|
75
|
+
export type AreaOption = z.infer<typeof areaOptionSchema>;
|
|
76
|
+
/**
|
|
77
|
+
* An area as a member reads it: a ward the tree names by its number alone
|
|
78
|
+
* ("25") is "Ward 25"; anything else by its name.
|
|
79
|
+
*/
|
|
80
|
+
export declare function areaWords(area: Pick<AreaOption, 'name' | 'type'>): string;
|
|
81
|
+
/** `GET /location/areas/states` and `/districts`: the whole list, sorted by name. */
|
|
82
|
+
export declare const areaListSchema: z.ZodObject<{
|
|
83
|
+
items: z.ZodArray<z.ZodObject<{
|
|
84
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
85
|
+
name: z.ZodString;
|
|
86
|
+
type: z.ZodEnum<{
|
|
87
|
+
COUNTRY: "COUNTRY";
|
|
88
|
+
STATE: "STATE";
|
|
89
|
+
DISTRICT: "DISTRICT";
|
|
90
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
91
|
+
BLOCK: "BLOCK";
|
|
92
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
93
|
+
VILLAGE: "VILLAGE";
|
|
94
|
+
URBAN_BODY: "URBAN_BODY";
|
|
95
|
+
URBAN_WARD: "URBAN_WARD";
|
|
96
|
+
}>;
|
|
97
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
98
|
+
within: z.ZodOptional<z.ZodString>;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
}, z.core.$strip>;
|
|
101
|
+
export type AreaList = z.infer<typeof areaListSchema>;
|
|
102
|
+
/** `GET /location/areas/localities`: one page (`LOCALITY_PAGE_SIZE`), sorted by name. */
|
|
103
|
+
export declare const areaPageSchema: z.ZodObject<{
|
|
104
|
+
items: z.ZodArray<z.ZodObject<{
|
|
105
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
106
|
+
name: z.ZodString;
|
|
107
|
+
type: z.ZodEnum<{
|
|
108
|
+
COUNTRY: "COUNTRY";
|
|
109
|
+
STATE: "STATE";
|
|
110
|
+
DISTRICT: "DISTRICT";
|
|
111
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
112
|
+
BLOCK: "BLOCK";
|
|
113
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
114
|
+
VILLAGE: "VILLAGE";
|
|
115
|
+
URBAN_BODY: "URBAN_BODY";
|
|
116
|
+
URBAN_WARD: "URBAN_WARD";
|
|
117
|
+
}>;
|
|
118
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
119
|
+
within: z.ZodOptional<z.ZodString>;
|
|
120
|
+
}, z.core.$strip>>;
|
|
121
|
+
hasMore: z.ZodBoolean;
|
|
122
|
+
}, z.core.$strip>;
|
|
123
|
+
export type AreaPage = z.infer<typeof areaPageSchema>;
|
|
124
|
+
/** `GET /location/areas/districts?stateId=` */
|
|
125
|
+
export declare const districtsQuerySchema: z.ZodObject<{
|
|
126
|
+
stateId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
127
|
+
}, z.core.$strip>;
|
|
128
|
+
export type DistrictsQuery = z.infer<typeof districtsQuerySchema>;
|
|
129
|
+
/**
|
|
130
|
+
* `GET /location/areas/localities?districtId=&q=&skip=`: every locality level
|
|
131
|
+
* anywhere inside the district (a ward sits under its town, not under the
|
|
132
|
+
* district). `q` matches anywhere in the name, as Jansathi's does; an emptied
|
|
133
|
+
* box is "no search".
|
|
134
|
+
*/
|
|
135
|
+
export declare const localitiesQuerySchema: z.ZodObject<{
|
|
136
|
+
districtId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
137
|
+
q: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
|
|
138
|
+
skip: z.ZodPreprocess<z.ZodDefault<z.ZodCoercedNumber<unknown>>, unknown>;
|
|
139
|
+
}, z.core.$strip>;
|
|
140
|
+
export type LocalitiesQuery = z.infer<typeof localitiesQuerySchema>;
|
|
141
|
+
export type LocalitiesQueryInput = z.input<typeof localitiesQuerySchema>;
|
|
142
|
+
/**
|
|
143
|
+
* A location as it is WRITTEN (0.19.0): onboarding's finish and Me's personal
|
|
144
|
+
* details. Ids only. `localityId: null` is the member's "my locality is not
|
|
145
|
+
* listed": the whole district (the user's choice, 2026-10-21).
|
|
146
|
+
*
|
|
147
|
+
* The server refuses ids that are not one chain (a district outside the
|
|
148
|
+
* state, a locality outside the district) and a state Founder Circle's list
|
|
149
|
+
* does not name (`findIndiaState`).
|
|
150
|
+
*/
|
|
151
|
+
export declare const locationPickSchema: z.ZodObject<{
|
|
152
|
+
stateId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
153
|
+
districtId: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
154
|
+
localityId: z.ZodNullable<z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>>;
|
|
155
|
+
}, z.core.$strict>;
|
|
156
|
+
export type LocationPick = z.infer<typeof locationPickSchema>;
|
|
157
|
+
/**
|
|
158
|
+
* A place with its names: the member's own location as Me reads it back, the
|
|
159
|
+
* area GPS matched, and the onboarding draft. What the location field shows
|
|
160
|
+
* ("Locality, District, State") and where the drawer reopens. Owner-only:
|
|
161
|
+
* other members read `locationSchema` (city, state, country).
|
|
162
|
+
*/
|
|
163
|
+
export declare const placeSchema: z.ZodObject<{
|
|
164
|
+
state: z.ZodObject<{
|
|
165
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
166
|
+
name: z.ZodString;
|
|
167
|
+
type: z.ZodEnum<{
|
|
168
|
+
COUNTRY: "COUNTRY";
|
|
169
|
+
STATE: "STATE";
|
|
170
|
+
DISTRICT: "DISTRICT";
|
|
171
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
172
|
+
BLOCK: "BLOCK";
|
|
173
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
174
|
+
VILLAGE: "VILLAGE";
|
|
175
|
+
URBAN_BODY: "URBAN_BODY";
|
|
176
|
+
URBAN_WARD: "URBAN_WARD";
|
|
177
|
+
}>;
|
|
178
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
179
|
+
within: z.ZodOptional<z.ZodString>;
|
|
180
|
+
}, z.core.$strip>;
|
|
181
|
+
district: z.ZodObject<{
|
|
182
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
183
|
+
name: z.ZodString;
|
|
184
|
+
type: z.ZodEnum<{
|
|
185
|
+
COUNTRY: "COUNTRY";
|
|
186
|
+
STATE: "STATE";
|
|
187
|
+
DISTRICT: "DISTRICT";
|
|
188
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
189
|
+
BLOCK: "BLOCK";
|
|
190
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
191
|
+
VILLAGE: "VILLAGE";
|
|
192
|
+
URBAN_BODY: "URBAN_BODY";
|
|
193
|
+
URBAN_WARD: "URBAN_WARD";
|
|
194
|
+
}>;
|
|
195
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
196
|
+
within: z.ZodOptional<z.ZodString>;
|
|
197
|
+
}, z.core.$strip>;
|
|
198
|
+
locality: z.ZodNullable<z.ZodObject<{
|
|
199
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
200
|
+
name: z.ZodString;
|
|
201
|
+
type: z.ZodEnum<{
|
|
202
|
+
COUNTRY: "COUNTRY";
|
|
203
|
+
STATE: "STATE";
|
|
204
|
+
DISTRICT: "DISTRICT";
|
|
205
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
206
|
+
BLOCK: "BLOCK";
|
|
207
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
208
|
+
VILLAGE: "VILLAGE";
|
|
209
|
+
URBAN_BODY: "URBAN_BODY";
|
|
210
|
+
URBAN_WARD: "URBAN_WARD";
|
|
211
|
+
}>;
|
|
212
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
213
|
+
within: z.ZodOptional<z.ZodString>;
|
|
214
|
+
}, z.core.$strip>>;
|
|
215
|
+
}, z.core.$strip>;
|
|
216
|
+
export type Place = z.infer<typeof placeSchema>;
|
|
217
|
+
/** The pick a place is (what saving it sends). */
|
|
218
|
+
export declare function pickOfPlace(place: Place): LocationPick;
|
|
219
|
+
/**
|
|
220
|
+
* "Locality, what it sits in, District, State", the deepest first; a name
|
|
221
|
+
* repeated is said once ("Ward 25, Bassi, Jaipur, Rajasthan"; "Rajpur,
|
|
222
|
+
* Dehradun, Uttarakhand").
|
|
223
|
+
*/
|
|
224
|
+
export declare function placeWords(place: Place): string;
|
|
225
|
+
/**
|
|
226
|
+
* `POST /me/geolocation`: one GPS fix, from the daily sync or a member's
|
|
227
|
+
* "Use my location" (Jansathi's body). Plain degrees, accuracy in metres. A
|
|
228
|
+
* fix coarser than `GEO_ACCURACY_MAX_M` is refused: it cannot name a place.
|
|
229
|
+
*/
|
|
230
|
+
export declare const geolocationFixSchema: z.ZodObject<{
|
|
231
|
+
latitude: z.ZodNumber;
|
|
232
|
+
longitude: z.ZodNumber;
|
|
233
|
+
accuracy: z.ZodNumber;
|
|
234
|
+
}, z.core.$strict>;
|
|
235
|
+
export type GeolocationFix = z.infer<typeof geolocationFixSchema>;
|
|
236
|
+
/**
|
|
237
|
+
* The answer: the place the fix falls in, for "Use my location" to put in the
|
|
238
|
+
* field (the member still saves it), or `null` when the area tree has no
|
|
239
|
+
* confident match (outside India, or nothing within reach). The daily sync
|
|
240
|
+
* ignores it. Never the coordinates themselves.
|
|
241
|
+
*/
|
|
242
|
+
export declare const geolocationSyncResultSchema: z.ZodObject<{
|
|
243
|
+
synced: z.ZodLiteral<true>;
|
|
244
|
+
match: z.ZodNullable<z.ZodObject<{
|
|
245
|
+
state: z.ZodObject<{
|
|
246
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
247
|
+
name: z.ZodString;
|
|
248
|
+
type: z.ZodEnum<{
|
|
249
|
+
COUNTRY: "COUNTRY";
|
|
250
|
+
STATE: "STATE";
|
|
251
|
+
DISTRICT: "DISTRICT";
|
|
252
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
253
|
+
BLOCK: "BLOCK";
|
|
254
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
255
|
+
VILLAGE: "VILLAGE";
|
|
256
|
+
URBAN_BODY: "URBAN_BODY";
|
|
257
|
+
URBAN_WARD: "URBAN_WARD";
|
|
258
|
+
}>;
|
|
259
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
260
|
+
within: z.ZodOptional<z.ZodString>;
|
|
261
|
+
}, z.core.$strip>;
|
|
262
|
+
district: z.ZodObject<{
|
|
263
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
264
|
+
name: z.ZodString;
|
|
265
|
+
type: z.ZodEnum<{
|
|
266
|
+
COUNTRY: "COUNTRY";
|
|
267
|
+
STATE: "STATE";
|
|
268
|
+
DISTRICT: "DISTRICT";
|
|
269
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
270
|
+
BLOCK: "BLOCK";
|
|
271
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
272
|
+
VILLAGE: "VILLAGE";
|
|
273
|
+
URBAN_BODY: "URBAN_BODY";
|
|
274
|
+
URBAN_WARD: "URBAN_WARD";
|
|
275
|
+
}>;
|
|
276
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
277
|
+
within: z.ZodOptional<z.ZodString>;
|
|
278
|
+
}, z.core.$strip>;
|
|
279
|
+
locality: z.ZodNullable<z.ZodObject<{
|
|
280
|
+
id: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
|
|
281
|
+
name: z.ZodString;
|
|
282
|
+
type: z.ZodEnum<{
|
|
283
|
+
COUNTRY: "COUNTRY";
|
|
284
|
+
STATE: "STATE";
|
|
285
|
+
DISTRICT: "DISTRICT";
|
|
286
|
+
SUB_DISTRICT: "SUB_DISTRICT";
|
|
287
|
+
BLOCK: "BLOCK";
|
|
288
|
+
GRAM_PANCHAYAT: "GRAM_PANCHAYAT";
|
|
289
|
+
VILLAGE: "VILLAGE";
|
|
290
|
+
URBAN_BODY: "URBAN_BODY";
|
|
291
|
+
URBAN_WARD: "URBAN_WARD";
|
|
292
|
+
}>;
|
|
293
|
+
urbanBodyType: z.ZodOptional<z.ZodString>;
|
|
294
|
+
within: z.ZodOptional<z.ZodString>;
|
|
295
|
+
}, z.core.$strip>>;
|
|
296
|
+
}, z.core.$strip>>;
|
|
297
|
+
}, z.core.$strip>;
|
|
298
|
+
export type GeolocationSyncResult = z.infer<typeof geolocationSyncResultSchema>;
|
|
299
|
+
/**
|
|
300
|
+
* Whether Founder Circle keeps the member's positions (the user, 2026-10-22:
|
|
301
|
+
* "Add stop + clear", India's DPDP right to withdraw consent). On by default,
|
|
302
|
+
* as Jansathi; it only matters once the browser allows location at all.
|
|
303
|
+
*
|
|
304
|
+
* OFF: the server keeps NO position: a fix (the daily check or a tap on "Use
|
|
305
|
+
* my location") is still answered with the place it falls in, so the field can
|
|
306
|
+
* be filled, but nothing of it is stored, and no history row is written, not
|
|
307
|
+
* even for a saved place. The web stops the daily check. The member's chosen
|
|
308
|
+
* place is not touched: removing it is the location field's Remove.
|
|
309
|
+
*
|
|
310
|
+
* `GET /api/v1/me/location-settings`, and `PATCH` with
|
|
311
|
+
* `updateLocationSettingsBodySchema`, both answer this.
|
|
312
|
+
*/
|
|
313
|
+
export declare const locationSettingsSchema: z.ZodObject<{
|
|
314
|
+
dailyLocation: z.ZodBoolean;
|
|
315
|
+
}, z.core.$strip>;
|
|
316
|
+
export type LocationSettings = z.infer<typeof locationSettingsSchema>;
|
|
317
|
+
/** `PATCH /api/v1/me/location-settings` */
|
|
318
|
+
export declare const updateLocationSettingsBodySchema: z.ZodObject<{
|
|
319
|
+
dailyLocation: z.ZodBoolean;
|
|
320
|
+
}, z.core.$strict>;
|
|
321
|
+
export type UpdateLocationSettingsBody = z.infer<typeof updateLocationSettingsBodySchema>;
|
|
322
|
+
/**
|
|
323
|
+
* `DELETE /api/v1/me/location-history`: every position and area the member's
|
|
324
|
+
* device sent, and the position kept with their saved place, deleted at once.
|
|
325
|
+
* The chosen place itself (what others see as city and state) stays.
|
|
326
|
+
*/
|
|
327
|
+
export declare const clearLocationHistoryResultSchema: z.ZodObject<{
|
|
328
|
+
cleared: z.ZodLiteral<true>;
|
|
329
|
+
}, z.core.$strip>;
|
|
330
|
+
export type ClearLocationHistoryResult = z.infer<typeof clearLocationHistoryResultSchema>;
|
|
331
|
+
//# sourceMappingURL=areas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"areas.d.ts","sourceRoot":"","sources":["../../../src/domains/location/areas.ts"],"names":[],"mappings":"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"}
|