@seedgrid/fe-core 0.2.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/dist/i18n.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export type SeedGridLocale = "pt-BR";
2
+ export type SeedGridMessages = Record<string, Record<string, string>>;
3
+ export declare function mergeMessages(target: SeedGridMessages, add: SeedGridMessages): SeedGridMessages;
4
+ //# sourceMappingURL=i18n.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,OAAO,CAAC;AAErC,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEtE,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,gBAAgB,GAAG,gBAAgB,CAM/F"}
package/dist/i18n.js ADDED
@@ -0,0 +1,7 @@
1
+ export function mergeMessages(target, add) {
2
+ const out = { ...target };
3
+ for (const ns of Object.keys(add)) {
4
+ out[ns] = { ...(out[ns] ?? {}), ...(add[ns] ?? {}) };
5
+ }
6
+ return out;
7
+ }
@@ -0,0 +1,5 @@
1
+ export * from "./module";
2
+ export * from "./registry";
3
+ export * from "./i18n";
4
+ export * from "./persistence";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ export * from "./module";
2
+ export * from "./registry";
3
+ export * from "./i18n";
4
+ export * from "./persistence";
@@ -0,0 +1,34 @@
1
+ import type React from "react";
2
+ export type SeedGridModuleId = string;
3
+ export type SeedGridProvider = React.ComponentType<{
4
+ children: React.ReactNode;
5
+ }>;
6
+ export type SeedGridNavItem = {
7
+ id: string;
8
+ labelKey: string;
9
+ href: string;
10
+ icon?: string;
11
+ requiresAuth?: boolean;
12
+ order?: number;
13
+ };
14
+ export type SeedGridRoute = {
15
+ id: string;
16
+ path: string;
17
+ requiresAuth?: boolean;
18
+ };
19
+ export type SeedGridI18nBundle = {
20
+ namespace: string;
21
+ resources: Record<string, string>;
22
+ distPath?: string;
23
+ };
24
+ export type SeedGridModuleManifest = {
25
+ id: SeedGridModuleId;
26
+ name: string;
27
+ version: string;
28
+ i18n?: {
29
+ defaultLocale: "pt-BR";
30
+ bundles: SeedGridI18nBundle[];
31
+ };
32
+ register: (registry: import("./registry").SeedGridRegistry) => void;
33
+ };
34
+ //# sourceMappingURL=module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC,MAAM,MAAM,gBAAgB,GAAG,KAAK,CAAC,aAAa,CAAC;IACjD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,CAAC,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,EAAE,EAAE,gBAAgB,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QACL,aAAa,EAAE,OAAO,CAAC;QACvB,OAAO,EAAE,kBAAkB,EAAE,CAAC;KAC/B,CAAC;IACF,QAAQ,EAAE,CAAC,QAAQ,EAAE,OAAO,YAAY,EAAE,gBAAgB,KAAK,IAAI,CAAC;CACrE,CAAC"}
package/dist/module.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,44 @@
1
+ export type NamespaceProvider = {
2
+ getNamespace: () => string | null;
3
+ };
4
+ export type PersistenceStrategy = {
5
+ load: (key: string) => unknown | Promise<unknown>;
6
+ save: (key: string, state: unknown) => void | Promise<void>;
7
+ clear: (key: string) => void | Promise<void>;
8
+ };
9
+ export type SgPersistenceRecordDTO = {
10
+ protocolVersion: 1;
11
+ key: string;
12
+ scope: string;
13
+ stateVersion: number;
14
+ updatedAt: string;
15
+ state: unknown;
16
+ };
17
+ export type SgPersistenceMode = "strict" | "fallback" | "mirror";
18
+ export type SgPersistenceConfig = {
19
+ scope: string;
20
+ mode: SgPersistenceMode;
21
+ stateVersion: number;
22
+ };
23
+ export type SgEnvironmentValue = {
24
+ namespaceProvider: NamespaceProvider;
25
+ persistenceStrategy: PersistenceStrategy;
26
+ persistence: SgPersistenceConfig;
27
+ };
28
+ export type SgEnvironment = SgEnvironmentValue;
29
+ export declare function buildSgPersistenceKey(baseKey: string, namespace?: string | null, scope?: string | null): string | null;
30
+ export declare function createLocalStorageStrategy(options?: {
31
+ prefix?: string;
32
+ }): PersistenceStrategy;
33
+ export declare function createApiPersistenceStrategy(args: {
34
+ baseUrl: string;
35
+ fetcher?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
36
+ scope: string;
37
+ stateVersion: number;
38
+ }): PersistenceStrategy;
39
+ export declare function createCompositePersistenceStrategy(args: {
40
+ mode: SgPersistenceMode;
41
+ primary: PersistenceStrategy;
42
+ secondary: PersistenceStrategy;
43
+ }): PersistenceStrategy;
44
+ //# sourceMappingURL=persistence.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"persistence.d.ts","sourceRoot":"","sources":["../src/persistence.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,GAAG;IAC9B,YAAY,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,eAAe,EAAE,CAAC,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,QAAQ,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEjE,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,iBAAiB,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,WAAW,EAAE,mBAAmB,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC;AAI/C,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,iBAMtG;AAED,wBAAgB,0BAA0B,CAAC,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,mBAAmB,CA4B7F;AAED,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,WAAW,GAAG,GAAG,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB,GAAG,mBAAmB,CAuCtB;AAED,wBAAgB,kCAAkC,CAAC,IAAI,EAAE;IACvD,IAAI,EAAE,iBAAiB,CAAC;IACxB,OAAO,EAAE,mBAAmB,CAAC;IAC7B,SAAS,EAAE,mBAAmB,CAAC;CAChC,GAAG,mBAAmB,CA4DtB"}
@@ -0,0 +1,152 @@
1
+ /* ─── Persistence types ─── */
2
+ /* ─── Pure functions ─── */
3
+ export function buildSgPersistenceKey(baseKey, namespace, scope) {
4
+ const resolved = namespace ?? "";
5
+ if (!resolved)
6
+ return null;
7
+ const resolvedScope = (scope ?? "").trim();
8
+ if (!resolvedScope)
9
+ return `sg:${resolved}:${baseKey}`;
10
+ return `sg:${resolved}:${resolvedScope}:${baseKey}`;
11
+ }
12
+ export function createLocalStorageStrategy(options) {
13
+ const prefix = options?.prefix ?? "";
14
+ const full = (key) => (prefix ? `${prefix}${key}` : key);
15
+ return {
16
+ load: (key) => {
17
+ try {
18
+ const raw = window.localStorage.getItem(full(key));
19
+ if (raw == null)
20
+ return null;
21
+ return JSON.parse(raw);
22
+ }
23
+ catch {
24
+ return null;
25
+ }
26
+ },
27
+ save: (key, state) => {
28
+ try {
29
+ window.localStorage.setItem(full(key), JSON.stringify(state));
30
+ }
31
+ catch {
32
+ // ignore
33
+ }
34
+ },
35
+ clear: (key) => {
36
+ try {
37
+ window.localStorage.removeItem(full(key));
38
+ }
39
+ catch {
40
+ // ignore
41
+ }
42
+ }
43
+ };
44
+ }
45
+ export function createApiPersistenceStrategy(args) {
46
+ const fetcher = args.fetcher ?? fetch;
47
+ const base = args.baseUrl.replace(/\/$/, "");
48
+ const version = args.stateVersion;
49
+ const scope = args.scope;
50
+ return {
51
+ load: async (key) => {
52
+ const res = await fetcher(`${base}/sg/persistence?key=${encodeURIComponent(key)}`, {
53
+ method: "GET"
54
+ });
55
+ if (!res.ok)
56
+ throw new Error(`SG persistence load failed (${res.status})`);
57
+ const data = (await res.json());
58
+ if (!data?.found || !data.record)
59
+ return null;
60
+ return data.record.state;
61
+ },
62
+ save: async (key, state) => {
63
+ const record = {
64
+ protocolVersion: 1,
65
+ key,
66
+ scope,
67
+ stateVersion: version,
68
+ updatedAt: new Date().toISOString(),
69
+ state
70
+ };
71
+ const res = await fetcher(`${base}/sg/persistence`, {
72
+ method: "POST",
73
+ headers: { "Content-Type": "application/json" },
74
+ body: JSON.stringify({ record })
75
+ });
76
+ if (!res.ok)
77
+ throw new Error(`SG persistence save failed (${res.status})`);
78
+ },
79
+ clear: async (key) => {
80
+ const res = await fetcher(`${base}/sg/persistence?key=${encodeURIComponent(key)}`, {
81
+ method: "DELETE"
82
+ });
83
+ if (!res.ok)
84
+ throw new Error(`SG persistence clear failed (${res.status})`);
85
+ }
86
+ };
87
+ }
88
+ export function createCompositePersistenceStrategy(args) {
89
+ const { mode, primary, secondary } = args;
90
+ return {
91
+ load: async (key) => {
92
+ if (mode === "strict") {
93
+ return await primary.load(key);
94
+ }
95
+ if (mode === "mirror") {
96
+ try {
97
+ const remote = await primary.load(key);
98
+ if (remote !== null && remote !== undefined)
99
+ return remote;
100
+ }
101
+ catch {
102
+ // ignore and fallback
103
+ }
104
+ return await secondary.load(key);
105
+ }
106
+ try {
107
+ return await primary.load(key);
108
+ }
109
+ catch {
110
+ return await secondary.load(key);
111
+ }
112
+ },
113
+ save: async (key, state) => {
114
+ if (mode === "strict") {
115
+ await primary.save(key, state);
116
+ return;
117
+ }
118
+ if (mode === "mirror") {
119
+ await Promise.allSettled([
120
+ Promise.resolve(primary.save(key, state)),
121
+ Promise.resolve(secondary.save(key, state))
122
+ ]);
123
+ return;
124
+ }
125
+ try {
126
+ await primary.save(key, state);
127
+ }
128
+ catch {
129
+ await secondary.save(key, state);
130
+ }
131
+ },
132
+ clear: async (key) => {
133
+ if (mode === "strict") {
134
+ await primary.clear(key);
135
+ return;
136
+ }
137
+ if (mode === "mirror") {
138
+ await Promise.allSettled([
139
+ Promise.resolve(primary.clear(key)),
140
+ Promise.resolve(secondary.clear(key))
141
+ ]);
142
+ return;
143
+ }
144
+ try {
145
+ await primary.clear(key);
146
+ }
147
+ catch {
148
+ await secondary.clear(key);
149
+ }
150
+ }
151
+ };
152
+ }
@@ -0,0 +1,13 @@
1
+ import type { SeedGridNavItem, SeedGridProvider, SeedGridRoute } from "./module";
2
+ export declare class SeedGridRegistry {
3
+ private providers;
4
+ private navItems;
5
+ private routes;
6
+ addProvider(provider: SeedGridProvider): void;
7
+ addNavItem(item: SeedGridNavItem): void;
8
+ addRoute(route: SeedGridRoute): void;
9
+ getProviders(): SeedGridProvider[];
10
+ getNavItems(): SeedGridNavItem[];
11
+ getRoutes(): SeedGridRoute[];
12
+ }
13
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEjF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,MAAM,CAAuB;IAErC,WAAW,CAAC,QAAQ,EAAE,gBAAgB;IAItC,UAAU,CAAC,IAAI,EAAE,eAAe;IAIhC,QAAQ,CAAC,KAAK,EAAE,aAAa;IAI7B,YAAY;IAIZ,WAAW;IAIX,SAAS;CAGV"}
@@ -0,0 +1,23 @@
1
+ export class SeedGridRegistry {
2
+ providers = [];
3
+ navItems = [];
4
+ routes = [];
5
+ addProvider(provider) {
6
+ this.providers.push(provider);
7
+ }
8
+ addNavItem(item) {
9
+ this.navItems.push(item);
10
+ }
11
+ addRoute(route) {
12
+ this.routes.push(route);
13
+ }
14
+ getProviders() {
15
+ return [...this.providers];
16
+ }
17
+ getNavItems() {
18
+ return [...this.navItems].sort((a, b) => (a.order ?? 999) - (b.order ?? 999));
19
+ }
20
+ getRoutes() {
21
+ return [...this.routes];
22
+ }
23
+ }
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@seedgrid/fe-core",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "default": "./dist/index.js"
11
+ }
12
+ },
13
+ "files": ["dist"],
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json",
16
+ "typecheck": "tsc -p tsconfig.json --noEmit"
17
+ },
18
+ "peerDependencies": {
19
+ "react": "^18.2.0 || ^19.0.0"
20
+ },
21
+ "devDependencies": {
22
+ "@types/react": "^19.0.0"
23
+ }
24
+ }