opengrammar-server 2.0.644277

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.
Files changed (53) hide show
  1. package/README.npm.md +95 -0
  2. package/bin/opengrammar-server.js +111 -0
  3. package/dist/server.js +48639 -0
  4. package/package.json +80 -0
  5. package/server-node.ts +159 -0
  6. package/server.ts +15 -0
  7. package/src/analyzer.ts +542 -0
  8. package/src/dictionary.ts +1973 -0
  9. package/src/index.ts +978 -0
  10. package/src/nlp/nlp-engine.ts +17 -0
  11. package/src/nlp/tone-analyzer.ts +269 -0
  12. package/src/rephraser.ts +146 -0
  13. package/src/rules/categories/academic-writing.ts +182 -0
  14. package/src/rules/categories/adjectives-adverbs.ts +152 -0
  15. package/src/rules/categories/articles.ts +160 -0
  16. package/src/rules/categories/business-writing.ts +250 -0
  17. package/src/rules/categories/capitalization.ts +79 -0
  18. package/src/rules/categories/clarity.ts +117 -0
  19. package/src/rules/categories/common-errors.ts +601 -0
  20. package/src/rules/categories/confused-words.ts +219 -0
  21. package/src/rules/categories/conjunctions.ts +176 -0
  22. package/src/rules/categories/dangling-modifiers.ts +123 -0
  23. package/src/rules/categories/formality.ts +274 -0
  24. package/src/rules/categories/formatting-idioms.ts +323 -0
  25. package/src/rules/categories/gerund-infinitive.ts +274 -0
  26. package/src/rules/categories/grammar-advanced.ts +294 -0
  27. package/src/rules/categories/grammar.ts +286 -0
  28. package/src/rules/categories/inclusive-language.ts +280 -0
  29. package/src/rules/categories/nouns-pronouns.ts +233 -0
  30. package/src/rules/categories/prepositions-extended.ts +217 -0
  31. package/src/rules/categories/prepositions.ts +159 -0
  32. package/src/rules/categories/punctuation.ts +347 -0
  33. package/src/rules/categories/quantity-agreement.ts +200 -0
  34. package/src/rules/categories/readability.ts +293 -0
  35. package/src/rules/categories/sentence-structure.ts +100 -0
  36. package/src/rules/categories/spelling-advanced.ts +164 -0
  37. package/src/rules/categories/spelling.ts +119 -0
  38. package/src/rules/categories/style-tone.ts +511 -0
  39. package/src/rules/categories/style.ts +78 -0
  40. package/src/rules/categories/subject-verb-agreement.ts +201 -0
  41. package/src/rules/categories/tone-rules.ts +206 -0
  42. package/src/rules/categories/verb-tense.ts +582 -0
  43. package/src/rules/context-filter.ts +446 -0
  44. package/src/rules/index.ts +96 -0
  45. package/src/rules/ruleset-part1-cj-pu-sp.json +657 -0
  46. package/src/rules/ruleset-part1-np-ad-aa-pr.json +831 -0
  47. package/src/rules/ruleset-part1-ss-vt.json +907 -0
  48. package/src/rules/ruleset-part2-cw-st-nf.json +318 -0
  49. package/src/rules/ruleset-part3-aw-bw-il-rd.json +161 -0
  50. package/src/rules/types.ts +79 -0
  51. package/src/shared-types.ts +152 -0
  52. package/src/spellchecker.ts +418 -0
  53. package/tsconfig.json +25 -0
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "opengrammar-server",
3
+ "version": "2.0.644277",
4
+ "description": "Privacy-first, open-source grammar intelligence server — run it on any device",
5
+ "homepage": "https://opengrammer.eu.cc",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/swadhinbiswas/opengrammar.git"
9
+ },
10
+ "bugs": {
11
+ "url": "https://github.com/swadhinbiswas/opengrammar/issues"
12
+ },
13
+ "license": "MIT",
14
+ "author": "Swadhin Biswas",
15
+ "keywords": [
16
+ "grammar",
17
+ "grammar-checker",
18
+ "nlp",
19
+ "spell-check",
20
+ "writing",
21
+ "hono",
22
+ "edge",
23
+ "api",
24
+ "server",
25
+ "opengrammar"
26
+ ],
27
+ "type": "module",
28
+ "main": "dist/server.js",
29
+ "bin": {
30
+ "opengrammar-server": "bin/opengrammar-server.js",
31
+ "opengrammar": "bin/opengrammar-server.js"
32
+ },
33
+ "files": [
34
+ "bin/",
35
+ "dist/",
36
+ "src/",
37
+ "server.ts",
38
+ "server-node.ts",
39
+ "tsconfig.json",
40
+ "README.npm.md"
41
+ ],
42
+ "scripts": {
43
+ "dev": "bun --hot server-bun.ts",
44
+ "start": "bun server-bun.ts",
45
+ "dev:node": "tsx watch server-node.ts",
46
+ "start:node": "tsx server-node.ts",
47
+ "build": "bun build server.ts --outdir dist --target node --format esm",
48
+ "build:check": "tsc --noEmit",
49
+ "prepublishOnly": "npm run build:check && npm run build",
50
+ "deploy": "wrangler deploy --env production",
51
+ "deploy:vercel": "vercel --prod",
52
+ "deploy:render": "git push render main",
53
+ "deploy:railway": "railway up",
54
+ "test": "bun test"
55
+ },
56
+ "dependencies": {
57
+ "@hono/node-server": "^1.19.9",
58
+ "@hono/zod-validator": "^0.7.6",
59
+ "compromise": "^14.15.0",
60
+ "groq-sdk": "^0.5.0",
61
+ "hono": "^4.11.10",
62
+ "openai": "^4.22.0",
63
+ "zod": "^3.25.76"
64
+ },
65
+ "devDependencies": {
66
+ "@cloudflare/workers-types": "^4.20260219.0",
67
+ "@netlify/functions": "^5.1.5",
68
+ "@types/bun": "^1.3.10",
69
+ "@types/node": "^25.3.0",
70
+ "tsx": "^4.21.0",
71
+ "typescript": "^5.9.3",
72
+ "wrangler": "^4.66.0"
73
+ },
74
+ "engines": {
75
+ "node": ">=18.0.0"
76
+ },
77
+ "publishConfig": {
78
+ "access": "public"
79
+ }
80
+ }
package/server-node.ts ADDED
@@ -0,0 +1,159 @@
1
+ import { serve } from '@hono/node-server';
2
+ import { Hono } from 'hono';
3
+ import { cors } from 'hono/cors';
4
+ import { logger } from 'hono/logger';
5
+ import { RuleBasedAnalyzer } from './src/analyzer.js';
6
+ import { PROVIDERS } from './src/shared-types.js';
7
+
8
+ const app = new Hono();
9
+
10
+ // Middleware
11
+ app.use('/*', logger());
12
+ app.use('/*', cors());
13
+
14
+ // Health check endpoint
15
+ app.get('/health', (c) => {
16
+ return c.json({
17
+ status: 'healthy',
18
+ timestamp: new Date().toISOString(),
19
+ environment: 'nodejs',
20
+ version: '2.0.0',
21
+ });
22
+ });
23
+
24
+ // List available providers
25
+ app.get('/providers', (c) => {
26
+ return c.json({
27
+ providers: PROVIDERS,
28
+ });
29
+ });
30
+
31
+ // Get models for a provider
32
+ app.post('/models', async (c) => {
33
+ try {
34
+ const { provider } = await c.req.json().catch(() => ({}));
35
+ const providerConfig = PROVIDERS.find((p) => p.id === provider);
36
+ return c.json({
37
+ provider,
38
+ models: providerConfig?.models || [],
39
+ });
40
+ } catch (error) {
41
+ console.error('Failed to fetch models:', error);
42
+ return c.json({ models: [] });
43
+ }
44
+ });
45
+
46
+ // Main analysis endpoint - rule-based only (fast and reliable)
47
+ app.post('/analyze', async (c) => {
48
+ const startTime = Date.now();
49
+
50
+ try {
51
+ const body = await c.req.json();
52
+ const { text, dictionary } = body;
53
+
54
+ // Validate input
55
+ if (!text || typeof text !== 'string') {
56
+ return c.json({ error: 'Invalid request: text is required' }, 400);
57
+ }
58
+
59
+ if (text.length > 50000) {
60
+ return c.json({ error: 'Text exceeds maximum length of 50,000 characters' }, 413);
61
+ }
62
+
63
+ console.log(`[Analyze] Text length: ${text.length}`);
64
+
65
+ // Run rule-based analysis
66
+ const issues = RuleBasedAnalyzer.analyze(text, {
67
+ dictionary: dictionary || [],
68
+ });
69
+
70
+ const duration = Date.now() - startTime;
71
+
72
+ console.log(`[Analyze] Found ${issues.length} issues in ${duration}ms`);
73
+
74
+ return c.json({
75
+ issues,
76
+ metadata: {
77
+ textLength: text.length,
78
+ issuesCount: issues.length,
79
+ processingTimeMs: duration,
80
+ },
81
+ });
82
+ } catch (error) {
83
+ console.error('Analysis error:', error);
84
+ return c.json(
85
+ {
86
+ error: 'Failed to analyze text',
87
+ message: error instanceof Error ? error.message : 'Unknown error',
88
+ issues: [],
89
+ },
90
+ 500,
91
+ );
92
+ }
93
+ });
94
+
95
+ // Tone rewriting endpoint (requires API key)
96
+ app.post('/rewrite', async (c) => {
97
+ try {
98
+ const { text, tone, apiKey } = await c.req.json();
99
+
100
+ if (!text || !tone) {
101
+ return c.json({ error: 'Text and tone are required' }, 400);
102
+ }
103
+
104
+ if (!apiKey) {
105
+ return c.json({
106
+ error: 'API key required for rewriting',
107
+ original: text,
108
+ rewritten: text,
109
+ tone,
110
+ });
111
+ }
112
+
113
+ // LLM rewriting would go here
114
+ return c.json({
115
+ original: text,
116
+ rewritten: text,
117
+ tone,
118
+ });
119
+ } catch (error) {
120
+ console.error('Rewrite error:', error);
121
+ return c.json(
122
+ {
123
+ error: 'Failed to rewrite text',
124
+ message: error instanceof Error ? error.message : 'Unknown error',
125
+ },
126
+ 500,
127
+ );
128
+ }
129
+ });
130
+
131
+ // Error handler
132
+ app.onError((err, c) => {
133
+ console.error('Unhandled error:', err);
134
+ return c.json(
135
+ {
136
+ error: 'Internal server error',
137
+ message: err.message,
138
+ },
139
+ 500,
140
+ );
141
+ });
142
+
143
+ // 404 handler
144
+ app.notFound((c) => {
145
+ return c.json({ error: 'Not found' }, 404);
146
+ });
147
+
148
+ const port = 8787;
149
+ console.log(`\n🪶 OpenGrammar Backend starting on http://localhost:${port}\n`);
150
+
151
+ serve(
152
+ {
153
+ fetch: app.fetch,
154
+ port,
155
+ },
156
+ (info) => {
157
+ console.log(`āœ… Server ready on http://localhost:${info.port}`);
158
+ },
159
+ );
package/server.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { serve } from '@hono/node-server';
2
+ import app from './src/index.js';
3
+
4
+ const port = parseInt(process.env.PORT || '8787', 10);
5
+ const host = process.env.HOST || '0.0.0.0';
6
+
7
+ serve(
8
+ { fetch: app.fetch, port, hostname: host },
9
+ (info) => {
10
+ console.log(` āœ… OpenGrammar ready → http://${info.address}:${info.port}`);
11
+ console.log(` šŸ“Š Dashboard → http://${info.address}:${info.port}/`);
12
+ console.log(` ā¤ļø Health → http://${info.address}:${info.port}/health`);
13
+ console.log(` šŸ” Analyze → POST http://${info.address}:${info.port}/analyze\n`);
14
+ },
15
+ );