refine-apito
Version:
A data provider for Refine that connects to Apito - a headless CMS and backend builder.
1 lines • 22 kB
Source Map (JSON)
{"version":3,"sources":["../src/apitoGraphqlNames.ts"],"names":[],"mappings":"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","file":"apitoGraphqlNames.mjs","sourcesContent":["/**\n * Apito model naming aligned with `open-core/utility/apito_naming.go`.\n * Store canonical model ids as snake_case (e.g. `food_order`); derive GraphQL names with pure string ops.\n */\n\nimport { singularize } from 'inflection';\n\nconst singularKeepAsIs = new Set([\n 'news',\n 'data',\n 'media',\n 'analytics',\n 'series',\n 'species',\n]);\n\nconst canonicalIDRe = /^[a-z][a-z0-9]*(?:_[a-z0-9]+)*$/;\n\n/** Same boundary rule as Go `rejectRunOnLowercaseConcat` (len >= 9, all a-z). */\nfunction rejectRunOnLowercaseConcat(raw: string): void {\n if (/[\\s_\\-]/.test(raw)) return;\n if (/[a-z][A-Z]/.test(raw)) return;\n if (!/^[a-z]+$/.test(raw)) return;\n if (raw.length >= 9) {\n throw new Error(\n 'model name needs a word boundary between words: use food_order, food-order, foodOrder, or \"food order\"'\n );\n }\n}\n\nfunction splitCamelPieces(piece: string): string[] {\n const spaced = piece.replace(/([a-z0-9])([A-Z])/g, '$1 $2');\n return spaced\n .split(/\\s+/)\n .filter(Boolean)\n .map((s) => s.replace(/[^a-zA-Z0-9]/g, '').toLowerCase())\n .filter(Boolean);\n}\n\nfunction splitIntoWordSegments(raw: string): string[] {\n const normalized = raw.trim().replace(/-/g, '_');\n const chunks = normalized.split(/[\\s_]+/).filter((c) => c.length > 0);\n const segments: string[] = [];\n for (const chunk of chunks) {\n const lettersOnly = chunk.replace(/[^a-zA-Z0-9]/g, '');\n const pieces =\n lettersOnly === chunk ? splitCamelPieces(chunk) : [lettersOnly.toLowerCase()];\n for (const p of pieces) {\n const s = p.replace(/[^a-z0-9]/gi, '').toLowerCase();\n if (s) segments.push(s);\n }\n }\n return segments;\n}\n\nfunction singularizeSegment(seg: string): string {\n if (singularKeepAsIs.has(seg)) return seg;\n return singularize(seg);\n}\n\n/**\n * Normalizes admin input to canonical snake_case singular model id (matches Go `CanonicalizeModelName`).\n */\nexport function canonicalizeModelName(raw: string): string {\n const t = raw.trim();\n if (!t) throw new Error('model name is required');\n rejectRunOnLowercaseConcat(t);\n const segments = splitIntoWordSegments(t);\n if (segments.length === 0) throw new Error('invalid model name');\n segments[segments.length - 1] = singularizeSegment(\n segments[segments.length - 1]!\n );\n const out = segments.join('_');\n if (!canonicalIDRe.test(out)) throw new Error('invalid model name');\n reservedCheck(out);\n return out;\n}\n\nfunction reservedCheck(canonical: string): void {\n switch (canonical) {\n case 'list':\n throw new Error(\n 'naming a Model `List` is not allowed. Apito uses List for plural resources.'\n );\n case 'user':\n throw new Error(\n 'naming a Model `User` is protected. Add the Authentication module from Settings.'\n );\n case 'system':\n throw new Error('naming a Model `System` is not allowed.');\n case 'function':\n throw new Error('naming a Model `Function` is not allowed.');\n }\n}\n\n/** lowerCamel from canonical snake (`food_order` → `foodOrder`). */\nexport function camelFromCanonical(canonical: string): string {\n const parts = canonical.split('_').filter(Boolean);\n return parts\n .map((p, i) =>\n i === 0\n ? p.toLowerCase()\n : p.charAt(0).toUpperCase() + p.slice(1).toLowerCase()\n )\n .join('');\n}\n\n/** PascalCase without underscores (`food_order` → `FoodOrder`). */\nexport function pascalFromCanonical(canonical: string): string {\n return canonical\n .split('_')\n .filter(Boolean)\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('');\n}\n\n/** Legacy camel id → Pascal (`foodCategory` → `FoodCategory`). */\nexport function pascalFromAnyModelId(modelId: string): string {\n if (!modelId) return '';\n if (modelId.includes('_')) return pascalFromCanonical(modelId);\n const segs = splitCamelPieces(modelId);\n return segs\n .map((s) => s.charAt(0).toUpperCase() + s.slice(1).toLowerCase())\n .join('');\n}\n\nexport function listGraphQLTypeName(modelId: string): string {\n return `${pascalFromAnyModelId(apitoSingularResourceName(modelId))}List`;\n}\n\n/** Matches Go `GraphQLComposedTypeName` (e.g. `Create_Payload`, `List_Upsert_Payload`). */\nexport function apitoGraphQLComposedTypeName(modelId: string, suffix: string): string {\n const singular = apitoSingularResourceName(modelId);\n const suf = suffix.replace(/^_/, '').split('_').filter(Boolean);\n const modelSegs = singular.includes('_')\n ? singular.split('_').filter(Boolean)\n : splitCamelPieces(singular).map((s) => s.toLowerCase());\n const extra = suf.flatMap((chunk) =>\n splitCamelPieces(chunk).map((x) => x.toLowerCase())\n );\n const all = [...modelSegs, ...extra];\n return all\n .map((p) => p.charAt(0).toUpperCase() + p.slice(1).toLowerCase())\n .join('_');\n}\n\n/**\n * lowerCamel field id for GraphQL root fields — matches Go `utility.SingularResourceName`:\n * trim `List` / `ListCount`, then camel-case the remainder (`CamelFromAny`), **without**\n * English plural→singular inflection (that diverged from the engine and broke variable types).\n */\nexport function apitoSingularResourceName(name: string): string {\n let t = name.trim();\n if (t.endsWith('ListCount')) t = t.slice(0, -'ListCount'.length);\n else if (t.endsWith('List')) t = t.slice(0, -'List'.length);\n t = t.trim();\n if (!t) return '';\n if (t.includes('_')) {\n return camelFromCanonical(t);\n }\n const segs = splitCamelPieces(t);\n if (segs.length === 0) return t.toLowerCase();\n return segs\n .map((s, i) =>\n i === 0\n ? s.toLowerCase()\n : s.charAt(0).toUpperCase() + s.slice(1).toLowerCase()\n )\n .join('');\n}\n\nexport const apitoModelName = apitoSingularResourceName;\n\nexport function apitoMultipleResourceName(name: string): string {\n return `${apitoSingularResourceName(name)}List`;\n}\n\n/**\n * Public GraphQL field name for a **relation** on list/getOne rows (matches engine `attachConnectionFields`):\n * - **has_many** → `{singular}List` (e.g. model `food` → `foodList`), **not** `food`.\n * - **has_one** → lowerCamel singular (e.g. `customer`, `foodCategory`).\n *\n * Use this for `meta.connectionFields` **keys** so the generated selection matches the schema.\n */\nexport function apitoConnectionFieldNameForRelation(\n relatedModelRef: string,\n relation: 'has_one' | 'has_many'\n): string {\n if (relation === 'has_many') {\n return apitoMultipleResourceName(relatedModelRef);\n }\n return apitoSingularResourceName(relatedModelRef);\n}\n\n/**\n * Maps `meta.connectionFields` / `aliasFields` keys and targets to engine GraphQL field names.\n * Unlike {@link apitoSingularResourceName} alone, this does **not** strip a trailing `List` from\n * connection field ids such as **`foodList`** (that strip is for list *operation* names like `foodOrderList` → `foodOrder`).\n */\nexport function apitoGraphqlConnectionFieldFromMetaKey(key: string): string {\n const k = key.trim();\n if (!k) return k;\n if (k.includes('_')) {\n return apitoSingularResourceName(k);\n }\n if (/List$/i.test(k) && !/ListCount$/i.test(k)) {\n return k.charAt(0).toLowerCase() + k.slice(1);\n }\n return apitoSingularResourceName(k);\n}\n\nexport function apitoGraphQLTypeNameForFilterArg(modelId: string): string {\n return listGraphQLTypeName(modelId);\n}\n\nexport function apitoListGraphQLTypeName(resource: string): string {\n return listGraphQLTypeName(resource);\n}\n\nexport function apitoListCountGraphQLTypeName(resource: string): string {\n return apitoGraphQLComposedTypeName(resource, 'List_Count');\n}\n\nexport function apitoSingularGraphQLTypeName(resource: string): string {\n return pascalFromAnyModelId(apitoSingularResourceName(resource));\n}\n\n/**\n * Stored model id as snake_case (matches engine `Connection.Model` / filter `definedModel.Name`).\n * Use this when building mutation `connect` / `disconnect` keys: `{storedId}_id` / `{storedId}_ids`.\n */\nexport function apitoStoredSnakeModelId(resource: string): string {\n const singular = apitoSingularResourceName(resource);\n if (singular.includes('_')) return singular;\n return splitCamelPieces(singular).join('_');\n}\n\n/** `connect` / `disconnect` field for a has_one relation: `{stored_model_id}_id` (e.g. `food_category_id`). */\nexport function apitoMutationConnectHasOneIdField(relatedModelRef: string): string {\n return `${apitoStoredSnakeModelId(relatedModelRef)}_id`;\n}\n\n/** `connect` / `disconnect` field for a has_many relation: `{stored_model_id}_ids`. */\nexport function apitoMutationConnectHasManyIdsField(\n relatedModelRef: string\n): string {\n return `${apitoStoredSnakeModelId(relatedModelRef)}_ids`;\n}\n\nexport function apitoConnectionFilterConditionType(resource: string): string {\n return `${apitoStoredSnakeModelId(resource)}_Connection_Filter_Condition`.toUpperCase();\n}\n\nexport function apitoWhereRelationFilterConditionType(resource: string): string {\n return `${apitoStoredSnakeModelId(resource)}_Where_Relation_Filter_Condition`.toUpperCase();\n}\n\n/**\n * List query `where` / sort / `_key` payload types for `*List` fields (e.g. `FOODORDERLIST_INPUT_WHERE_PAYLOAD`).\n * Do **not** use this for `*ListCount` — use {@link apitoListCountWhereInputType} / {@link apitoListCountSortInputType}.\n */\nexport function apitoWhereInputType(resource: string): string {\n return `${listGraphQLTypeName(resource)}_Input_Where_Payload`.toUpperCase();\n}\n\nexport function apitoSortInputType(resource: string): string {\n return `${listGraphQLTypeName(resource)}_Input_Sort_Payload`.toUpperCase();\n}\n\nexport function apitoListKeyConditionType(resource: string): string {\n return `${listGraphQLTypeName(resource)}_Key_Condition`.toUpperCase();\n}\n\nexport function apitoListCountKeyConditionType(resource: string): string {\n return `${apitoGraphQLComposedTypeName(resource, 'List_Count')}_Key_Condition`.toUpperCase();\n}\n\n/**\n * `*ListCount` query `where` argument type (e.g. `FOOD_ORDER_LIST_COUNT_INPUT_WHERE_PAYLOAD`).\n * This is **not** `FoodOrderList` + `_Count_*` (wrong: `FOODORDERLIST_COUNT_*`); the engine uses\n * {@link apitoGraphQLComposedTypeName} with suffix `List_Count` (underscores between word segments).\n */\nexport function apitoListCountWhereInputType(resource: string): string {\n return `${apitoGraphQLComposedTypeName(resource, 'List_Count')}_Input_Where_Payload`.toUpperCase();\n}\n\n/** `*ListCount` query `sort` argument type (e.g. `FOOD_ORDER_LIST_COUNT_INPUT_SORT_PAYLOAD`). */\nexport function apitoListCountSortInputType(resource: string): string {\n return `${apitoGraphQLComposedTypeName(resource, 'List_Count')}_Input_Sort_Payload`.toUpperCase();\n}\n\n/**\n * Builds nested relation field lines for list/getOne GraphQL selection sets.\n * Normalizes stored snake_case ids and legacy names to the same lowerCamel field names as the Apito engine\n * (`apitoSingularResourceName`), so `aliasFields: { foodCategory: \"food_category\" }` still resolves to `foodCategory`.\n *\n * - `connectionFields` keys are the **client/response key** when `aliasFields` is set; otherwise the key is\n * normalized to the schema field name.\n * - `aliasFields[key]` when present is the **schema field name** (may be legacy `food_category`); it is normalized.\n * - **has_many** relations use **`{model}List`** on the parent type (e.g. `foodList`), not the singular `food`.\n * Use {@link apitoConnectionFieldNameForRelation}(..., `'has_many'`) or {@link apitoMultipleResourceName} for keys.\n * Keys like `foodList` are preserved (see {@link apitoGraphqlConnectionFieldFromMetaKey}).\n */\nexport function formatApitoConnectionSubselections(\n connectionFields: Record<string, string>,\n aliasFields: Record<string, string> = {}\n): string {\n return Object.keys(connectionFields)\n .map((key) => {\n const selection = connectionFields[key];\n const rawTarget = aliasFields[key];\n const hasExplicitAlias =\n rawTarget !== undefined &&\n rawTarget !== null &&\n String(rawTarget).trim() !== '';\n\n const targetField = apitoGraphqlConnectionFieldFromMetaKey(\n hasExplicitAlias ? String(rawTarget).trim() : key\n );\n\n if (hasExplicitAlias) {\n const responseKey = key;\n if (responseKey === targetField) {\n return `${targetField} { ${selection} }`;\n }\n return `${responseKey}: ${targetField} { ${selection} }`;\n }\n\n return `${targetField} { ${selection} }`;\n })\n .join('\\n');\n}\n\nexport function buildApitoCreateMutation(\n resource: string,\n fields: string[]\n): string {\n const id = apitoSingularResourceName(resource);\n const pascal = pascalFromAnyModelId(id);\n const payload = apitoGraphQLComposedTypeName(id, 'Create_Payload');\n const rel = apitoGraphQLComposedTypeName(id, 'Relation_Connect_Payload');\n return ` mutation Create${pascal}($payload: ${payload}!, $connect: ${rel}) {\n create${pascal}(payload: $payload, connect: $connect, status: published) {\n id\n data {\n ${fields.join('\\n')}\n }\n meta {\n created_at\n status\n updated_at\n }\n }\n }`;\n}\n"]}