runid-lys 0.4.2 → 0.5.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.
@@ -1,114 +0,0 @@
1
- import { useMemo } from "react";
2
- import { useIntl } from "react-intl";
3
- const lowerCaseFirstLetter = (str) => {
4
- return str.charAt(0).toLowerCase() + str.slice(1);
5
- };
6
- const cn = (...classes) => {
7
- return classes.filter(Boolean).join(" ");
8
- };
9
- const toSnakeCase = (str) => {
10
- return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
11
- };
12
- const numberToString = (value) => {
13
- if (value == null) return "";
14
- const num = typeof value === "string" ? parseFloat(value) : value;
15
- if (isNaN(num)) return "";
16
- return num.toLocaleString("fullwide", { useGrouping: false, maximumFractionDigits: 20 });
17
- };
18
- function extractOperationNames(node) {
19
- const operationNames = [];
20
- if ("operation" in node && node.operation) {
21
- const operation = node.operation;
22
- if ("selections" in operation && Array.isArray(operation.selections)) {
23
- operation.selections.forEach((selection) => {
24
- if (selection && typeof selection === "object" && "name" in selection) {
25
- operationNames.push(selection.name);
26
- }
27
- });
28
- }
29
- }
30
- return operationNames;
31
- }
32
- function checkOperationsPermission(operationNames, checkWebserviceAccess) {
33
- if (!operationNames.length) {
34
- return false;
35
- }
36
- return operationNames.every(
37
- (operationName) => checkWebserviceAccess(operationName)
38
- );
39
- }
40
- const inferComponentType = (componentName) => {
41
- if (componentName.endsWith("Feature")) return "features";
42
- if (componentName.endsWith("Element")) return "elements";
43
- if (componentName.endsWith("Page")) return "pages";
44
- if (componentName.endsWith("Restricted")) return "restrictedFeatures";
45
- if (componentName.endsWith("Provider")) return "providers";
46
- throw new Error(
47
- `Cannot infer component type from "${componentName}". Component name must end with: Feature, Element, Page, Restricted, or Provider`
48
- );
49
- };
50
- const toTranslationKey = (componentName) => {
51
- return componentName.charAt(0).toLowerCase() + componentName.slice(1);
52
- };
53
- const createComponentTranslations = (componentName, translations, pathBase = "lys.components.") => {
54
- const componentType = inferComponentType(componentName);
55
- const translationKey = toTranslationKey(componentName);
56
- const translationPath = `${pathBase}${componentType}.${translationKey}`;
57
- return {
58
- /**
59
- * Configuration object for the i18n system
60
- * Export this in your features/elements/pages/restrictedFeatures index
61
- */
62
- config: {
63
- translation: translations
64
- },
65
- /**
66
- * React hook to use translations in your component
67
- * Returns an object with type-safe `t()` and `common()` functions
68
- *
69
- * @returns Object containing:
70
- * - t(key, values?): Component-specific translations with optional interpolation
71
- * - common(key, values?): Shared common translations with optional interpolation
72
- */
73
- useTranslations: () => {
74
- const intl = useIntl();
75
- return useMemo(() => {
76
- const t = (key, options) => {
77
- const id = `${translationPath}.${String(key)}`;
78
- const result = intl.formatMessage({ id }, options == null ? void 0 : options.values);
79
- if ((options == null ? void 0 : options.fallbackToKey) && result === id) {
80
- return String(key);
81
- }
82
- return result;
83
- };
84
- const common = (key, options) => {
85
- const id = `lys.services.i18n.common.${String(key)}`;
86
- const result = intl.formatMessage({ id }, options == null ? void 0 : options.values);
87
- if ((options == null ? void 0 : options.fallbackToKey) && result === id) {
88
- return String(key);
89
- }
90
- return result;
91
- };
92
- return { t, common };
93
- }, [intl]);
94
- },
95
- /**
96
- * Generated translation path (for debugging)
97
- */
98
- translationPath,
99
- /**
100
- * Available translation keys (for reference)
101
- */
102
- translationKeys: Object.keys(translations)
103
- };
104
- };
105
- export {
106
- cn as a,
107
- createComponentTranslations as b,
108
- checkOperationsPermission as c,
109
- extractOperationNames as e,
110
- lowerCaseFirstLetter as l,
111
- numberToString as n,
112
- toSnakeCase as t
113
- };
114
- //# sourceMappingURL=translationTools-CSKULpZZ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"translationTools-CSKULpZZ.js","sources":["../src/tools/stringTools.ts","../src/tools/relayTools.ts","../src/tools/translationTools.ts"],"sourcesContent":["/**\n * Convert first letter of string to lowercase\n */\nexport const lowerCaseFirstLetter = (str: string) => {\n return str.charAt(0).toLowerCase() + str.slice(1);\n}\n\n/**\n * Combine multiple classnames into a single string\n * Filters out falsy values\n */\nexport const cn = (...classes: (string | undefined | null | false)[]) => {\n return classes.filter(Boolean).join(' ');\n}\n\n/**\n * Convert camelCase string to snake_case\n */\nexport const toSnakeCase = (str: string): string => {\n return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);\n}\n\n/**\n * Convert number to string without scientific notation\n */\nexport const numberToString = (value: number | string | null | undefined): string => {\n if (value == null) return \"\";\n const num = typeof value === \"string\" ? parseFloat(value) : value;\n if (isNaN(num)) return \"\";\n return num.toLocaleString(\"fullwide\", {useGrouping: false, maximumFractionDigits: 20});\n}\n","import {GraphQLTaggedNode} from \"relay-runtime\";\n\n/**\n * Extract operation names from a GraphQL query or mutation\n * Used for permission checking based on webservice names\n */\nexport function extractOperationNames(node: GraphQLTaggedNode): string[] {\n const operationNames: string[] = [];\n\n if ('operation' in node && node.operation) {\n const operation = node.operation as unknown as Record<string, unknown>;\n if ('selections' in operation && Array.isArray(operation.selections)) {\n operation.selections.forEach((selection) => {\n if (selection && typeof selection === 'object' && 'name' in selection) {\n operationNames.push(selection.name as string);\n }\n });\n }\n }\n\n return operationNames;\n}\n\n/**\n * Check if user has permission to access all operations\n * Note: checkWebserviceAccess handles snake_case conversion internally\n */\nexport function checkOperationsPermission(\n operationNames: string[],\n checkWebserviceAccess: (name: string) => boolean\n): boolean {\n if (!operationNames.length) {\n return false;\n }\n\n return operationNames.every(operationName =>\n checkWebserviceAccess(operationName)\n );\n}\n","import {useMemo} from \"react\";\nimport {useIntl} from \"react-intl\";\nimport {ComponentDescriptionType} from \"../types/descriptionTypes\";\nimport {TranslationType} from \"../types/i18nTypes\";\nimport {I18nLocaleEnum} from \"../types/i18nTypes\";\n\n/**\n * Infers component type from component name based on naming convention\n * - ends with \"Feature\" -> \"features\"\n * - ends with \"Element\" -> \"elements\"\n * - ends with \"Page\" -> \"pages\"\n * - ends with \"Restricted\" -> \"restrictedFeatures\"\n * - ends with \"Provider\" -> \"providers\"\n */\nconst inferComponentType = (componentName: string): string => {\n if (componentName.endsWith(\"Feature\")) return \"features\";\n if (componentName.endsWith(\"Element\")) return \"elements\";\n if (componentName.endsWith(\"Page\")) return \"pages\";\n if (componentName.endsWith(\"Restricted\")) return \"restrictedFeatures\";\n if (componentName.endsWith(\"Provider\")) return \"providers\";\n\n throw new Error(\n `Cannot infer component type from \"${componentName}\". ` +\n `Component name must end with: Feature, Element, Page, Restricted, or Provider`\n );\n};\n\n/**\n * Converts component name to translation key format\n * LoginFeature -> loginFeature\n * ButtonElement -> buttonElement\n */\nconst toTranslationKey = (componentName: string): string => {\n return componentName.charAt(0).toLowerCase() + componentName.slice(1);\n};\n\n/**\n * Creates a component translation configuration with typed helper hook\n *\n * Supports all languages defined in I18nLocaleEnum. TypeScript will enforce\n * that all translations include every language.\n *\n * @param componentName - Component name (e.g., \"LoginFeature\", \"ButtonElement\")\n * @param translations - Translation object with keys in format {key: Record<I18nLocaleEnum, string>}\n * @param pathBase - Base path for translations (default: \"lys.components.\")\n * @returns Object with config for i18n system and useTranslations hook\n *\n * @example\n * ```typescript\n * // In LoginFeature/translations.ts\n * const {config, useTranslations} = createComponentTranslations(\n * \"LoginFeature\",\n * {\n * email: {en: \"Email\", fr: \"Email\"},\n * password: {en: \"Password\", fr: \"Mot de passe\"}\n * }\n * );\n *\n * export const loginFeatureConfig = config;\n * export const useLoginTranslations = useTranslations;\n *\n * // In LoginFeature/index.tsx\n * const {t} = useLoginTranslations();\n * const label = t(\"email\"); // Type-safe!\n * ```\n */\nexport const createComponentTranslations = <\n T extends Record<string, Record<I18nLocaleEnum, string>>,\n TCommonKey extends string = string\n>(\n componentName: string,\n translations: T,\n pathBase: string = \"lys.components.\"\n) => {\n const componentType = inferComponentType(componentName);\n const translationKey = toTranslationKey(componentName);\n const translationPath = `${pathBase}${componentType}.${translationKey}`;\n\n return {\n /**\n * Configuration object for the i18n system\n * Export this in your features/elements/pages/restrictedFeatures index\n */\n config: {\n translation: translations as TranslationType\n } satisfies ComponentDescriptionType,\n\n /**\n * React hook to use translations in your component\n * Returns an object with type-safe `t()` and `common()` functions\n *\n * @returns Object containing:\n * - t(key, values?): Component-specific translations with optional interpolation\n * - common(key, values?): Shared common translations with optional interpolation\n */\n useTranslations: () => {\n const intl = useIntl();\n\n return useMemo(() => {\n /**\n * Translate a component-specific key\n * @param key - Translation key (autocompleted)\n * @param options - Optional: values for interpolation, fallbackToKey to return raw key if not found\n */\n const t = (key: keyof T, options?: {\n values?: Record<string, string | number>,\n fallbackToKey?: boolean\n }): string => {\n const id = `${translationPath}.${String(key)}`;\n const result = intl.formatMessage({id}, options?.values);\n if (options?.fallbackToKey && result === id) {\n return String(key);\n }\n return result;\n };\n\n /**\n * Translate a common/shared key\n * @param key - Common translation key (autocompleted)\n * @param options - Optional: values for interpolation, fallbackToKey to return raw key if not found\n */\n const common = (key: TCommonKey, options?: {\n values?: Record<string, string | number>,\n fallbackToKey?: boolean\n }): string => {\n const id = `lys.services.i18n.common.${String(key)}`;\n const result = intl.formatMessage({id}, options?.values);\n if (options?.fallbackToKey && result === id) {\n return String(key);\n }\n return result;\n };\n\n return {t, common};\n }, [intl]);\n },\n\n /**\n * Generated translation path (for debugging)\n */\n translationPath,\n\n /**\n * Available translation keys (for reference)\n */\n translationKeys: Object.keys(translations) as Array<keyof T>\n };\n};\n"],"names":[],"mappings":"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"}